├── .gitattributes ├── .gitignore ├── Chapter01 ├── 1_10_reuse_socket_address.py ├── 1_11_print_machine_time.py ├── 1_12_sntp_client.py ├── 1_13a_echo_server.py ├── 1_13b_echo_client.py ├── 1_14a_echo_server_udp.py ├── 1_14b_echo_client_udp.py ├── 1_1_local_machine_info.py ├── 1_2_remote_machine_info.py ├── 1_3_ip4_address_conversion.py ├── 1_4_finding_service_name.py ├── 1_5_integer_conversion.py ├── 1_6_socket_timeout.py ├── 1_7_socket_errors.py ├── 1_8_modify_buff_size.py ├── 1_9_socket_modes.py └── __init__.py ├── Chapter02 ├── 2_1_forking_mixin_socket_server.py ├── 2_1_forking_mixin_socket_server2.py ├── 2_2_threading_mixin_socket_server.py ├── 2_3_chat_server_with_select.py ├── 2_4_simple_web_server_with_epoll.py ├── 2_5_echo_server_with_diesel.py └── __init__.py ├── Chapter03 ├── 3_10_check_ipv6_support.py ├── 3_11_extract_ipv6_prefix.py ├── 3_12a_ipv6_echo_server.py ├── 3_12b_ipv6_echo_client.py ├── 3_1_port_forwarding.py ├── 3_2_ping_remote_host.py ├── 3_3_wait_for_remote_service.py ├── 3_4_list_network_interfaces.py ├── 3_5_get_interface_ip_address.py ├── 3_6_find_network_interface_status.py ├── 3_7_detect_inactive_machines.py ├── 3_8_ipc_using_socketpairs.py ├── 3_9a_unix_domain_socket_server.py ├── 3_9b_unix_domain_socket_client.py └── __init__.py ├── Chapter04 ├── 4_10_https_server.py ├── 4_11_twisted_async_server.py ├── 4_12_tornado_async_server.py ├── 4_13_tornado_conc_future.py ├── 4_1_download_data.py ├── 4_2_simple_http_server.py ├── 4_3_extract_cookie_information.py ├── 4_4_submit_web_form.py ├── 4_5_proxy_web_request.py ├── 4_6_checking_webpage_with_HEAD_request.py ├── 4_7_spoof_mozilla_firefox_in_client_code.py ├── 4_8_http_compression.py ├── 4_9_http_fail_over_client.py └── __init__.py ├── Chapter05 ├── 5_10_secure_mail_client.py ├── 5_11_pop3_mail_client.py ├── 5_1_list_files_on_ftp_server.py ├── 5_2_upload_file_to_ftp_server.py ├── 5_3_email_current_dir_zipped.py ├── 5_4_download_google_email_via_pop3.py ├── 5_5_check_remote_email_via_imap.py ├── 5_6_send_email_from_gmail.py ├── 5_7_cgi_server.py ├── 5_7_send_feedback.html ├── 5_8_verify_email.py ├── 5_9a_mail_server.py ├── 5_9b_mail_client.py ├── __init__.py ├── cgi-bin │ └── 5_7_get_feedback.py ├── python-logo.gif └── readme.txt ├── Chapter06 ├── 6_1_execute_remote_telnet_cmd.py ├── 6_2_copy_remote_file_over_sftp.py ├── 6_3_print_remote_cpu_info.py ├── 6_4_install_python_package_remotely.py ├── 6_5_run_mysql_command_remotely.py ├── 6_6_transfer_file_over_ssh.py ├── 6_7_configure_Apache_for_hosting_website_remotely.py ├── __init__.py ├── fabfile.py ├── index.html ├── op.txt ├── test.txt └── vhost.conf ├── Chapter07 ├── 7_1_query_supervisord_xmlrpc_server.py ├── 7_2_multithreaded_multicall_xmlrpc_server.py ├── 7_3a_xmlrpc_server_with_http_auth.py ├── 7_3b_xmprpc_client.py ├── 7_4_get_flickr_photo_info.py ├── 7_5_search_amazonaws_with_soap.py ├── 7_6_search_amazon_for_books.py ├── 7_7_create_restful_webservice.py ├── __init__.py ├── local_settings.py ├── local_settings.pyc └── supervisord.conf ├── Chapter08 ├── 8_1_packet_sniffer.py ├── 8_2_save_packets_in_pcap_format.py ├── 8_3_add_an_extra_header_in_http_packet.py ├── 8_4_scan_port_of_a_remote_host.py ├── 8_5_modify_ip_in_a_packet.py ├── 8_6_replay_traffic.py ├── 8_7_broadcast_scanning.py └── __init__.py ├── Chapter09 ├── 9_1_ns3_simulation.py ├── 9_2_mininet_emulation.py ├── 9_3_maxinet_emulation.py ├── 9_4_mininet_wifi_emulation.py ├── 9_5_containernet_emulation.py └── __init__.py ├── Chapter10 ├── 10_1_sdn_mininet_emulation.py ├── 10_2_sdn_opendaylight.py ├── 10_3.mn ├── 10_3_sdn_onos.py ├── 10_4_sdn_floodlight.py ├── 10_5_sdn_ryu.py ├── 10_6_sdn_pox.py ├── 10_7_sdn_miniedit.mn ├── 10_7_sdn_miniedit.py ├── __init__.py ├── __pycache__ │ └── 10_5_sdn_ryu.cpython-35.pyc └── miniedit.py ├── Chapter11 ├── 11_10_requests_throttling.py ├── 11_10_requests_throttling.sh ├── 11_1_dns_names_with_dnspython.py ├── 11_2_dns_host_with_dnspython.py ├── 11_3_find_dns_rr_details.py ├── 11_4_dns_zone_transfer.py ├── 11_5_query_ntp_server.py ├── 11_6_connect_ldap_server.py ├── 11_6_output_with_ipa.demo1.freeipa.org.txt ├── 11_6_output_with_ldap.forumsys.com.txt ├── 11_7_query_ldap_server.py ├── 11_7_query_ldap_server_b.py ├── 11_8_read_ldap_server.py ├── 11_9_eve_basic_auth.py └── settings.py ├── Chapter12 ├── 12_1_configure_red_pnda_output ├── 12_4_open_contrail_control_node.sh ├── 12_5_open_contrail_analytics_node.sh ├── 12_5_open_contrail_compute_node.sh ├── 12_5_open_contrail_configuration_node.sh ├── 12_7_cisco_spark_api.py ├── etc │ ├── contrail │ │ ├── contrail-analytics-api.conf │ │ ├── contrail-collector.conf │ │ ├── contrail-query-engine.conf │ │ ├── contrail-vrouter-agent.conf │ │ └── control-node.conf │ └── network │ │ └── interfaces └── nsx.ini ├── Chapter13 ├── 13_1_quickstart.sh ├── 13_2_quickstart.sh ├── 13_3_install.sh ├── 13_3_quickstart.sh ├── 13_3_snas_log_consumer.py ├── 13_4_dronekit_sitl_simulation.py ├── 13_5_pnda_aws_setup.sh ├── config.yaml └── pnda_env.yaml ├── Chapter14 ├── 14_1_healthcheck.py ├── 14_2_benchmark_with_bgperf │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── base.py │ ├── bgperf.py │ ├── bird.py │ ├── docs │ │ ├── benchmark_remote_target.md │ │ ├── bgperf.jpg │ │ ├── bgperf_remote.jpg │ │ ├── how_bgperf_works.md │ │ └── mrt.md │ ├── exabgp.py │ ├── gobgp.py │ ├── monitor.py │ ├── mrt_tester.py │ ├── pip-requirements.txt │ ├── quagga.py │ ├── settings.py │ └── tester.py └── __init__.py ├── LICENSE └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /Chapter01/1_10_reuse_socket_address.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 1 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import socket 7 | import sys 8 | 9 | 10 | def reuse_socket_addr(): 11 | sock = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) 12 | 13 | # Get the old state of the SO_REUSEADDR option 14 | old_state = sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR ) 15 | print ("Old sock state: %s" %old_state) 16 | 17 | # Enable the SO_REUSEADDR option 18 | sock.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 ) 19 | new_state = sock.getsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR ) 20 | print ("New sock state: %s" %new_state) 21 | 22 | local_port = 8282 23 | 24 | srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 25 | srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 26 | srv.bind( ('', local_port) ) 27 | srv.listen(1) 28 | print ("Listening on port: %s " %local_port) 29 | while True: 30 | try: 31 | connection, addr = srv.accept() 32 | print ('Connected by %s:%s' % (addr[0], addr[1])) 33 | except KeyboardInterrupt: 34 | break 35 | except socket.error as msg: 36 | print ('%s' % (msg,)) 37 | 38 | 39 | if __name__ == '__main__': 40 | reuse_socket_addr() 41 | -------------------------------------------------------------------------------- /Chapter01/1_11_print_machine_time.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 1 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import ntplib 7 | from time import ctime 8 | 9 | 10 | def print_time(): 11 | ntp_client = ntplib.NTPClient() 12 | response = ntp_client.request('pool.ntp.org') 13 | print (ctime(response.tx_time)) 14 | 15 | 16 | if __name__ == '__main__': 17 | print_time() 18 | -------------------------------------------------------------------------------- /Chapter01/1_12_sntp_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 1 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | import socket 8 | import struct 9 | import sys 10 | import time 11 | 12 | NTP_SERVER = "0.uk.pool.ntp.org" 13 | TIME1970 = 2208988800 14 | 15 | def sntp_client(): 16 | client = socket.socket( socket.AF_INET, socket.SOCK_DGRAM ) 17 | data = '\x1b' + 47 * '\0' 18 | client.sendto( data.encode('utf-8'), ( NTP_SERVER, 123 )) 19 | data, address = client.recvfrom( 1024 ) 20 | if data: 21 | print ('Response received from:', address) 22 | t = struct.unpack( '!12I', data )[10] 23 | t -= TIME1970 24 | print ('\tTime=%s' % time.ctime(t)) 25 | 26 | 27 | if __name__ == '__main__': 28 | sntp_client() 29 | -------------------------------------------------------------------------------- /Chapter01/1_13a_echo_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 1 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | import socket 8 | import sys 9 | import argparse 10 | 11 | host = 'localhost' 12 | data_payload = 2048 13 | backlog = 5 14 | 15 | 16 | def echo_server(port): 17 | """ A simple echo server """ 18 | # Create a TCP socket 19 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 20 | # Enable reuse address/port 21 | sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 22 | # Bind the socket to the port 23 | server_address = (host, port) 24 | print ("Starting up echo server on %s port %s" % server_address) 25 | sock.bind(server_address) 26 | # Listen to clients, backlog argument specifies the max no. of queued connections 27 | sock.listen(backlog) 28 | while True: 29 | print ("Waiting to receive message from client") 30 | client, address = sock.accept() 31 | data = client.recv(data_payload) 32 | if data: 33 | print ("Data: %s" %data) 34 | client.send(data) 35 | print ("sent %s bytes back to %s" % (data, address)) 36 | # end connection 37 | client.close() 38 | 39 | if __name__ == '__main__': 40 | parser = argparse.ArgumentParser(description='Socket Server Example') 41 | parser.add_argument('--port', action="store", dest="port", type=int, required=True) 42 | given_args = parser.parse_args() 43 | port = given_args.port 44 | echo_server(port) 45 | -------------------------------------------------------------------------------- /Chapter01/1_13b_echo_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 1 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import socket 7 | import sys 8 | 9 | import argparse 10 | 11 | host = 'localhost' 12 | 13 | def echo_client(port): 14 | """ A simple echo client """ 15 | # Create a TCP/IP socket 16 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 17 | # Connect the socket to the server 18 | server_address = (host, port) 19 | print ("Connecting to %s port %s" % server_address) 20 | sock.connect(server_address) 21 | 22 | # Send data 23 | try: 24 | # Send data 25 | message = "Test message. This will be echoed" 26 | print ("Sending %s" % message) 27 | sock.sendall(message.encode('utf-8')) 28 | # Look for the response 29 | amount_received = 0 30 | amount_expected = len(message) 31 | while amount_received < amount_expected: 32 | data = sock.recv(16) 33 | amount_received += len(data) 34 | print ("Received: %s" % data) 35 | except socket.error as e: 36 | print ("Socket error: %s" %str(e)) 37 | except Exception as e: 38 | print ("Other exception: %s" %str(e)) 39 | finally: 40 | print ("Closing connection to the server") 41 | sock.close() 42 | 43 | if __name__ == '__main__': 44 | parser = argparse.ArgumentParser(description='Socket Server Example') 45 | parser.add_argument('--port', action="store", dest="port", type=int, required=True) 46 | given_args = parser.parse_args() 47 | port = given_args.port 48 | echo_client(port) 49 | -------------------------------------------------------------------------------- /Chapter01/1_14a_echo_server_udp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 1 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import socket 7 | import sys 8 | import argparse 9 | 10 | host = 'localhost' 11 | data_payload = 2048 12 | 13 | def echo_server(port): 14 | """ A simple echo server """ 15 | # Create a UDP socket 16 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 17 | 18 | # Bind the socket to the port 19 | server_address = (host, port) 20 | print ("Starting up echo server on %s port %s" % server_address) 21 | 22 | sock.bind(server_address) 23 | 24 | while True: 25 | print ("Waiting to receive message from client") 26 | data, address = sock.recvfrom(data_payload) 27 | 28 | print ("received %s bytes from %s" % (len(data), address)) 29 | print ("Data: %s" %data) 30 | 31 | if data: 32 | sent = sock.sendto(data, address) 33 | print ("sent %s bytes back to %s" % (sent, address)) 34 | 35 | 36 | if __name__ == '__main__': 37 | parser = argparse.ArgumentParser(description='Socket Server Example') 38 | parser.add_argument('--port', action="store", dest="port", type=int, required=True) 39 | given_args = parser.parse_args() 40 | port = given_args.port 41 | echo_server(port) 42 | -------------------------------------------------------------------------------- /Chapter01/1_14b_echo_client_udp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 1 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import socket 7 | import sys 8 | import argparse 9 | 10 | host = 'localhost' 11 | data_payload = 2048 12 | 13 | def echo_client(port): 14 | """ A simple echo client """ 15 | # Create a UDP socket 16 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 17 | 18 | server_address = (host, port) 19 | print ("Connecting to %s port %s" % server_address) 20 | message = 'This is the message. It will be repeated.' 21 | 22 | try: 23 | 24 | # Send data 25 | message = "Test message. This will be echoed" 26 | print ("Sending %s" % message) 27 | sent = sock.sendto(message.encode('utf-8'), server_address) 28 | 29 | # Receive response 30 | data, server = sock.recvfrom(data_payload) 31 | print ("received %s" % data) 32 | 33 | finally: 34 | print ("Closing connection to the server") 35 | sock.close() 36 | 37 | if __name__ == '__main__': 38 | parser = argparse.ArgumentParser(description='Socket Server Example') 39 | parser.add_argument('--port', action="store", dest="port", type=int, required=True) 40 | given_args = parser.parse_args() 41 | port = given_args.port 42 | echo_client(port) 43 | -------------------------------------------------------------------------------- /Chapter01/1_1_local_machine_info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 1 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import socket 7 | 8 | 9 | def print_machine_info(): 10 | host_name = socket.gethostname() 11 | ip_address = socket.gethostbyname(host_name) 12 | print ("Host name: %s" %host_name) 13 | print ("IP address: %s" %ip_address) 14 | 15 | if __name__ == '__main__': 16 | print_machine_info() 17 | -------------------------------------------------------------------------------- /Chapter01/1_2_remote_machine_info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 1 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | import socket 8 | 9 | def get_remote_machine_info(): 10 | remote_host = 'www.python.org' 11 | try: 12 | print ("IP address of %s: %s" %(remote_host, socket.gethostbyname(remote_host))) 13 | except socket.error as err_msg: 14 | print ("%s: %s" %(remote_host, err_msg)) 15 | 16 | if __name__ == '__main__': 17 | get_remote_machine_info() 18 | -------------------------------------------------------------------------------- /Chapter01/1_3_ip4_address_conversion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 1 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | import socket 8 | from binascii import hexlify 9 | 10 | 11 | def convert_ip4_address(): 12 | for ip_addr in ['127.0.0.1', '192.168.0.1']: 13 | packed_ip_addr = socket.inet_aton(ip_addr) 14 | unpacked_ip_addr = socket.inet_ntoa(packed_ip_addr) 15 | print ("IP Address: %s => Packed: %s, Unpacked: %s" %(ip_addr, hexlify(packed_ip_addr), unpacked_ip_addr)) 16 | 17 | if __name__ == '__main__': 18 | convert_ip4_address() 19 | -------------------------------------------------------------------------------- /Chapter01/1_4_finding_service_name.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 1 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import socket 7 | 8 | def find_service_name(): 9 | protocolname = 'tcp' 10 | for port in [80, 25]: 11 | print ("Port: %s => service name: %s" %(port, socket.getservbyport(port, protocolname))) 12 | 13 | print ("Port: %s => service name: %s" %(53, socket.getservbyport(53, 'udp'))) 14 | 15 | if __name__ == '__main__': 16 | find_service_name() 17 | -------------------------------------------------------------------------------- /Chapter01/1_5_integer_conversion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 1 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import socket 7 | 8 | def convert_integer(): 9 | data = 1234 10 | # 32-bit 11 | print ("Original: %s => Long host byte order: %s, Network byte order: %s" %(data, socket.ntohl(data), socket.htonl(data))) 12 | # 16-bit 13 | print ("Original: %s => Short host byte order: %s, Network byte order: %s" %(data, socket.ntohs(data), socket.htons(data))) 14 | 15 | 16 | if __name__ == '__main__': 17 | convert_integer() 18 | -------------------------------------------------------------------------------- /Chapter01/1_6_socket_timeout.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 1 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | import socket 8 | 9 | def test_socket_timeout(): 10 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 11 | print ("Default socket timeout: %s" %s.gettimeout()) 12 | s.settimeout(100) 13 | print ("Current socket timeout: %s" %s.gettimeout()) 14 | 15 | if __name__ == '__main__': 16 | test_socket_timeout() 17 | -------------------------------------------------------------------------------- /Chapter01/1_7_socket_errors.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 1 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import sys 7 | import socket 8 | import argparse 9 | 10 | 11 | def main(): 12 | # setup argument parsing 13 | parser = argparse.ArgumentParser(description='Socket Error Examples') 14 | parser.add_argument('--host', action="store", dest="host", required=False) 15 | parser.add_argument('--port', action="store", dest="port", type=int, required=False) 16 | parser.add_argument('--file', action="store", dest="file", required=False) 17 | given_args = parser.parse_args() 18 | host = given_args.host 19 | port = given_args.port 20 | filename = given_args.file 21 | 22 | # First try-except block -- create socket 23 | try: 24 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 25 | except socket.error as e: 26 | print ("Error creating socket: %s" % e) 27 | sys.exit(1) 28 | 29 | # Second try-except block -- connect to given host/port 30 | try: 31 | s.connect((host, port)) 32 | except socket.gaierror as e: 33 | print ("Address-related error connecting to server: %s" % e) 34 | sys.exit(1) 35 | except socket.error as e: 36 | print ("Connection error: %s" % e) 37 | sys.exit(1) 38 | 39 | # Third try-except block -- sending data 40 | try: 41 | msg = "GET %s HTTP/1.0\r\n\r\n" % filename 42 | s.sendall(msg.encode('utf-8')) 43 | except socket.error as e: 44 | print ("Error sending data: %s" % e) 45 | sys.exit(1) 46 | 47 | while 1: 48 | # Fourth tr-except block -- waiting to receive data from remote host 49 | try: 50 | buf = s.recv(2048) 51 | except socket.error as e: 52 | print ("Error receiving data: %s" % e) 53 | sys.exit(1) 54 | if not len(buf): 55 | break 56 | # write the received data 57 | sys.stdout.write(buf.decode('utf-8')) 58 | 59 | if __name__ == '__main__': 60 | main() 61 | -------------------------------------------------------------------------------- /Chapter01/1_8_modify_buff_size.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 1 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import socket 7 | 8 | SEND_BUF_SIZE = 4096 9 | RECV_BUF_SIZE = 4096 10 | 11 | def modify_buff_size(): 12 | sock = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) 13 | 14 | # Get the size of the socket's send buffer 15 | bufsize = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF) 16 | print ("Buffer size [Before]:%d" %bufsize) 17 | 18 | sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) 19 | sock.setsockopt( 20 | socket.SOL_SOCKET, 21 | socket.SO_SNDBUF, 22 | SEND_BUF_SIZE) 23 | sock.setsockopt( 24 | socket.SOL_SOCKET, 25 | socket.SO_RCVBUF, 26 | RECV_BUF_SIZE) 27 | bufsize = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF) 28 | print ("Buffer size [After]:%d" %bufsize) 29 | 30 | if __name__ == '__main__': 31 | modify_buff_size() 32 | -------------------------------------------------------------------------------- /Chapter01/1_9_socket_modes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 1 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import socket 7 | 8 | def test_socket_modes(): 9 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 10 | s.setblocking(1) 11 | s.settimeout(0.5) 12 | s.bind(("127.0.0.1", 0)) 13 | 14 | socket_address = s.getsockname() 15 | print ("Trivial Server launched on socket: %s" %str(socket_address)) 16 | while(1): 17 | s.listen(1) 18 | 19 | if __name__ == '__main__': 20 | test_socket_modes() 21 | -------------------------------------------------------------------------------- /Chapter01/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Network-Programming-Cookbook-Second-Edition/7a2618500cd7a3a4ff527751664bd9b39bb63a7a/Chapter01/__init__.py -------------------------------------------------------------------------------- /Chapter02/2_1_forking_mixin_socket_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 2 3 | # This program is optimized for Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | # To make it run on Python 2.7.12, needs some changes due to API differences. 6 | # begin with replacing "socketserver" with "SocketServer" throughout the program. 7 | # See more: http://docs.python.org/2/library/socketserver.html 8 | # See more: http://docs.python.org/3/library/socketserver.html 9 | 10 | import os 11 | import socket 12 | import threading 13 | import socketserver 14 | 15 | 16 | SERVER_HOST = 'localhost' 17 | SERVER_PORT = 0 # tells the kernel to pickup a port dynamically 18 | BUF_SIZE = 1024 19 | ECHO_MSG = 'Hello echo server!' 20 | 21 | 22 | class ForkedClient(): 23 | """ A client to test forking server""" 24 | def __init__(self, ip, port): 25 | # Create a socket 26 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 27 | # Connect to the server 28 | self.sock.connect((ip, port)) 29 | 30 | def run(self): 31 | """ Client playing with the server""" 32 | # Send the data to server 33 | current_process_id = os.getpid() 34 | print ('PID %s Sending echo message to the server : "%s"' % (current_process_id, ECHO_MSG)) 35 | 36 | sent_data_length = self.sock.send(bytes(ECHO_MSG, 'utf-8')) 37 | 38 | print ("Sent: %d characters, so far..." %sent_data_length) 39 | 40 | # Display server response 41 | response = self.sock.recv(BUF_SIZE) 42 | print ("PID %s received: %s" % (current_process_id, response[5:])) 43 | 44 | def shutdown(self): 45 | """ Cleanup the client socket """ 46 | self.sock.close() 47 | 48 | 49 | class ForkingServerRequestHandler(socketserver.BaseRequestHandler): 50 | def handle(self): 51 | # Send the echo back to the client 52 | 53 | #received = str(sock.recv(1024), "utf-8") 54 | data = str(self.request.recv(BUF_SIZE), 'utf-8') 55 | 56 | current_process_id = os.getpid() 57 | response = '%s: %s' % (current_process_id, data) 58 | print ("Server sending response [current_process_id: data] = [%s]" %response) 59 | self.request.send(bytes(response, 'utf-8')) 60 | return 61 | 62 | 63 | class ForkingServer(socketserver.ForkingMixIn, 64 | socketserver.TCPServer, 65 | ): 66 | """Nothing to add here, inherited everything necessary from parents""" 67 | pass 68 | 69 | 70 | def main(): 71 | # Launch the server 72 | server = ForkingServer((SERVER_HOST, SERVER_PORT), ForkingServerRequestHandler) 73 | ip, port = server.server_address # Retrieve the port number 74 | server_thread = threading.Thread(target=server.serve_forever) 75 | server_thread.setDaemon(True) # don't hang on exit 76 | server_thread.start() 77 | print ("Server loop running PID: %s" %os.getpid()) 78 | 79 | # Launch the client(s) 80 | 81 | client1 = ForkedClient(ip, port) 82 | client1.run() 83 | 84 | print("First client running") 85 | 86 | client2 = ForkedClient(ip, port) 87 | client2.run() 88 | 89 | print("Second client running") 90 | 91 | # Clean them up 92 | server.shutdown() 93 | client1.shutdown() 94 | client2.shutdown() 95 | server.socket.close() 96 | 97 | 98 | if __name__ == '__main__': 99 | main() 100 | -------------------------------------------------------------------------------- /Chapter02/2_1_forking_mixin_socket_server2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 2 3 | # This program is optimized for Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | # 6 | # Need some modifications to make it run on Python 2.7.x: 7 | # For the start, replace "socketserver" with "SocketServer" throughout the program. 8 | # Progress accordingly addressing the API changes between the versions. 9 | # 10 | # See more: http://docs.python.org/2/library/socketserver.html 11 | # See more: http://docs.python.org/3/library/socketserver.html 12 | 13 | import os 14 | import socket 15 | import threading 16 | import socketserver 17 | 18 | 19 | SERVER_HOST = 'localhost' 20 | SERVER_PORT = 0 # tells the kernel to pickup a port dynamically 21 | BUF_SIZE = 1024 22 | ECHO_MSG = 'Hello echo server!' 23 | 24 | 25 | class ForkedClient(): 26 | """ A client to test forking server""" 27 | def __init__(self, ip, port): 28 | # Create a socket 29 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 30 | # Connect to the server 31 | self.sock.connect((ip, port)) 32 | 33 | def run(self): 34 | """ Client playing with the server""" 35 | # Send the data to server 36 | current_process_id = os.getpid() 37 | print ('PID %s Sending echo message to the server : "%s"' % (current_process_id, ECHO_MSG)) 38 | 39 | sent_data_length = self.sock.send(bytes(ECHO_MSG, 'utf-8')) 40 | 41 | print ("Sent: %d characters, so far..." %sent_data_length) 42 | 43 | # Display server response 44 | response = self.sock.recv(BUF_SIZE) 45 | print ("PID %s received: %s" % (current_process_id, response[5:])) 46 | 47 | def shutdown(self): 48 | """ Cleanup the client socket """ 49 | self.sock.close() 50 | 51 | 52 | class ForkingServerRequestHandler(socketserver.BaseRequestHandler): 53 | def handle(self): 54 | # Send the echo back to the client 55 | 56 | #received = str(sock.recv(1024), "utf-8") 57 | data = str(self.request.recv(BUF_SIZE), 'utf-8') 58 | 59 | current_process_id = os.getpid() 60 | response = '%s: %s' % (current_process_id, data) 61 | print ("Server sending response [current_process_id: data] = [%s]" %response) 62 | self.request.send(bytes(response, 'utf-8')) 63 | return 64 | 65 | 66 | class ForkingServer(socketserver.ForkingMixIn, 67 | socketserver.TCPServer, 68 | ): 69 | """Nothing to add here, inherited everything necessary from parents""" 70 | pass 71 | 72 | 73 | def main(): 74 | # Launch the server 75 | server = ForkingServer((SERVER_HOST, SERVER_PORT), ForkingServerRequestHandler) 76 | ip, port = server.server_address # Retrieve the port number 77 | server_thread = threading.Thread(target=server.serve_forever) 78 | server_thread.setDaemon(True) # don't hang on exit 79 | server_thread.start() 80 | print ('Server loop running PID: %s' %os.getpid()) 81 | 82 | # Launch the client(s) 83 | 84 | client1 = ForkedClient(ip, port) 85 | client1.run() 86 | 87 | print("First client running") 88 | 89 | client2 = ForkedClient(ip, port) 90 | client2.run() 91 | 92 | print("Second client running") 93 | 94 | # Clean them up 95 | server.shutdown() 96 | client1.shutdown() 97 | client2.shutdown() 98 | server.socket.close() 99 | 100 | 101 | if __name__ == '__main__': 102 | main() 103 | -------------------------------------------------------------------------------- /Chapter02/2_2_threading_mixin_socket_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 2 3 | # This program is optimized for Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | # To make it run on Python 2.7.x, needs some changes due to API differences. 6 | # begin with replacing "socketserver" with "SocketServer" throughout the program. 7 | # See more: http://docs.python.org/2/library/socketserver.html 8 | # See more: http://docs.python.org/3/library/socketserver.html 9 | 10 | import os 11 | import socket 12 | import threading 13 | import socketserver 14 | 15 | SERVER_HOST = 'localhost' 16 | SERVER_PORT = 0 # tells the kernel to pickup a port dynamically 17 | BUF_SIZE = 1024 18 | 19 | 20 | def client(ip, port, message): 21 | """ A client to test threading mixin server""" 22 | # Connect to the server 23 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 24 | sock.connect((ip, port)) 25 | try: 26 | sock.sendall(bytes(message, 'utf-8')) 27 | response = sock.recv(BUF_SIZE) 28 | print ("Client received: %s" %response) 29 | finally: 30 | sock.close() 31 | 32 | 33 | class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): 34 | """ An example of threaded TCP request handler """ 35 | def handle(self): 36 | data = self.request.recv(1024) 37 | cur_thread = threading.current_thread() 38 | response = "%s: %s" %(cur_thread.name, data) 39 | self.request.sendall(bytes(response, 'utf-8')) 40 | 41 | class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): 42 | """Nothing to add here, inherited everything necessary from parents""" 43 | pass 44 | 45 | 46 | if __name__ == "__main__": 47 | # Run server 48 | server = ThreadedTCPServer((SERVER_HOST, SERVER_PORT), ThreadedTCPRequestHandler) 49 | ip, port = server.server_address # retrieve ip address 50 | 51 | # Start a thread with the server -- one thread per request 52 | server_thread = threading.Thread(target=server.serve_forever) 53 | # Exit the server thread when the main thread exits 54 | server_thread.daemon = True 55 | server_thread.start() 56 | print ("Server loop running on thread: %s" %server_thread.name) 57 | 58 | # Run clients 59 | client(ip, port, "Hello from client 1") 60 | client(ip, port, "Hello from client 2") 61 | client(ip, port, "Hello from client 3") 62 | 63 | # Server cleanup 64 | server.shutdown() 65 | -------------------------------------------------------------------------------- /Chapter02/2_4_simple_web_server_with_epoll.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 2 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | import socket 8 | import select 9 | import argparse 10 | 11 | SERVER_HOST = 'localhost' 12 | 13 | EOL1 = b'\n\n' 14 | EOL2 = b'\n\r\n' 15 | SERVER_RESPONSE = b"""HTTP/1.1 200 OK\r\nDate: Mon, 1 Apr 2013 01:01:01 GMT\r\nContent-Type: text/plain\r\nContent-Length: 25\r\n\r\n 16 | Hello from Epoll Server!""" 17 | 18 | 19 | class EpollServer(object): 20 | """ A socket server using Epoll""" 21 | 22 | def __init__(self, host=SERVER_HOST, port=0): 23 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 24 | self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 25 | self.sock.bind((host, port)) 26 | self.sock.listen(1) 27 | self.sock.setblocking(0) 28 | self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) 29 | print ("Started Epoll Server") 30 | self.epoll = select.epoll() 31 | self.epoll.register(self.sock.fileno(), select.EPOLLIN) 32 | 33 | def run(self): 34 | """Executes epoll server operation""" 35 | try: 36 | connections = {}; requests = {}; responses = {} 37 | while True: 38 | events = self.epoll.poll(1) 39 | for fileno, event in events: 40 | if fileno == self.sock.fileno(): 41 | connection, address = self.sock.accept() 42 | connection.setblocking(0) 43 | self.epoll.register(connection.fileno(), select.EPOLLIN) 44 | connections[connection.fileno()] = connection 45 | requests[connection.fileno()] = b'' 46 | responses[connection.fileno()] = SERVER_RESPONSE 47 | elif event & select.EPOLLIN: 48 | requests[fileno] += connections[fileno].recv(1024) 49 | if EOL1 in requests[fileno] or EOL2 in requests[fileno]: 50 | self.epoll.modify(fileno, select.EPOLLOUT) 51 | print('-'*40 + '\n' + requests[fileno].decode()[:-2]) 52 | elif event & select.EPOLLOUT: 53 | byteswritten = connections[fileno].send(responses[fileno]) 54 | responses[fileno] = responses[fileno][byteswritten:] 55 | if len(responses[fileno]) == 0: 56 | self.epoll.modify(fileno, 0) 57 | connections[fileno].shutdown(socket.SHUT_RDWR) 58 | elif event & select.EPOLLHUP: 59 | self.epoll.unregister(fileno) 60 | connections[fileno].close() 61 | del connections[fileno] 62 | finally: 63 | self.epoll.unregister(self.sock.fileno()) 64 | self.epoll.close() 65 | self.sock.close() 66 | 67 | 68 | if __name__ == '__main__': 69 | parser = argparse.ArgumentParser(description='Socket Server Example with Epoll') 70 | parser.add_argument('--port', action="store", dest="port", type=int, required=True) 71 | given_args = parser.parse_args() 72 | port = given_args.port 73 | server = EpollServer(host=SERVER_HOST, port=port) 74 | server.run() 75 | -------------------------------------------------------------------------------- /Chapter02/2_5_echo_server_with_diesel.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 2 3 | # This program is optimized for Python 2.7.12. 4 | # It will work with Python 3.5.2 once the depedencies for diesel are sorted out. 5 | # It may run on any other version with/without modifications. 6 | # You also need diesel library 3.0 or a later version. 7 | # Make sure to install the dependencies beforehand. 8 | 9 | import diesel 10 | import argparse 11 | 12 | class EchoServer(object): 13 | """ An echo server using diesel""" 14 | 15 | def handler(self, remote_addr): 16 | """Runs the echo server""" 17 | host, port = remote_addr[0], remote_addr[1] 18 | print ("Echo client connected from: %s:%d" %(host, port)) 19 | 20 | while True: 21 | try: 22 | message = diesel.until_eol() 23 | your_message = ': '.join(['You said', message]) 24 | diesel.send(your_message) 25 | except Exception as e: 26 | print ("Exception:",e) 27 | 28 | 29 | def main(server_port): 30 | app = diesel.Application() 31 | server = EchoServer() 32 | app.add_service(diesel.Service(server.handler, server_port)) 33 | app.run() 34 | 35 | 36 | if __name__ == '__main__': 37 | parser = argparse.ArgumentParser(description='Echo server example with Diesel') 38 | parser.add_argument('--port', action="store", dest="port", type=int, required=True) 39 | given_args = parser.parse_args() 40 | port = given_args.port 41 | main(port) 42 | 43 | 44 | -------------------------------------------------------------------------------- /Chapter02/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Network-Programming-Cookbook-Second-Edition/7a2618500cd7a3a4ff527751664bd9b39bb63a7a/Chapter02/__init__.py -------------------------------------------------------------------------------- /Chapter03/3_10_check_ipv6_support.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 3 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | # This program depends on Python module netifaces => 0.8 6 | 7 | import socket 8 | import argparse 9 | import netifaces as ni 10 | 11 | 12 | def inspect_ipv6_support(): 13 | """ Find the ipv6 address""" 14 | print ("IPV6 support built into Python: %s" %socket.has_ipv6) 15 | ipv6_addr = {} 16 | for interface in ni.interfaces(): 17 | all_addresses = ni.ifaddresses(interface) 18 | print ("Interface %s:" %interface) 19 | 20 | for family,addrs in all_addresses.items(): 21 | fam_name = ni.address_families[family] 22 | print (' Address family: %s' % fam_name) 23 | for addr in addrs: 24 | if fam_name == 'AF_INET6': 25 | ipv6_addr[interface] = addr['addr'] 26 | print (' Address : %s' % addr['addr']) 27 | nmask = addr.get('netmask', None) 28 | if nmask: 29 | print (' Netmask : %s' % nmask) 30 | bcast = addr.get('broadcast', None) 31 | if bcast: 32 | print (' Broadcast: %s' % bcast) 33 | if ipv6_addr: 34 | print ("Found IPv6 address: %s" %ipv6_addr) 35 | else: 36 | print ("No IPv6 interface found!") 37 | 38 | 39 | if __name__ == '__main__': 40 | inspect_ipv6_support() 41 | -------------------------------------------------------------------------------- /Chapter03/3_11_extract_ipv6_prefix.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 3 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | # This program depends on Python modules netifaces and netaddr. 6 | 7 | import socket 8 | import netifaces as ni 9 | import netaddr as na 10 | 11 | def extract_ipv6_info(): 12 | """ Extracts IPv6 information""" 13 | print ("IPv6 support built into Python: %s" %socket.has_ipv6) 14 | for interface in ni.interfaces(): 15 | all_addresses = ni.ifaddresses(interface) 16 | print ("Interface %s:" %interface) 17 | for family,addrs in all_addresses.items(): 18 | fam_name = ni.address_families[family] 19 | 20 | for addr in addrs: 21 | if fam_name == 'AF_INET6': 22 | addr = addr['addr'] 23 | has_eth_string = addr.split("%eth") 24 | if has_eth_string: 25 | addr = addr.split("%eth")[0] 26 | try: 27 | print (" IP Address: %s" %na.IPNetwork(addr)) 28 | print (" IP Version: %s" %na.IPNetwork(addr).version) 29 | print (" IP Prefix length: %s" %na.IPNetwork(addr).prefixlen) 30 | print (" Network: %s" %na.IPNetwork(addr).network) 31 | print (" Broadcast: %s" %na.IPNetwork(addr).broadcast) 32 | except Exception as e: 33 | print ("Skip Non-IPv6 Interface") 34 | 35 | if __name__ == '__main__': 36 | extract_ipv6_info() 37 | -------------------------------------------------------------------------------- /Chapter03/3_12a_ipv6_echo_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 3 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | import socket 8 | import sys 9 | 10 | HOST = 'localhost' 11 | 12 | def echo_server(port, host=HOST): 13 | """Echo server using IPv6 """ 14 | for result in socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE): 15 | af, socktype, proto, canonname, sa = result 16 | try: 17 | sock = socket.socket(af, socktype, proto) 18 | except socket.error as err: 19 | print ("Error: %s" %err) 20 | 21 | try: 22 | sock.bind(sa) 23 | sock.listen(1) 24 | print ("Server lisenting on %s:%s" %(host, port)) 25 | except socket.error as msg: 26 | sock.close() 27 | continue 28 | break 29 | sys.exit(1) 30 | conn, addr = sock.accept() 31 | print ('Connected to', addr) 32 | while True: 33 | data = conn.recv(1024) 34 | print ("Received data from the client: [%s]" %data) 35 | if not data: break 36 | conn.send(data) 37 | print ("Sent data echoed back to the client: [%s]" %data) 38 | conn.close() 39 | 40 | if __name__ == '__main__': 41 | parser = argparse.ArgumentParser(description='IPv6 Socket Server Example') 42 | parser.add_argument('--port', action="store", dest="port", type=int, required=True) 43 | given_args = parser.parse_args() 44 | port = given_args.port 45 | echo_server(port) 46 | 47 | -------------------------------------------------------------------------------- /Chapter03/3_12b_ipv6_echo_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 3 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | import socket 8 | import sys 9 | 10 | HOST = 'localhost' 11 | BUFSIZE = 1024 12 | 13 | def ipv6_echo_client(port, host=HOST): 14 | for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM): 15 | af, socktype, proto, canonname, sa = res 16 | try: 17 | sock = socket.socket(af, socktype, proto) 18 | except socket.error as err: 19 | print ("Error:%s" %err) 20 | try: 21 | sock.connect(sa) 22 | except socket.error as msg: 23 | sock.close() 24 | continue 25 | if sock is None: 26 | print ('Failed to open socket!') 27 | sys.exit(1) 28 | msg = "Hello from ipv6 client" 29 | print ("Send data to server: %s" %msg) 30 | sock.send(bytes(msg.encode('utf-8'))) 31 | while True: 32 | data = sock.recv(BUFSIZE) 33 | print ('Received from server', repr(data)) 34 | if not data: 35 | break 36 | sock.close() 37 | 38 | 39 | if __name__ == '__main__': 40 | parser = argparse.ArgumentParser(description='IPv6 socket client example') 41 | parser.add_argument('--port', action="store", dest="port", type=int, required=True) 42 | given_args = parser.parse_args() 43 | port = given_args.port 44 | ipv6_echo_client(port) 45 | -------------------------------------------------------------------------------- /Chapter03/3_1_port_forwarding.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 3 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | import argparse 8 | 9 | LOCAL_SERVER_HOST = 'localhost' 10 | REMOTE_SERVER_HOST = 'www.google.com' 11 | BUFSIZE = 4096 12 | 13 | import asyncore 14 | import socket 15 | 16 | class PortForwarder(asyncore.dispatcher): 17 | def __init__(self, ip, port, remoteip,remoteport,backlog=5): 18 | asyncore.dispatcher.__init__(self) 19 | self.remoteip=remoteip 20 | self.remoteport=remoteport 21 | self.create_socket(socket.AF_INET,socket.SOCK_STREAM) 22 | self.set_reuse_addr() 23 | self.bind((ip,port)) 24 | self.listen(backlog) 25 | 26 | def handle_accept(self): 27 | conn, addr = self.accept() 28 | print ("Connected to:",addr) 29 | Sender(Receiver(conn),self.remoteip,self.remoteport) 30 | 31 | class Receiver(asyncore.dispatcher): 32 | def __init__(self,conn): 33 | asyncore.dispatcher.__init__(self,conn) 34 | self.from_remote_buffer='' 35 | self.to_remote_buffer='' 36 | self.sender=None 37 | 38 | def handle_connect(self): 39 | pass 40 | 41 | def handle_read(self): 42 | read = self.recv(BUFSIZE) 43 | self.from_remote_buffer += read 44 | 45 | def writable(self): 46 | return (len(self.to_remote_buffer) > 0) 47 | 48 | def handle_write(self): 49 | sent = self.send(self.to_remote_buffer) 50 | self.to_remote_buffer = self.to_remote_buffer[sent:] 51 | 52 | def handle_close(self): 53 | self.close() 54 | if self.sender: 55 | self.sender.close() 56 | 57 | class Sender(asyncore.dispatcher): 58 | def __init__(self, receiver, remoteaddr,remoteport): 59 | asyncore.dispatcher.__init__(self) 60 | self.receiver=receiver 61 | receiver.sender=self 62 | self.create_socket(socket.AF_INET, socket.SOCK_STREAM) 63 | self.connect((remoteaddr, remoteport)) 64 | 65 | def handle_connect(self): 66 | pass 67 | 68 | def handle_read(self): 69 | read = self.recv(BUFSIZE) 70 | self.receiver.to_remote_buffer += read 71 | 72 | def writable(self): 73 | return (len(self.receiver.from_remote_buffer) > 0) 74 | 75 | def handle_write(self): 76 | sent = self.send(self.receiver.from_remote_buffer) 77 | self.receiver.from_remote_buffer = self.receiver.from_remote_buffer[sent:] 78 | 79 | def handle_close(self): 80 | self.close() 81 | self.receiver.close() 82 | 83 | 84 | if __name__ == "__main__": 85 | parser = argparse.ArgumentParser(description='Stackless Socket Server Example') 86 | parser.add_argument('--local-host', action="store", dest="local_host", default=LOCAL_SERVER_HOST) 87 | parser.add_argument('--local-port', action="store", dest="local_port", type=int, required=True) 88 | parser.add_argument('--remote-host', action="store", dest="remote_host", default=REMOTE_SERVER_HOST) 89 | parser.add_argument('--remote-port', action="store", dest="remote_port", type=int, default=80) 90 | given_args = parser.parse_args() 91 | local_host, remote_host = given_args.local_host, given_args.remote_host 92 | local_port, remote_port = given_args.local_port, given_args.remote_port 93 | 94 | print ("Starting port forwarding local %s:%s => remote %s:%s" % (local_host, local_port, remote_host, remote_port)) 95 | PortForwarder(local_host, local_port, remote_host, remote_port) 96 | asyncore.loop() 97 | -------------------------------------------------------------------------------- /Chapter03/3_3_wait_for_remote_service.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 3 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | import socket 8 | import errno 9 | from time import time as now 10 | 11 | DEFAULT_TIMEOUT = 120 12 | DEFAULT_SERVER_HOST = 'localhost' 13 | DEFAULT_SERVER_PORT = 80 14 | 15 | class NetServiceChecker(object): 16 | """ Wait for a network service to come online""" 17 | def __init__(self, host, port, timeout=DEFAULT_TIMEOUT): 18 | self.host = host 19 | self.port = port 20 | self.timeout = timeout 21 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 22 | 23 | def end_wait(self): 24 | self.sock.close() 25 | 26 | def check(self): 27 | """ Check the service """ 28 | if self.timeout: 29 | end_time = now() + self.timeout 30 | 31 | while True: 32 | try: 33 | if self.timeout: 34 | next_timeout = end_time - now() 35 | if next_timeout < 0: 36 | return False 37 | else: 38 | print ("setting socket next timeout %ss" %round(next_timeout)) 39 | self.sock.settimeout(next_timeout) 40 | self.sock.connect((self.host, self.port)) 41 | # handle exceptions 42 | except socket.timeout as err: 43 | if self.timeout: 44 | return False 45 | except socket.error as err: 46 | print ("Exception: %s" %err) 47 | else: # if all goes well 48 | self.end_wait() 49 | return True 50 | 51 | if __name__ == '__main__': 52 | parser = argparse.ArgumentParser(description='Wait for Network Service') 53 | parser.add_argument('--host', action="store", dest="host", default=DEFAULT_SERVER_HOST) 54 | parser.add_argument('--port', action="store", dest="port", type=int, default=DEFAULT_SERVER_PORT) 55 | parser.add_argument('--timeout', action="store", dest="timeout", type=int, default=DEFAULT_TIMEOUT) 56 | given_args = parser.parse_args() 57 | host, port, timeout = given_args.host, given_args.port, given_args.timeout 58 | service_checker = NetServiceChecker(host, port, timeout=timeout) 59 | print ("Checking for network service %s:%s ..." %(host, port)) 60 | if service_checker.check(): 61 | print ("Service is available again!") 62 | -------------------------------------------------------------------------------- /Chapter03/3_4_list_network_interfaces.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 3 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import sys 7 | import socket 8 | import fcntl 9 | import struct 10 | import array 11 | 12 | SIOCGIFCONF = 0x8912 #from C library sockios.h 13 | STUCT_SIZE_32 = 32 14 | STUCT_SIZE_64 = 40 15 | PLATFORM_32_MAX_NUMBER = 2**32 16 | DEFAULT_INTERFACES = 8 17 | 18 | 19 | def list_interfaces(): 20 | interfaces = [] 21 | max_interfaces = DEFAULT_INTERFACES 22 | is_64bits = sys.maxsize > PLATFORM_32_MAX_NUMBER 23 | struct_size = STUCT_SIZE_64 if is_64bits else STUCT_SIZE_32 24 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 25 | while True: 26 | bytes = max_interfaces * struct_size 27 | interface_names = array.array('B', b'\0' * bytes) 28 | sock_info = fcntl.ioctl( 29 | sock.fileno(), 30 | SIOCGIFCONF, 31 | struct.pack('iL', bytes, interface_names.buffer_info()[0]) 32 | ) 33 | outbytes = struct.unpack('iL', sock_info)[0] 34 | if outbytes == bytes: 35 | max_interfaces *= 2 36 | else: 37 | break 38 | namestr = interface_names.tostring() 39 | for i in range(0, outbytes, struct_size): 40 | interfaces.append((namestr[i:i+16].split(b'\0', 1)[0]).decode('ascii', 'ignore')) 41 | return interfaces 42 | 43 | 44 | if __name__ == '__main__': 45 | interfaces = list_interfaces() 46 | print ("This machine has %s network interfaces: %s." %(len(interfaces), interfaces)) 47 | 48 | -------------------------------------------------------------------------------- /Chapter03/3_5_get_interface_ip_address.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 3 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | import sys 8 | import socket 9 | import fcntl 10 | import struct 11 | import array 12 | 13 | 14 | def get_ip_address(ifname): 15 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 16 | return socket.inet_ntoa(fcntl.ioctl( 17 | s.fileno(), 18 | 0x8915, # SIOCGIFADDR 19 | struct.pack(b'256s', bytes(ifname[:15], 'utf-8')) 20 | )[20:24]) 21 | 22 | if __name__ == '__main__': 23 | parser = argparse.ArgumentParser(description='Python networking utils') 24 | parser.add_argument('--ifname', action="store", dest="ifname", required=True) 25 | given_args = parser.parse_args() 26 | ifname = given_args.ifname 27 | print ("Interface [%s] --> IP: %s" %(ifname, get_ip_address(ifname))) 28 | -------------------------------------------------------------------------------- /Chapter03/3_6_find_network_interface_status.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 3 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | import argparse 8 | import socket 9 | import struct 10 | import fcntl 11 | import nmap 12 | 13 | 14 | SAMPLE_PORTS = '21-23' 15 | 16 | 17 | def get_interface_status(ifname): 18 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 19 | ip_address = socket.inet_ntoa(fcntl.ioctl( 20 | sock.fileno(), 21 | 0x8915, #SIOCGIFADDR, C socket library sockios.h 22 | struct.pack(b'256s', bytes(ifname[:15], 'utf-8')) 23 | )[20:24]) 24 | nm = nmap.PortScanner() 25 | nm.scan(ip_address, SAMPLE_PORTS) 26 | return nm[ip_address].state() 27 | 28 | 29 | if __name__ == '__main__': 30 | parser = argparse.ArgumentParser(description='Python networking utils') 31 | parser.add_argument('--ifname', action="store", dest="ifname", required=True) 32 | given_args = parser.parse_args() 33 | ifname = given_args.ifname 34 | print ("Interface [%s] is: %s" %(ifname, get_interface_status(ifname))) 35 | 36 | -------------------------------------------------------------------------------- /Chapter03/3_7_detect_inactive_machines.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 3 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | # Requires scapy-2.2.0 or higher for Python 2.7. 6 | # Visit: http://www.secdev.org/projects/scapy/files/scapy-latest.zip 7 | # As of now, requires a separate bundle for Python 3.x. 8 | # Download it from: https://pypi.python.org/pypi/scapy-python3/0.20 9 | 10 | 11 | import argparse 12 | import time 13 | import sched 14 | from scapy.all import sr, srp, IP, UDP, ICMP, TCP, ARP, Ether 15 | 16 | RUN_FREQUENCY = 10 17 | 18 | scheduler = sched.scheduler(time.time, time.sleep) 19 | 20 | 21 | def detect_inactive_hosts(scan_hosts): 22 | """ 23 | Scans the network to find scan_hosts are live or dead 24 | scan_hosts can be like 10.0.2.2-4 to cover range. 25 | See Scapy docs for specifying targets. 26 | """ 27 | global scheduler 28 | scheduler.enter(RUN_FREQUENCY, 1, detect_inactive_hosts, (scan_hosts, )) 29 | inactive_hosts = [] 30 | try: 31 | ans, unans = sr(IP(dst=scan_hosts)/ICMP(), retry=0, timeout=1) 32 | ans.summary(lambda r : r.sprintf("%IP.src% is alive")) 33 | for inactive in unans: 34 | print ("%s is inactive" %inactive.dst) 35 | inactive_hosts.append(inactive.dst) 36 | 37 | print ("Total %d hosts are inactive" %(len(inactive_hosts))) 38 | 39 | 40 | except KeyboardInterrupt: 41 | exit(0) 42 | 43 | 44 | if __name__ == "__main__": 45 | parser = argparse.ArgumentParser(description='Python networking utils') 46 | parser.add_argument('--scan-hosts', action="store", dest="scan_hosts", required=True) 47 | given_args = parser.parse_args() 48 | scan_hosts = given_args.scan_hosts 49 | scheduler.enter(1, 1, detect_inactive_hosts, (scan_hosts, )) 50 | scheduler.run() 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /Chapter03/3_8_ipc_using_socketpairs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 3 3 | # This program is optimized for Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | # To make it run on Python 2.7.x, needs some changes due to API differences. 6 | # Follow the comments inline to make the program work with Python 2. 7 | 8 | import socket 9 | import os 10 | 11 | BUFSIZE = 1024 12 | 13 | def test_socketpair(): 14 | """ Test Unix socketpair""" 15 | parent, child = socket.socketpair() 16 | 17 | pid = os.fork() 18 | try: 19 | if pid: 20 | print ("@Parent, sending message...") 21 | child.close() 22 | 23 | parent.sendall(bytes("Hello from parent!", 'utf-8')) 24 | # Comment out the above line and uncomment the below line for Python 2.7. 25 | # parent.sendall("Hello from parent!") 26 | 27 | response = parent.recv(BUFSIZE) 28 | print ("Response from child:", response) 29 | parent.close() 30 | 31 | else: 32 | print ("@Child, waiting for message from parent") 33 | parent.close() 34 | message = child.recv(BUFSIZE) 35 | print ("Message from parent:", message) 36 | 37 | child.sendall(bytes("Hello from child!!", 'utf-8')) 38 | # Comment out the above line and uncomment the below line for Python 2.7. 39 | # child.sendall("Hello from child!!") 40 | 41 | child.close() 42 | except Exception as err: 43 | print ("Error: %s" %err) 44 | 45 | 46 | if __name__ == '__main__': 47 | test_socketpair() 48 | -------------------------------------------------------------------------------- /Chapter03/3_9a_unix_domain_socket_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 3 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | import socket 8 | import os 9 | import time 10 | 11 | SERVER_PATH = "/tmp/python_unix_socket_server" 12 | 13 | def run_unix_domain_socket_server(): 14 | if os.path.exists(SERVER_PATH): 15 | os.remove( SERVER_PATH ) 16 | 17 | print ("starting unix domain socket server.") 18 | server = socket.socket( socket.AF_UNIX, socket.SOCK_DGRAM ) 19 | server.bind(SERVER_PATH) 20 | 21 | print ("Listening on path: %s" %SERVER_PATH) 22 | while True: 23 | datagram = server.recv( 1024 ) 24 | if not datagram: 25 | break 26 | else: 27 | print ("-" * 20) 28 | print (datagram) 29 | if "DONE" == datagram: 30 | break 31 | print ("-" * 20) 32 | print ("Server is shutting down now...") 33 | server.close() 34 | os.remove(SERVER_PATH) 35 | print ("Server shutdown and path removed.") 36 | 37 | if __name__ == '__main__': 38 | run_unix_domain_socket_server() 39 | -------------------------------------------------------------------------------- /Chapter03/3_9b_unix_domain_socket_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 3 3 | # This program is optimized for Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | # To make it run on Python 2.7.x, needs some changes due to API differences. 6 | # Follow the comments inline to make the program work with Python 2. 7 | 8 | 9 | import socket 10 | import sys 11 | 12 | SERVER_PATH = "/tmp/python_unix_socket_server" 13 | 14 | def run_unix_domain_socket_client(): 15 | """ Run "a Unix domain socket client """ 16 | sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) 17 | 18 | # Connect the socket to the path where the server is listening 19 | server_address = SERVER_PATH 20 | print ("connecting to %s" % server_address) 21 | try: 22 | sock.connect(server_address) 23 | except socket.error as msg: 24 | print (msg) 25 | sys.exit(1) 26 | 27 | try: 28 | message = "This is the message. This will be echoed back!" 29 | print ("Sending [%s]" %message) 30 | 31 | sock.sendall(bytes(message, 'utf-8')) 32 | # Comment out the above line and uncomment the below line for Python 2.7. 33 | # sock.sendall(message) 34 | 35 | amount_received = 0 36 | amount_expected = len(message) 37 | 38 | while amount_received < amount_expected: 39 | data = sock.recv(16) 40 | amount_received += len(data) 41 | print ("Received [%s]" % data) 42 | 43 | finally: 44 | print ("Closing client") 45 | sock.close() 46 | 47 | if __name__ == '__main__': 48 | run_unix_domain_socket_client() 49 | -------------------------------------------------------------------------------- /Chapter03/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Network-Programming-Cookbook-Second-Edition/7a2618500cd7a3a4ff527751664bd9b39bb63a7a/Chapter03/__init__.py -------------------------------------------------------------------------------- /Chapter04/4_10_https_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook -- Chapter - 4 3 | # This program requires Python 3.5.2 or any later version 4 | # It may run on any other version with/without modifications. 5 | # 6 | # Follow the comments inline to make it run on Python 2.7.x. 7 | # Requires pyOpenSSL and SSL packages installed 8 | 9 | import socket, os 10 | from OpenSSL import SSL 11 | 12 | from socketserver import BaseServer 13 | from http.server import HTTPServer 14 | from http.server import SimpleHTTPRequestHandler 15 | # Comment out the above 3 lines and uncomment the below 3 lines for Python 2.7.x. 16 | #from SocketServer import BaseServer 17 | #from BaseHTTPServer import HTTPServer 18 | #from SimpleHTTPServer import SimpleHTTPRequestHandler 19 | 20 | 21 | class SecureHTTPServer(HTTPServer): 22 | def __init__(self, server_address, HandlerClass): 23 | BaseServer.__init__(self, server_address, HandlerClass) 24 | ctx = SSL.Context(SSL.SSLv23_METHOD) 25 | fpem = 'server.pem' # location of the server private key and the server certificate 26 | ctx.use_privatekey_file (fpem) 27 | ctx.use_certificate_file(fpem) 28 | self.socket = SSL.Connection(ctx, socket.socket(self.address_family, 29 | self.socket_type)) 30 | self.server_bind() 31 | self.server_activate() 32 | 33 | 34 | class SecureHTTPRequestHandler(SimpleHTTPRequestHandler): 35 | def setup(self): 36 | self.connection = self.request 37 | self.rfile = socket._fileobject(self.request, "rb", self.rbufsize) 38 | self.wfile = socket._fileobject(self.request, "wb", self.wbufsize) 39 | 40 | 41 | def run_server(HandlerClass = SecureHTTPRequestHandler, 42 | ServerClass = SecureHTTPServer): 43 | server_address = ('', 4443) # port needs to be accessible by user 44 | server = ServerClass(server_address, HandlerClass) 45 | running_address = server.socket.getsockname() 46 | print ("Serving HTTPS Server on %s:%s ..." %(running_address[0], running_address[1])) 47 | server.serve_forever() 48 | 49 | 50 | if __name__ == '__main__': 51 | run_server() 52 | 53 | -------------------------------------------------------------------------------- /Chapter04/4_11_twisted_async_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 3 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | from twisted.internet import reactor, protocol, endpoints 8 | from twisted.protocols import basic 9 | 10 | class PubProtocol(basic.LineReceiver): 11 | def __init__(self, factory): 12 | self.factory = factory 13 | 14 | def connectionMade(self): 15 | self.factory.clients.add(self) 16 | 17 | def connectionLost(self, reason): 18 | self.factory.clients.remove(self) 19 | 20 | def lineReceived(self, line): 21 | for c in self.factory.clients: 22 | source = u"<{}> ".format(self.transport.getHost()).encode("ascii") 23 | c.sendLine(source + line) 24 | 25 | class PubFactory(protocol.Factory): 26 | def __init__(self): 27 | self.clients = set() 28 | 29 | def buildProtocol(self, addr): 30 | return PubProtocol(self) 31 | 32 | 33 | if __name__ == '__main__': 34 | parser = argparse.ArgumentParser(description='Socket Server Example with Epoll') 35 | parser.add_argument('--port', action="store", dest="port", type=int, required=True) 36 | given_args = parser.parse_args() 37 | port = given_args.port 38 | endpoints.serverFromString(reactor, "tcp:%s" %port).listen(PubFactory()) 39 | reactor.run() 40 | 41 | -------------------------------------------------------------------------------- /Chapter04/4_12_tornado_async_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 3 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | import tornado.ioloop 8 | import tornado.httpclient 9 | 10 | 11 | class TornadoAsync(): 12 | def handle_request(self,response): 13 | if response.error: 14 | print ("Error:", response.error) 15 | else: 16 | print (response.body) 17 | tornado.ioloop.IOLoop.instance().stop() 18 | 19 | def run_server(url): 20 | tornadoAsync = TornadoAsync() 21 | http_client = tornado.httpclient.AsyncHTTPClient() 22 | http_client.fetch(url, tornadoAsync.handle_request) 23 | tornado.ioloop.IOLoop.instance().start() 24 | 25 | if __name__ == '__main__': 26 | parser = argparse.ArgumentParser(description='Async Server Example') 27 | parser.add_argument('--url', action="store", dest="url", type=str, required=True) 28 | given_args = parser.parse_args() 29 | url = given_args.url 30 | run_server(url) 31 | -------------------------------------------------------------------------------- /Chapter04/4_13_tornado_conc_future.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 3 3 | # This program is optimized for Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | import time 8 | import datetime 9 | 10 | import tornado.httpserver 11 | import tornado.ioloop 12 | import tornado.options 13 | import tornado.web 14 | 15 | from tornado import gen 16 | from tornado.concurrent import return_future 17 | 18 | class AsyncUser(object): 19 | @return_future 20 | def req1(self, callback=None): 21 | time.sleep(0.1) 22 | result = datetime.datetime.utcnow() 23 | callback(result) 24 | 25 | @return_future 26 | def req2(self, callback=None): 27 | time.sleep(0.2) 28 | result = datetime.datetime.utcnow() 29 | callback(result) 30 | 31 | 32 | 33 | class Application(tornado.web.Application): 34 | def __init__(self): 35 | handlers = [ 36 | (r"/", UserHandler), 37 | ] 38 | tornado.web.Application.__init__(self, handlers) 39 | 40 | 41 | class UserHandler(tornado.web.RequestHandler): 42 | @gen.coroutine 43 | def get(self): 44 | user = AsyncUser() 45 | response1 = yield (user.req1()) 46 | response2 = yield (user.req2()) 47 | print ("response1,2: %s %s" %(response1, response2)) 48 | self.finish() 49 | 50 | def main(port): 51 | http_server = tornado.httpserver.HTTPServer(Application()) 52 | print("Server listening at Port: ", port) 53 | http_server.listen(port) 54 | tornado.ioloop.IOLoop.instance().start() 55 | 56 | 57 | if __name__ == "__main__": 58 | parser = argparse.ArgumentParser(description='Async Server Example') 59 | parser.add_argument('--port', action="store", dest="port", type=int, required=True) 60 | given_args = parser.parse_args() 61 | port = given_args.port 62 | main(port) 63 | -------------------------------------------------------------------------------- /Chapter04/4_1_download_data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook -- Chapter - 4 3 | # This program requires Python 3.5.2 or any later version 4 | # It may run on any other version with/without modifications. 5 | # 6 | # Follow the comments inline to make it run on Python 2.7.x. 7 | 8 | import argparse 9 | 10 | import urllib.request 11 | # Comment out the above line and uncomment the below for Python 2.7.x. 12 | #import urllib2 13 | 14 | REMOTE_SERVER_HOST = 'http://www.cnn.com' 15 | 16 | class HTTPClient: 17 | 18 | def __init__(self, host): 19 | self.host = host 20 | 21 | def fetch(self): 22 | response = urllib.request.urlopen(self.host) 23 | # Comment out the above line and uncomment the below for Python 2.7.x. 24 | #response = urllib2.urlopen(self.host) 25 | 26 | data = response.read() 27 | text = data.decode('utf-8') 28 | return text 29 | 30 | if __name__ == "__main__": 31 | parser = argparse.ArgumentParser(description='HTTP Client Example') 32 | parser.add_argument('--host', action="store", dest="host", default=REMOTE_SERVER_HOST) 33 | 34 | given_args = parser.parse_args() 35 | host = given_args.host 36 | client = HTTPClient(host) 37 | print (client.fetch()) 38 | 39 | -------------------------------------------------------------------------------- /Chapter04/4_2_simple_http_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook -- Chapter - 4 3 | # This program requires Python 3.5.2 or any later version 4 | # It may run on any other version with/without modifications. 5 | # 6 | # Follow the comments inline to make it run on Python 2.7.x. 7 | 8 | 9 | import argparse 10 | import sys 11 | 12 | from http.server import BaseHTTPRequestHandler, HTTPServer 13 | # Comment out the above line and uncomment the below for Python 2.7.x. 14 | #from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer 15 | 16 | DEFAULT_HOST = '127.0.0.1' 17 | DEFAULT_PORT = 8800 18 | 19 | 20 | class RequestHandler(BaseHTTPRequestHandler): 21 | """ Custom request handler""" 22 | 23 | def do_GET(self): 24 | """ Handler for the GET requests """ 25 | self.send_response(200) 26 | self.send_header('Content-type','text/html') 27 | self.end_headers() 28 | # Send the message to browser 29 | self.wfile.write("Hello from server!") 30 | return 31 | 32 | 33 | class CustomHTTPServer(HTTPServer): 34 | "A custom HTTP server" 35 | def __init__(self, host, port): 36 | server_address = (host, port) 37 | HTTPServer.__init__(self, server_address, RequestHandler) 38 | 39 | 40 | def run_server(port): 41 | try: 42 | server= CustomHTTPServer(DEFAULT_HOST, port) 43 | print ("Custom HTTP server started on port: %s" % port) 44 | server.serve_forever() 45 | except Exception as err: 46 | print ("Error:%s" %err) 47 | except KeyboardInterrupt: 48 | print ("Server interrupted and is shutting down...") 49 | server.socket.close() 50 | 51 | 52 | if __name__ == "__main__": 53 | parser = argparse.ArgumentParser(description='Simple HTTP Server Example') 54 | parser.add_argument('--port', action="store", dest="port", type=int, default=DEFAULT_PORT) 55 | given_args = parser.parse_args() 56 | port = given_args.port 57 | run_server(port) 58 | -------------------------------------------------------------------------------- /Chapter04/4_3_extract_cookie_information.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook -- Chapter - 4 3 | # This program requires Python 3.5.2 or any later version 4 | # It may run on any other version with/without modifications. 5 | # 6 | # Follow the comments inline to make it run on Python 2.7.x. 7 | 8 | import http.cookiejar 9 | # Comment out the above line and uncomment the below for Python 2.7.x. 10 | #import cookielib 11 | 12 | import urllib 13 | 14 | # Uncomment the below line for Python 2.7.x. 15 | #import urllib2 16 | 17 | 18 | ID_USERNAME = 'id_username' 19 | ID_PASSWORD = 'id_password' 20 | USERNAME = 'you@email.com' 21 | PASSWORD = 'mypassword' 22 | LOGIN_URL = 'https://bitbucket.org/account/signin/?next=/' 23 | NORMAL_URL = 'https://bitbucket.org/' 24 | 25 | def extract_cookie_info(): 26 | """ Fake login to a site with cookie""" 27 | # setup cookie jar 28 | 29 | cj = http.cookiejar.CookieJar() 30 | # Comment out the above line and uncomment the below for Python 2.7.x. 31 | #cj = cookielib.CookieJar() 32 | 33 | login_data = urllib.parse.urlencode({ID_USERNAME : USERNAME, ID_PASSWORD : PASSWORD}).encode("utf-8") 34 | # Comment out the above line and uncomment the below for Python 2.7.x. 35 | #login_data = urllib.urlencode({ID_USERNAME : USERNAME, ID_PASSWORD : PASSWORD}) 36 | 37 | # create url opener 38 | 39 | opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj)) 40 | # Comment out the above line and uncomment the below for Python 2.7.x. 41 | #opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) 42 | 43 | resp = opener.open(LOGIN_URL, login_data) 44 | 45 | # send login info 46 | for cookie in cj: 47 | print ("----First time cookie: %s --> %s" %(cookie.name, cookie.value)) 48 | print ("Headers: %s" %resp.headers) 49 | 50 | # now access without any login info 51 | resp = opener.open(NORMAL_URL) 52 | for cookie in cj: 53 | print ("++++Second time cookie: %s --> %s" %(cookie.name, cookie.value)) 54 | 55 | print ("Headers: %s" %resp.headers) 56 | 57 | if __name__ == '__main__': 58 | extract_cookie_info() 59 | -------------------------------------------------------------------------------- /Chapter04/4_4_submit_web_form.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook -- Chapter - 4 3 | # This program requires Python 3.5.2 or any later version 4 | # It may run on any other version with/without modifications. 5 | # 6 | # Follow the comments inline to make it run on Python 2.7.x. 7 | 8 | 9 | import requests 10 | import urllib 11 | 12 | # Uncomment the below line for Python 2.7.x. 13 | #import urllib2 14 | 15 | ID_USERNAME = 'signup-user-name' 16 | ID_EMAIL = 'signup-user-email' 17 | ID_PASSWORD = 'signup-user-password' 18 | USERNAME = 'username' 19 | EMAIL = 'you@email.com' 20 | PASSWORD = 'yourpassword' 21 | SIGNUP_URL = 'https://twitter.com/account/create' 22 | 23 | 24 | def submit_form(): 25 | """Submit a form""" 26 | payload = {ID_USERNAME : USERNAME, 27 | ID_EMAIL : EMAIL, 28 | ID_PASSWORD : PASSWORD,} 29 | 30 | # make a get request 31 | resp = requests.get(SIGNUP_URL) 32 | print ("Response to GET request: %s" %resp.content) 33 | 34 | # send POST request 35 | resp = requests.post(SIGNUP_URL, payload) 36 | print ("Headers from a POST request response: %s" %resp.headers) 37 | 38 | 39 | if __name__ == '__main__': 40 | submit_form() 41 | 42 | -------------------------------------------------------------------------------- /Chapter04/4_5_proxy_web_request.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook -- Chapter - 4 3 | # This program requires Python 3.5.2 or any later version 4 | # It may run on any other version with/without modifications. 5 | # 6 | # Follow the comments inline to make it run on Python 2.7.x. 7 | 8 | import urllib.request, urllib.parse, urllib.error 9 | # Comment out the above line and uncomment the below for Python 2.7.x. 10 | #import urllib 11 | 12 | URL = 'https://www.github.com' 13 | PROXY_ADDRESS = "165.24.10.8:8080" # By Googling free proxy server 14 | 15 | 16 | if __name__ == '__main__': 17 | 18 | proxy = urllib.request.ProxyHandler({"http" : PROXY_ADDRESS}) 19 | opener = urllib.request.build_opener(proxy) 20 | urllib.request.install_opener(opener) 21 | resp = urllib.request.urlopen(URL) 22 | # Comment out the above 4 lines and uncomment the below for Python 2.7.x. 23 | #resp = urllib.urlopen(URL, proxies = {"http" : PROXY_ADDRESS}) 24 | 25 | print ("Proxy server returns response headers: %s " %resp.headers) 26 | 27 | -------------------------------------------------------------------------------- /Chapter04/4_6_checking_webpage_with_HEAD_request.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook -- Chapter - 4 3 | # This program requires Python 3.5.2 or any later version 4 | # It may run on any other version with/without modifications. 5 | # 6 | # Follow the comments inline to make it run on Python 2.7.x. 7 | 8 | import argparse 9 | 10 | import http.client 11 | # Comment out the above line and uncomment the below for Python 2.7.x. 12 | #import httplib 13 | 14 | import urllib.parse 15 | # Comment out the above line and uncomment the below for Python 2.7.x. 16 | #import urlparse 17 | 18 | import re 19 | import urllib.request, urllib.error 20 | # Comment out the above line and uncomment the below for Python 2.7.x. 21 | #import urllib 22 | 23 | DEFAULT_URL = 'http://www.python.org' 24 | 25 | HTTP_GOOD_CODES = [http.client.OK, http.client.FOUND, http.client.MOVED_PERMANENTLY] 26 | # Comment out the above line and uncomment the below for Python 2.7.x. 27 | #HTTP_GOOD_CODES = [httplib.OK, httplib.FOUND, httplib.MOVED_PERMANENTLY] 28 | 29 | def get_server_status_code(url): 30 | """ 31 | Download just the header of a URL and 32 | return the server's status code. 33 | """ 34 | host, path = urllib.parse.urlparse(url)[1:3] 35 | # Comment out the above line and uncomment the below for Python 2.7.x. 36 | #host, path = urlparse.urlparse(url)[1:3] 37 | try: 38 | conn = http.client.HTTPConnection(host) 39 | # Comment out the above line and uncomment the below for Python 2.7.x. 40 | #conn = httplib.HTTPConnection(host) 41 | 42 | conn.request('HEAD', path) 43 | return conn.getresponse().status 44 | 45 | except Exception as e: 46 | print ("Server: %s status is: %s " %(url, e)) 47 | # Comment out the above line and uncomment the below for Python 2.7.x. 48 | #except StandardError: 49 | return None 50 | 51 | if __name__ == '__main__': 52 | parser = argparse.ArgumentParser(description='Example HEAD Request') 53 | parser.add_argument('--url', action="store", dest="url", default=DEFAULT_URL) 54 | given_args = parser.parse_args() 55 | url = given_args.url 56 | if get_server_status_code(url) in HTTP_GOOD_CODES: 57 | print ("Server: %s status is OK: %s " %(url, get_server_status_code(url))) 58 | else: 59 | print ("Server: %s status is NOT OK: %s" %(url, get_server_status_code(url))) 60 | -------------------------------------------------------------------------------- /Chapter04/4_7_spoof_mozilla_firefox_in_client_code.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook -- Chapter - 4 3 | # This program requires Python 3.5.2 or any later version 4 | # It may run on any other version with/without modifications. 5 | # 6 | # Follow the comments inline to make it run on Python 2.7.x. 7 | 8 | import urllib.request, urllib.error, urllib.parse 9 | # Comment out the above line and uncomment the below for Python 2.7.x. 10 | #import urllib2 11 | 12 | BROWSER = 'Mozilla/5.0 (Windows NT 5.1; rv:20.0) Gecko/20100101 Firefox/20.0' 13 | URL = 'http://www.python.org' 14 | 15 | def spoof_firefox(): 16 | 17 | opener = urllib.request.build_opener() 18 | # Comment out the above line and uncomment the below for Python 2.7.x. 19 | #opener = urllib2.build_opener() 20 | 21 | opener.addheaders = [('User-agent', BROWSER)] 22 | result = opener.open(URL) 23 | print ("Response headers:") 24 | 25 | for header in result.headers: 26 | # Comment out the above line and uncomment the below for Python 2.7.x. 27 | #for header in result.headers.headers: 28 | print ("%s: %s" %(header, result.headers.get(header))) 29 | # Comment out the above line and uncomment the below for Python 2.7.x. 30 | #print (header) 31 | if __name__ == '__main__': 32 | spoof_firefox() 33 | 34 | -------------------------------------------------------------------------------- /Chapter04/4_8_http_compression.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook -- Chapter - 4 3 | # This program requires Python 3.5.2 or any later version 4 | # It may run on any other version with/without modifications. 5 | # 6 | # Follow the comments inline to make it run on Python 2.7.x. 7 | 8 | import argparse 9 | import string 10 | import os 11 | import sys 12 | import gzip 13 | 14 | import io 15 | # Comment out the above line and uncomment the below for Python 2.7.x. 16 | #import cStringIO 17 | 18 | from http.server import BaseHTTPRequestHandler, HTTPServer 19 | # Comment out the above line and uncomment the below for Python 2.7.x. 20 | #from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer 21 | 22 | DEFAULT_HOST = '127.0.0.1' 23 | DEFAULT_PORT = 8800 24 | 25 | HTML_CONTENT = b"""

Compressed Hello World!

""" 26 | # Comment out the above line and uncomment the below for Python 2.7.x. 27 | #HTML_CONTENT = b"""

Compressed Hello World!

""" 28 | 29 | class RequestHandler(BaseHTTPRequestHandler): 30 | """ Custom request handler""" 31 | 32 | def do_GET(self): 33 | """ Handler for the GET requests """ 34 | self.send_response(200) 35 | self.send_header('Content-type','text/html') 36 | self.send_header('Content-Encoding','gzip') 37 | zbuf = self.compress_buffer(HTML_CONTENT) 38 | sys.stdout.write("Content-Encoding: gzip\r\n") 39 | self.send_header('Content-Length',len(zbuf)) 40 | self.end_headers() 41 | # Send the message to browser 42 | zbuf = self.compress_buffer(HTML_CONTENT) 43 | sys.stdout.write("Content-Encoding: gzip\r\n") 44 | sys.stdout.write("Content-Length: %d\r\n" % (len(zbuf))) 45 | sys.stdout.write("\r\n") 46 | 47 | self.wfile.write(zbuf) 48 | 49 | return 50 | 51 | def compress_buffer(self, buf): 52 | 53 | zbuf = io.BytesIO() 54 | # Comment out the above line and uncomment the below for Python 2.7.x. 55 | #zbuf = cStringIO.StringIO() 56 | 57 | zfile = gzip.GzipFile(mode = 'wb', fileobj = zbuf, compresslevel = 6) 58 | zfile.write(buf) 59 | zfile.close() 60 | return zbuf.getvalue() 61 | 62 | 63 | if __name__ == '__main__': 64 | parser = argparse.ArgumentParser(description='Simple HTTP Server Example') 65 | parser.add_argument('--port', action="store", dest="port", type=int, default=DEFAULT_PORT) 66 | given_args = parser.parse_args() 67 | port = given_args.port 68 | server_address = (DEFAULT_HOST, port) 69 | server = HTTPServer(server_address, RequestHandler) 70 | server.serve_forever() 71 | 72 | -------------------------------------------------------------------------------- /Chapter04/4_9_http_fail_over_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook -- Chapter - 4 3 | # This program requires Python 3.5.2 or any later version 4 | # It may run on any other version with/without modifications. 5 | # 6 | # Follow the comments inline to make it run on Python 2.7.x. 7 | 8 | import urllib.request, urllib.parse, urllib.error 9 | # Comment out the above line and uncomment the below for Python 2.7.x. 10 | #import urllib 11 | 12 | import os 13 | 14 | TARGET_URL = 'http://python.org/ftp/python/2.7.4/' 15 | TARGET_FILE = 'Python-2.7.4.tgz' 16 | 17 | class CustomURLOpener(urllib.request.FancyURLopener): 18 | # Comment out the above line and uncomment the below for Python 2.7.x. 19 | #class CustomURLOpener(urllib.FancyURLopener): 20 | """Override FancyURLopener to skip error 206 (when a 21 | partial file is being sent) 22 | """ 23 | def http_error_206(self, url, fp, errcode, errmsg, headers, data=None): 24 | pass 25 | 26 | def resume_download(): 27 | file_exists = False 28 | CustomURLClass = CustomURLOpener() 29 | if os.path.exists(TARGET_FILE): 30 | out_file = open(TARGET_FILE,"ab") 31 | file_exists = os.path.getsize(TARGET_FILE) 32 | #If the file exists, then only download the unfinished part 33 | CustomURLClass.addheader("range","bytes=%s-" % (file_exists)) 34 | else: 35 | out_file = open(TARGET_FILE,"wb") 36 | 37 | web_page = CustomURLClass.open(TARGET_URL + TARGET_FILE) 38 | 39 | #Check if last download was OK 40 | if int(web_page.headers['Content-Length']) == file_exists: 41 | loop = 0 42 | print ("File already downloaded!") 43 | 44 | byte_count = 0 45 | while True: 46 | data = web_page.read(8192) 47 | if not data: 48 | break 49 | out_file.write(data) 50 | byte_count = byte_count + len(data) 51 | 52 | web_page.close() 53 | out_file.close() 54 | 55 | for k,v in list(web_page.headers.items()): 56 | # Comment out the above line and uncomment the below for Python 2.7.x. 57 | #for k,v in web_page.headers.items(): 58 | print (k, "=",v) 59 | print ("File copied", byte_count, "bytes from", web_page.url) 60 | 61 | if __name__ == '__main__': 62 | resume_download() 63 | -------------------------------------------------------------------------------- /Chapter04/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Network-Programming-Cookbook-Second-Edition/7a2618500cd7a3a4ff527751664bd9b39bb63a7a/Chapter04/__init__.py -------------------------------------------------------------------------------- /Chapter05/5_10_secure_mail_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 5 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import smtplib 7 | from email.mime.multipart import MIMEMultipart 8 | from email.mime.text import MIMEText 9 | import argparse 10 | import getpass 11 | 12 | def mail_client(host, port, fromAddress, password, toAddress, subject, body): 13 | msg = MIMEMultipart() 14 | 15 | msg['From'] = fromAddress 16 | msg['To'] = toAddress 17 | msg['Subject'] = subject 18 | message = body 19 | msg.attach(MIMEText(message)) 20 | 21 | mailserver = smtplib.SMTP(host,port) 22 | 23 | # Identify to the SMTP Gmail Client 24 | mailserver.ehlo() 25 | 26 | # Secure with TLS Encryption 27 | mailserver.starttls() 28 | 29 | # Reidentifying as an encrypted connection 30 | mailserver.ehlo() 31 | mailserver.login(fromAddress, password) 32 | 33 | mailserver.sendmail(fromAddress,toAddress,msg.as_string()) 34 | print ("Email sent from:", fromAddress) 35 | 36 | mailserver.quit() 37 | 38 | 39 | 40 | if __name__ == '__main__': 41 | parser = argparse.ArgumentParser(description='Mail Server Example') 42 | parser.add_argument('--host', action="store", dest="host", type=str, required=True) 43 | parser.add_argument('--port', action="store", dest="port", type=int, required=True) 44 | parser.add_argument('--fromAddress', action="store", dest="fromAddress", type=str, required=True) 45 | parser.add_argument('--toAddress', action="store", dest="toAddress", type=str, required=True) 46 | parser.add_argument('--subject', action="store", dest="subject", type=str, required=True) 47 | parser.add_argument('--body', action="store", dest="body", type=str, required=True) 48 | password = getpass.getpass("Enter your Password:") 49 | given_args = parser.parse_args() 50 | mail_client(given_args.host, given_args.port, given_args.fromAddress, password, given_args.toAddress, given_args.subject, given_args.body) 51 | 52 | -------------------------------------------------------------------------------- /Chapter05/5_11_pop3_mail_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 5 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import getpass 7 | import poplib 8 | import argparse 9 | 10 | def mail_client(host, port, user, password): 11 | Mailbox = poplib.POP3_SSL(host, port) 12 | Mailbox.user(user) 13 | Mailbox.pass_(password) 14 | numMessages = len(Mailbox.list()[1]) 15 | print (Mailbox.retr(1)[1]) 16 | Mailbox.quit() 17 | 18 | 19 | if __name__ == '__main__': 20 | parser = argparse.ArgumentParser(description='Mail Server Example') 21 | parser.add_argument('--host', action="store", dest="host", type=str, required=True) 22 | parser.add_argument('--port', action="store", dest="port", type=int, required=True) 23 | parser.add_argument('--user', action="store", dest="user", type=str, required=True) 24 | password = getpass.getpass("Enter your Password:") 25 | given_args = parser.parse_args() 26 | mail_client(given_args.host, given_args.port, given_args.user, password) 27 | 28 | -------------------------------------------------------------------------------- /Chapter05/5_1_list_files_on_ftp_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 5 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | FTP_SERVER_URL = 'ftp.ed.ac.uk' 8 | 9 | import ftplib 10 | from ftplib import FTP 11 | 12 | def test_ftp_connection(path, username, email): 13 | #Open ftp connection 14 | ftp = ftplib.FTP(path, username, email) 15 | 16 | #List the files in the /pub directory 17 | ftp.cwd("/pub") 18 | print ("File list at %s:" %path) 19 | files = ftp.dir() 20 | print (files) 21 | 22 | ftp.quit() 23 | 24 | if __name__ == '__main__': 25 | test_ftp_connection(path=FTP_SERVER_URL, username='anonymous', 26 | email='nobody@nourl.com', 27 | ) 28 | -------------------------------------------------------------------------------- /Chapter05/5_2_upload_file_to_ftp_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 5 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import os 7 | import argparse 8 | import ftplib 9 | import getpass 10 | 11 | LOCAL_FTP_SERVER = 'localhost' 12 | LOCAL_FILE = 'readme.txt' 13 | 14 | def ftp_upload(ftp_server, username, password, file_name): 15 | print ("Connecting to FTP server: %s" %ftp_server) 16 | ftp = ftplib.FTP(ftp_server) 17 | print ("Login to FTP server: user=%s" %username) 18 | ftp.login(username, password) 19 | ext = os.path.splitext(file_name)[1] 20 | if ext in (".txt", ".htm", ".html"): 21 | ftp.storlines("STOR " + file_name, open(file_name)) 22 | else: 23 | ftp.storbinary("STOR " + file_name, open(file_name, "rb"), 1024) 24 | print ("Uploaded file: %s" %file_name) 25 | 26 | 27 | if __name__ == '__main__': 28 | parser = argparse.ArgumentParser(description='FTP Server Upload Example') 29 | parser.add_argument('--ftp-server', action="store", dest="ftp_server", default=LOCAL_FTP_SERVER) 30 | parser.add_argument('--file-name', action="store", dest="file_name", default=LOCAL_FILE) 31 | parser.add_argument('--username', action="store", dest="username", default=getpass.getuser()) 32 | given_args = parser.parse_args() 33 | ftp_server, file_name, username = given_args.ftp_server, given_args.file_name, given_args.username 34 | password = getpass.getpass(prompt="Enter you FTP password: ") 35 | ftp_upload(ftp_server, username, password, file_name) 36 | 37 | -------------------------------------------------------------------------------- /Chapter05/5_3_email_current_dir_zipped.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 5 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import os 7 | import argparse 8 | import smtplib 9 | import zipfile 10 | import tempfile 11 | from email import encoders 12 | from email.mime.base import MIMEBase 13 | from email.mime.multipart import MIMEMultipart 14 | 15 | def email_dir_zipped(sender, recipient): 16 | zf = tempfile.TemporaryFile(prefix='mail', suffix='.zip') 17 | zip = zipfile.ZipFile(zf, 'w') 18 | print ("Zipping current dir: %s" %os.getcwd()) 19 | for file_name in os.listdir(os.getcwd()): 20 | zip.write(file_name) 21 | zip.close() 22 | zf.seek(0) 23 | 24 | # Create the message 25 | print ("Creating email message...") 26 | email_msg = MIMEMultipart() 27 | email_msg['Subject'] = 'File from path %s' %os.getcwd() 28 | email_msg['To'] = ', '.join(recipient) 29 | email_msg['From'] = sender 30 | email_msg.preamble = 'Testing email from Python.\n' 31 | msg = MIMEBase('application', 'zip') 32 | msg.set_payload(zf.read()) 33 | encoders.encode_base64(msg) 34 | msg.add_header('Content-Disposition', 'attachment', 35 | filename=os.getcwd()[-1] + '.zip') 36 | email_msg.attach(msg) 37 | email_msg = email_msg.as_string() 38 | 39 | # send the message 40 | print ("Sending email message...") 41 | try: 42 | smtp = smtplib.SMTP('localhost') 43 | smtp.set_debuglevel(1) 44 | smtp.sendmail(sender, recipient, email_msg) 45 | except Exception as e: 46 | print ("Error: %s" %str(e)) 47 | finally: 48 | smtp.close() 49 | 50 | if __name__ == '__main__': 51 | parser = argparse.ArgumentParser(description='Email Example') 52 | parser.add_argument('--sender', action="store", dest="sender", default='you@you.com') 53 | parser.add_argument('--recipient', action="store", dest="recipient") 54 | given_args = parser.parse_args() 55 | email_dir_zipped(given_args.sender, given_args.recipient) 56 | -------------------------------------------------------------------------------- /Chapter05/5_4_download_google_email_via_pop3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 5 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | import getpass 8 | import poplib 9 | 10 | GOOGLE_POP3_SERVER = 'pop.googlemail.com' 11 | 12 | def download_email(username): 13 | mailbox = poplib.POP3_SSL(GOOGLE_POP3_SERVER, '995') 14 | mailbox.user(username) 15 | password = getpass.getpass(prompt="Enter your Google password: ") 16 | mailbox.pass_(password) 17 | num_messages = len(mailbox.list()[1]) 18 | print ("Total emails: %s" %num_messages) 19 | print ("Getting last message") 20 | for msg in mailbox.retr(num_messages)[1]: 21 | print (msg) 22 | mailbox.quit() 23 | 24 | if __name__ == '__main__': 25 | parser = argparse.ArgumentParser(description='Email Download Example') 26 | parser.add_argument('--username', action="store", dest="username", default=getpass.getuser()) 27 | given_args = parser.parse_args() 28 | username = given_args.username 29 | download_email(username) 30 | -------------------------------------------------------------------------------- /Chapter05/5_5_check_remote_email_via_imap.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 5 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | import getpass 8 | import imaplib 9 | 10 | GOOGLE_IMAP_SERVER = 'imap.googlemail.com' 11 | 12 | def check_email(username): 13 | mailbox = imaplib.IMAP4_SSL(GOOGLE_IMAP_SERVER, '993') 14 | password = getpass.getpass(prompt="Enter your Google password: ") 15 | mailbox.login(username, password) 16 | mailbox.select('Inbox') 17 | typ, data = mailbox.search(None, 'ALL') 18 | for num in data[0].split(): 19 | typ, data = mailbox.fetch(num, '(RFC822)') 20 | print ('Message %s\n%s\n' % (num, data[0][1])) 21 | break 22 | mailbox.close() 23 | mailbox.logout() 24 | 25 | 26 | if __name__ == '__main__': 27 | parser = argparse.ArgumentParser(description='Email Download Example') 28 | parser.add_argument('--username', action="store", dest="username", default=getpass.getuser()) 29 | given_args = parser.parse_args() 30 | username = given_args.username 31 | check_email(username) 32 | -------------------------------------------------------------------------------- /Chapter05/5_6_send_email_from_gmail.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 5 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | import os 8 | import getpass 9 | import re 10 | import sys 11 | import smtplib 12 | 13 | from email.mime.image import MIMEImage 14 | from email.mime.multipart import MIMEMultipart 15 | from email.mime.text import MIMEText 16 | 17 | SMTP_SERVER = 'smtp.gmail.com' 18 | SMTP_PORT = 587 19 | 20 | def send_email(sender, recipient): 21 | """ Send email message """ 22 | msg = MIMEMultipart() 23 | msg['Subject'] = 'Python Emaill Test' 24 | msg['To'] = recipient 25 | msg['From'] = sender 26 | subject = 'Python email Test' 27 | message = 'Images attached.' 28 | # attach imgae files 29 | files = os.listdir(os.getcwd()) 30 | gifsearch = re.compile(".gif", re.IGNORECASE) 31 | files = filter(gifsearch.search, files) 32 | for filename in files: 33 | path = os.path.join(os.getcwd(), filename) 34 | if not os.path.isfile(path): 35 | continue 36 | img = MIMEImage(open(path, 'rb').read(), _subtype="gif") 37 | img.add_header('Content-Disposition', 'attachment', filename=filename) 38 | msg.attach(img) 39 | 40 | part = MIMEText('text', "plain") 41 | part.set_payload(message) 42 | msg.attach(part) 43 | 44 | # create smtp session 45 | session = smtplib.SMTP(SMTP_SERVER, SMTP_PORT) 46 | session.ehlo() 47 | session.starttls() 48 | session.ehlo 49 | password = getpass.getpass(prompt="Enter your Google password: ") 50 | session.login(sender, password) 51 | session.sendmail(sender, recipient, msg.as_string()) 52 | print ("Email sent.") 53 | session.quit() 54 | 55 | if __name__ == '__main__': 56 | parser = argparse.ArgumentParser(description='Email Sending Example') 57 | parser.add_argument('--sender', action="store", dest="sender") 58 | parser.add_argument('--recipient', action="store", dest="recipient") 59 | given_args = parser.parse_args() 60 | send_email(given_args.sender, given_args.recipient) 61 | -------------------------------------------------------------------------------- /Chapter05/5_7_cgi_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook -- Chapter - 5 3 | # This program requires Python 3.5.2 or any later version 4 | # It may run on any other version with/without modifications. 5 | # 6 | # Follow the comments inline to make it run on Python 2.7.x. 7 | 8 | import os 9 | import cgi 10 | import argparse 11 | 12 | import http.server 13 | # Comment out the above line and uncomment the below for Python 2.7.x. 14 | #import BaseHTTPServer 15 | 16 | # Uncomment the below line for Python 2.7.x. 17 | #import CGIHTTPServer 18 | 19 | import cgitb 20 | cgitb.enable() ## enable CGI error reporting 21 | 22 | 23 | def web_server(port): 24 | 25 | server = http.server.HTTPServer 26 | # Comment out the above line and uncomment the below for Python 2.7.x. 27 | #server = BaseHTTPServer.HTTPServer 28 | 29 | handler = http.server.CGIHTTPRequestHandler #RequestsHandler 30 | # Comment out the above line and uncomment the below for Python 2.7.x. 31 | #handler = CGIHTTPServer.CGIHTTPRequestHandler #RequestsHandler 32 | 33 | server_address = ("", port) 34 | handler.cgi_directories = ["/cgi-bin", ] 35 | httpd = server(server_address, handler) 36 | print ("Starting web server with CGI support on port: %s ..." %port) 37 | httpd.serve_forever() 38 | 39 | if __name__ == '__main__': 40 | parser = argparse.ArgumentParser(description='CGI Server Example') 41 | parser.add_argument('--port', action="store", dest="port", type=int, required=True) 42 | given_args = parser.parse_args() 43 | web_server(given_args.port) 44 | 45 | -------------------------------------------------------------------------------- /Chapter05/5_7_send_feedback.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | Name:
5 | Comment: 6 | 7 |
8 | 9 | -------------------------------------------------------------------------------- /Chapter05/5_8_verify_email.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 5 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import re 7 | import smtplib 8 | import dns.resolver 9 | import argparse 10 | 11 | 12 | def mail_checker(fromAddress, toAddress): 13 | 14 | regex = '^[a-z0-9][a-z0-9._%+-]{0,63}@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$' 15 | 16 | addressToVerify = str(toAddress) 17 | 18 | match = re.match(regex, addressToVerify) 19 | if match == None: 20 | print('Bad Syntax in the address to verify. Re-enter the correct value') 21 | raise ValueError('Bad Syntax') 22 | 23 | splitAddress = addressToVerify.split('@') 24 | domain = str(splitAddress[1]) 25 | 26 | records = dns.resolver.query(domain, 'MX') 27 | mxRecord = records[0].exchange 28 | mxRecord = str(mxRecord) 29 | 30 | 31 | server = smtplib.SMTP() 32 | server.set_debuglevel(1) 33 | 34 | try: 35 | server.connect(mxRecord) 36 | except Exception as e: 37 | print ("Mail Check Failed Due to Error: %s" %str(e)) 38 | return 39 | 40 | server.helo(server.local_hostname) 41 | server.mail(fromAddress) 42 | code, message = server.rcpt(str(addressToVerify)) 43 | server.quit() 44 | 45 | if code == 250: 46 | print('Successfully verified the email: %s', fromAddress) 47 | else: 48 | print('Failed to verify the email: %s', fromAddress) 49 | 50 | 51 | 52 | if __name__ == '__main__': 53 | parser = argparse.ArgumentParser(description='Mail Server Example') 54 | parser.add_argument('--fromAddress', action="store", dest="fromAddress", type=str, required=True) 55 | parser.add_argument('--toAddress', action="store", dest="toAddress", type=str, required=True) 56 | given_args = parser.parse_args() 57 | mail_checker(given_args.fromAddress, given_args.toAddress) 58 | 59 | -------------------------------------------------------------------------------- /Chapter05/5_9a_mail_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 5 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import smtpd 7 | import asyncore 8 | import argparse 9 | 10 | class CustomSMTPServer(smtpd.SMTPServer): 11 | 12 | def process_message(self, peer, mailfrom, rcpttos, data): 13 | print ('Message Received from:', peer) 14 | print ('From:', mailfrom) 15 | print ('To :', rcpttos) 16 | print ('Message :', data) 17 | return 18 | 19 | if __name__ == '__main__': 20 | parser = argparse.ArgumentParser(description='Mail Server Example') 21 | parser.add_argument('--host', action="store", dest="host", type=str, required=True) 22 | parser.add_argument('--port', action="store", dest="port", type=int, required=True) 23 | given_args = parser.parse_args() 24 | server = CustomSMTPServer((given_args.host, given_args.port), None) 25 | asyncore.loop() 26 | 27 | 28 | -------------------------------------------------------------------------------- /Chapter05/5_9b_mail_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 5 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import smtplib 7 | import email.utils 8 | import argparse 9 | from email.mime.text import MIMEText 10 | 11 | def mail_client(host, port, fromAddress, toAddress, subject, body): 12 | msg = MIMEText(body) 13 | msg['To'] = email.utils.formataddr(('Recipient', toAddress)) 14 | msg['From'] = email.utils.formataddr(('Author', fromAddress)) 15 | msg['Subject'] = subject 16 | 17 | server = smtplib.SMTP(host, port) 18 | server.set_debuglevel(True) 19 | try: 20 | server.sendmail(fromAddress, toAddress, msg.as_string()) 21 | finally: 22 | server.quit() 23 | 24 | 25 | if __name__ == '__main__': 26 | parser = argparse.ArgumentParser(description='Mail Server Example') 27 | parser.add_argument('--host', action="store", dest="host", type=str, required=True) 28 | parser.add_argument('--port', action="store", dest="port", type=int, required=True) 29 | parser.add_argument('--fromAddress', action="store", dest="fromAddress", type=str, required=True) 30 | parser.add_argument('--toAddress', action="store", dest="toAddress", type=str, required=True) 31 | parser.add_argument('--subject', action="store", dest="subject", type=str, required=True) 32 | parser.add_argument('--body', action="store", dest="body", type=str, required=True) 33 | given_args = parser.parse_args() 34 | mail_client(given_args.host, given_args.port, given_args.fromAddress, given_args.toAddress, given_args.subject, given_args.body) 35 | 36 | -------------------------------------------------------------------------------- /Chapter05/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Network-Programming-Cookbook-Second-Edition/7a2618500cd7a3a4ff527751664bd9b39bb63a7a/Chapter05/__init__.py -------------------------------------------------------------------------------- /Chapter05/cgi-bin/5_7_get_feedback.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 5 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | #!/usr/bin/python 8 | 9 | # Import modules for CGI handling 10 | import cgi 11 | import cgitb 12 | 13 | # Create instance of FieldStorage 14 | form = cgi.FieldStorage() 15 | 16 | # Get data from fields 17 | name = form.getvalue('Name') 18 | comment = form.getvalue('Comment') 19 | 20 | print ("Content-type:text/html\r\n\r\n") 21 | print ("") 22 | print ("") 23 | print ("CGI Program Example ") 24 | print ("") 25 | print ("") 26 | print ("

%s sends a comment: %s

" % (name, comment)) 27 | print ("") 28 | print ("") 29 | -------------------------------------------------------------------------------- /Chapter05/python-logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Network-Programming-Cookbook-Second-Edition/7a2618500cd7a3a4ff527751664bd9b39bb63a7a/Chapter05/python-logo.gif -------------------------------------------------------------------------------- /Chapter05/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Network-Programming-Cookbook-Second-Edition/7a2618500cd7a3a4ff527751664bd9b39bb63a7a/Chapter05/readme.txt -------------------------------------------------------------------------------- /Chapter06/6_1_execute_remote_telnet_cmd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 6 3 | # This program is optimized for Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | # To make it run on Python 2.7.x, needs some changes due to API differences. 6 | # Follow the comments inline to make the program work with Python 2. 7 | 8 | 9 | import getpass 10 | import sys 11 | import telnetlib 12 | 13 | HOST = "localhost" 14 | 15 | def run_telnet_session(): 16 | 17 | user = input("Enter your remote account: ") 18 | # Comment out the above line and uncomment the below line for Python 2.7. 19 | # user = raw_input("Enter your remote account: ") 20 | 21 | password = getpass.getpass() 22 | 23 | session = telnetlib.Telnet(HOST) 24 | 25 | session.read_until(b"login: ") 26 | session.write(user.encode('ascii') + b"\n") 27 | if password: 28 | session.read_until(b"Password: ") 29 | session.write(password.encode('ascii') + b"\n") 30 | 31 | session.write(b"ls\n") 32 | session.write(b"exit\n") 33 | 34 | print (session.read_all()) 35 | 36 | if __name__ == '__main__': 37 | run_telnet_session() 38 | 39 | -------------------------------------------------------------------------------- /Chapter06/6_2_copy_remote_file_over_sftp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 6 3 | # This program is optimized for Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | # To make it run on Python 2.7.x, needs some changes due to API differences. 6 | # Follow the comments inline to make the program work with Python 2. 7 | 8 | 9 | import argparse 10 | import paramiko 11 | import getpass 12 | 13 | 14 | SOURCE = '6_2_copy_remote_file_over_sftp.py' 15 | DESTINATION ='/tmp/6_2_copy_remote_file_over_sftp.py ' 16 | 17 | 18 | def copy_file(hostname, port, username, password, src, dst): 19 | client = paramiko.SSHClient() 20 | client.load_system_host_keys() 21 | print (" Connecting to %s \n with username=%s... \n" %(hostname,username)) 22 | t = paramiko.Transport(hostname, port) 23 | t.connect(username=username,password=password) 24 | sftp = paramiko.SFTPClient.from_transport(t) 25 | print ("Copying file: %s to path: %s" %(src, dst)) 26 | sftp.put(src, dst) 27 | sftp.close() 28 | t.close() 29 | 30 | 31 | if __name__ == '__main__': 32 | parser = argparse.ArgumentParser(description='Remote file copy') 33 | parser.add_argument('--host', action="store", dest="host", default='localhost') 34 | parser.add_argument('--port', action="store", dest="port", default=22, type=int) 35 | parser.add_argument('--src', action="store", dest="src", default=SOURCE) 36 | parser.add_argument('--dst', action="store", dest="dst", default=DESTINATION) 37 | 38 | given_args = parser.parse_args() 39 | hostname, port = given_args.host, given_args.port 40 | src, dst = given_args.src, given_args.dst 41 | 42 | user = input("Enter your remote account: ") 43 | # Comment out the above line and uncomment the below line for Python 2.7. 44 | # user = raw_input("Enter your remote account: ") 45 | 46 | password = getpass.getpass("Enter password for %s: " %user) 47 | 48 | copy_file(hostname, port, user, password, src, dst) 49 | -------------------------------------------------------------------------------- /Chapter06/6_3_print_remote_cpu_info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 6 3 | # This program is optimized for Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | # To make it run on Python 2.7.x, needs some changes due to API differences. 6 | # Follow the comments inline to make the program work with Python 2. 7 | 8 | 9 | import argparse 10 | import getpass 11 | import paramiko 12 | 13 | RECV_BYTES = 4096 14 | COMMAND = 'cat /proc/cpuinfo' 15 | 16 | def print_remote_cpu_info(hostname, port, username, password): 17 | client = paramiko.Transport((hostname, port)) 18 | client.connect(username=username, password=password) 19 | 20 | stdout_data = [] 21 | stderr_data = [] 22 | session = client.open_channel(kind='session') 23 | session.exec_command(COMMAND) 24 | while True: 25 | if session.recv_ready(): 26 | stdout_data.append(session.recv(RECV_BYTES)) 27 | if session.recv_stderr_ready(): 28 | stderr_data.append(session.recv_stderr(RECV_BYTES)) 29 | if session.exit_status_ready(): 30 | break 31 | 32 | print ('exit status: ', session.recv_exit_status()) 33 | print (b''.join(stdout_data)) 34 | print (b''.join(stderr_data)) 35 | 36 | session.close() 37 | client.close() 38 | 39 | if __name__ == '__main__': 40 | parser = argparse.ArgumentParser(description='Remote file copy') 41 | parser.add_argument('--host', action="store", dest="host", default='localhost') 42 | parser.add_argument('--port', action="store", dest="port", default=22, type=int) 43 | given_args = parser.parse_args() 44 | hostname, port = given_args.host, given_args.port 45 | 46 | user = input("Enter your remote account: ") 47 | # Comment out the above line and uncomment the below line for Python 2.7. 48 | # user = raw_input("Enter your remote account: ") 49 | 50 | password = getpass.getpass("Enter password for %s: " %user) 51 | print_remote_cpu_info(hostname, port, user, password) 52 | 53 | -------------------------------------------------------------------------------- /Chapter06/6_4_install_python_package_remotely.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 6 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | from getpass import getpass 7 | from fabric.api import settings, run, env, prompt 8 | 9 | 10 | def remote_server(): 11 | env.hosts = ['127.0.0.1'] 12 | env.user = prompt('Enter user name: ') 13 | env.password = getpass('Enter password: ') 14 | 15 | def install_package(): 16 | run("pip install yolk") 17 | -------------------------------------------------------------------------------- /Chapter06/6_5_run_mysql_command_remotely.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 6 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | from getpass import getpass 7 | from fabric.api import run, env, prompt, cd 8 | 9 | def remote_server(): 10 | env.hosts = ['127.0.0.1'] 11 | env.user = prompt('Enter your system username: ') 12 | env.password = getpass('Enter your system user password: ') 13 | env.mysqlhost = 'localhost' 14 | env.mysqluser = prompt('Enter your db username: ') 15 | env.mysqlpassword = getpass('Enter your db user password: ') 16 | env.db_name = '' 17 | 18 | def show_dbs(): 19 | """ Wraps mysql show databases cmd""" 20 | q = "show databases" 21 | run("echo '%s' | mysql -u%s -p%s" %(q, env.mysqluser, env.mysqlpassword)) 22 | 23 | 24 | def run_sql(db_name, query): 25 | """ Generic function to run sql""" 26 | with cd('/tmp'): 27 | run("echo '%s' | mysql -u%s -p%s -D %s" %(query, env.mysqluser, env.mysqlpassword, db_name)) 28 | 29 | def create_db(): 30 | """Create a MySQL DB for App version""" 31 | if not env.db_name: 32 | db_name = prompt("Enter the DB name:") 33 | else: 34 | db_name = env.db_name 35 | run('echo "CREATE DATABASE %s default character set utf8 collate utf8_unicode_ci;"|mysql --batch --user=%s --password=%s --host=%s'\ 36 | % (db_name, env.mysqluser, env.mysqlpassword, env.mysqlhost), pty=True) 37 | 38 | def ls_db(): 39 | """ List a dbs with size in MB """ 40 | if not env.db_name: 41 | db_name = prompt("Which DB to ls?") 42 | else: 43 | db_name = env.db_name 44 | query = """SELECT table_schema "DB Name", 45 | Round(Sum(data_length + index_length) / 1024 / 1024, 1) "DB Size in MB" 46 | FROM information_schema.tables 47 | WHERE table_schema = \"%s\" 48 | GROUP BY table_schema """ %db_name 49 | run_sql(db_name, query) 50 | 51 | 52 | def empty_db(): 53 | """ Empty all tables of a given DB """ 54 | db_name = prompt("Enter DB name to empty:") 55 | cmd = """ 56 | (echo 'SET foreign_key_checks = 0;'; 57 | (mysqldump -u%s -p%s --add-drop-table --no-data %s | 58 | grep ^DROP); 59 | echo 'SET foreign_key_checks = 1;') | \ 60 | mysql -u%s -p%s -b %s 61 | """ %(env.mysqluser, env.mysqlpassword, db_name, env.mysqluser, env.mysqlpassword, db_name) 62 | run(cmd) 63 | -------------------------------------------------------------------------------- /Chapter06/6_6_transfer_file_over_ssh.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 6 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | from getpass import getpass 8 | from fabric.api import local, run, env, get, put, prompt, open_shell 9 | 10 | def remote_server(): 11 | env.hosts = ['127.0.0.1'] 12 | env.password = getpass('Enter your system password: ') 13 | env.home_folder = '/tmp' 14 | 15 | def login(): 16 | open_shell(command="cd %s" %env.home_folder) 17 | 18 | 19 | def download_file(): 20 | print ("Checking local disk space...") 21 | local("df -h") 22 | remote_path = prompt("Enter the remote file path:") 23 | local_path = prompt("Enter the local file path:") 24 | get(remote_path=remote_path, local_path=local_path) 25 | local("ls %s" %local_path) 26 | 27 | 28 | def upload_file(): 29 | print ("Checking remote disk space...") 30 | run("df -h") 31 | local_path = prompt("Enter the local file path:") 32 | remote_path = prompt("Enter the remote file path:") 33 | put(remote_path=remote_path, local_path=local_path) 34 | run("ls %s" %remote_path) 35 | 36 | 37 | -------------------------------------------------------------------------------- /Chapter06/6_7_configure_Apache_for_hosting_website_remotely.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 6 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | from getpass import getpass 7 | from fabric.api import env, put, sudo, prompt 8 | from fabric.contrib.files import exists 9 | 10 | WWW_DOC_ROOT = "/data/apache/test/" 11 | WWW_USER = "www-data" 12 | WWW_GROUP = "www-data" 13 | APACHE_SITES_PATH = "/etc/apache2/sites-enabled/" 14 | APACHE_INIT_SCRIPT = "/etc/init.d/apache2 " 15 | 16 | 17 | def remote_server(): 18 | env.hosts = ['127.0.0.1'] 19 | env.user = prompt('Enter user name: ') 20 | env.password = getpass('Enter your system password: ') 21 | 22 | 23 | def setup_vhost(): 24 | """ Setup a test website """ 25 | print ("Preparing the Apache vhost setup...") 26 | print ("Setting up the document root...") 27 | if exists(WWW_DOC_ROOT): 28 | sudo("rm -rf %s" %WWW_DOC_ROOT) 29 | sudo("mkdir -p %s" %WWW_DOC_ROOT) 30 | sudo("chown -R %s.%s %s" %(env.user, env.user, WWW_DOC_ROOT)) 31 | put(local_path="index.html", remote_path=WWW_DOC_ROOT) 32 | sudo("chown -R %s.%s %s" %(WWW_USER, WWW_GROUP, WWW_DOC_ROOT)) 33 | print ("Setting up the vhost...") 34 | sudo("chown -R %s.%s %s" %(env.user, env.user, APACHE_SITES_PATH)) 35 | put(local_path="vhost.conf", remote_path=APACHE_SITES_PATH) 36 | sudo("chown -R %s.%s %s" %('root', 'root', APACHE_SITES_PATH)) 37 | sudo("%s restart" %APACHE_INIT_SCRIPT) 38 | print ("Setup complete. Now open the server path http://abc.remote-server.org/ in your web browser.") 39 | 40 | -------------------------------------------------------------------------------- /Chapter06/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Network-Programming-Cookbook-Second-Edition/7a2618500cd7a3a4ff527751664bd9b39bb63a7a/Chapter06/__init__.py -------------------------------------------------------------------------------- /Chapter06/fabfile.py: -------------------------------------------------------------------------------- 1 | 6_7_configure_Apache_for_hosting_website_remotely.py -------------------------------------------------------------------------------- /Chapter06/index.html: -------------------------------------------------------------------------------- 1 |

It works!

2 |

This is the default web page for this server.

3 |

The web server software is running but no content has been added, yet.

4 | -------------------------------------------------------------------------------- /Chapter06/test.txt: -------------------------------------------------------------------------------- 1 | This is test.txt 2 | -------------------------------------------------------------------------------- /Chapter06/vhost.conf: -------------------------------------------------------------------------------- 1 | UseCanonicalName Off 2 | 3 | LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon 4 | 5 | 6 | ServerName abc.remote-server.org 7 | ServerAlias * 8 | VirtualDocumentRoot /data/apache/test/ 9 | # insert logging config, anything else you need.. 10 | 11 | Order Allow,Deny 12 | Allow from all 13 | AllowOverride None 14 | 15 | 16 | -------------------------------------------------------------------------------- /Chapter07/7_1_query_supervisord_xmlrpc_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 7 3 | # This program is optimized for Python 2.7.12. 4 | # Supervisor requires Python 2.x, and does not run on Python 3.x. 5 | 6 | 7 | import supervisor.xmlrpc 8 | import xmlrpclib 9 | 10 | def query_supervisr(sock): 11 | transport = supervisor.xmlrpc.SupervisorTransport(None, None, 12 | 'unix://%s' %sock) 13 | proxy = xmlrpclib.ServerProxy('http://127.0.0.1', 14 | transport=transport) 15 | print ("Getting info about all running processes via Supervisord...") 16 | print (proxy.supervisor.getAllProcessInfo()) 17 | 18 | if __name__ == '__main__': 19 | query_supervisr(sock='/tmp/supervisor.sock') 20 | 21 | 22 | -------------------------------------------------------------------------------- /Chapter07/7_2_multithreaded_multicall_xmlrpc_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 7 3 | # This program is optimized for Python 3.5.2. 4 | # To make it work with Python 2.7.12: 5 | # Follow through the code inline for some changes. 6 | # It may run on any other version with/without modifications. 7 | 8 | import argparse 9 | import xmlrpc 10 | # Comment out the above line and uncomment the below line for Python 2.x. 11 | #import xmlrpclib 12 | import threading 13 | 14 | from xmlrpc.server import SimpleXMLRPCServer 15 | # Comment out the above line and uncomment the below line for Python 2.x. 16 | #from SimpleXMLRPCServer import SimpleXMLRPCServer 17 | 18 | # some trivial functions 19 | def add(x,y): 20 | return x+y 21 | 22 | def subtract(x, y): 23 | return x-y 24 | 25 | def multiply(x, y): 26 | return x*y 27 | 28 | def divide(x, y): 29 | return x/y 30 | 31 | 32 | class ServerThread(threading.Thread): 33 | def __init__(self, server_addr): 34 | threading.Thread.__init__(self) 35 | self.server = SimpleXMLRPCServer(server_addr) 36 | self.server.register_multicall_functions() 37 | self.server.register_function(add, 'add') 38 | self.server.register_function(subtract, 'subtract') 39 | self.server.register_function(multiply, 'multiply') 40 | self.server.register_function(divide, 'divide') 41 | 42 | def run(self): 43 | self.server.serve_forever() 44 | 45 | def run_server(host, port): 46 | # server code 47 | server_addr = (host, port) 48 | server = ServerThread(server_addr) 49 | server.start() # The server is now running 50 | print ("Server thread started. Testing the server...") 51 | 52 | def run_client(host, port): 53 | 54 | # client code 55 | proxy = xmlrpc.client.ServerProxy("http://%s:%s/" %(host, port)) 56 | # Comment out the above line and uncomment the below line for Python 2.x. 57 | #proxy = xmlrpclib.ServerProxy("http://%s:%s/" %(host, port)) 58 | 59 | multicall = xmlrpc.client.MultiCall(proxy) 60 | # Comment out the above line and uncomment the below line for Python 2.x. 61 | #multicall = xmlrpclib.MultiCall(proxy) 62 | 63 | multicall.add(7,3) 64 | multicall.subtract(7,3) 65 | multicall.multiply(7,3) 66 | multicall.divide(7,3) 67 | result = multicall() 68 | print ("7+3=%d, 7-3=%d, 7*3=%d, 7/3=%d" % tuple(result)) 69 | 70 | if __name__ == '__main__': 71 | parser = argparse.ArgumentParser(description='Multithreaded multicall XMLRPC Server/Proxy') 72 | parser.add_argument('--host', action="store", dest="host", default='localhost') 73 | parser.add_argument('--port', action="store", dest="port", default=8000, type=int) 74 | # parse arguments 75 | given_args = parser.parse_args() 76 | host, port = given_args.host, given_args.port 77 | run_server(host, port) 78 | run_client(host, port) 79 | 80 | -------------------------------------------------------------------------------- /Chapter07/7_3a_xmlrpc_server_with_http_auth.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 7 3 | # This program is optimized for Python 3.5.2. 4 | # To make it work with Python 2.7.12: 5 | # Follow through the code inline for some changes. 6 | # It may run on any other version with/without modifications. 7 | 8 | 9 | import argparse 10 | import xmlrpc 11 | # Comment out the above line and uncomment the below line for Python 2.x. 12 | #import xmlrpclib 13 | from base64 import b64decode 14 | 15 | from xmlrpc.server import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler 16 | # Comment out the above line and uncomment the below line for Python 2.x. 17 | #from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler 18 | 19 | 20 | class SecureXMLRPCServer(SimpleXMLRPCServer): 21 | 22 | def __init__(self, host, port, username, password, *args, **kargs): 23 | self.username = username 24 | self.password = password 25 | # authenticate method is called from inner class 26 | class VerifyingRequestHandler(SimpleXMLRPCRequestHandler): 27 | # method to override 28 | def parse_request(request): 29 | if SimpleXMLRPCRequestHandler.parse_request(request): 30 | # authenticate 31 | if self.authenticate(request.headers): 32 | return True 33 | else: 34 | # if authentication fails return 401 35 | request.send_error(401, 'Authentication failed, Try agin.') 36 | return False 37 | # initialize 38 | SimpleXMLRPCServer.__init__(self, (host, port), requestHandler=VerifyingRequestHandler, *args, **kargs) 39 | 40 | def authenticate(self, headers): 41 | headers = headers.get('Authorization').split() 42 | basic, encoded = headers[0], headers[1] 43 | if basic != 'Basic': 44 | print ('Only basic authentication supported') 45 | return False 46 | secret = b64decode(encoded).split(b':') 47 | 48 | username, password = secret[0].decode("utf-8"), secret[1].decode("utf-8") 49 | return True if (username == self.username and password == self.password) else False 50 | 51 | 52 | def run_server(host, port, username, password): 53 | server = SecureXMLRPCServer(host, port, username, password) 54 | # simple test function 55 | def echo(msg): 56 | """Reply client in uppser case """ 57 | reply = msg.upper() 58 | print ("Client said: %s. So we echo that in uppercase: %s" %(msg, reply)) 59 | return reply 60 | server.register_function(echo, 'echo') 61 | print ("Running a HTTP auth enabled XMLRPC server on %s:%s..." %(host, port)) 62 | server.serve_forever() 63 | 64 | 65 | if __name__ == '__main__': 66 | parser = argparse.ArgumentParser(description='Multithreaded multicall XMLRPC Server/Proxy') 67 | parser.add_argument('--host', action="store", dest="host", default='localhost') 68 | parser.add_argument('--port', action="store", dest="port", default=8000, type=int) 69 | parser.add_argument('--username', action="store", dest="username", default='user') 70 | parser.add_argument('--password', action="store", dest="password", default='pass') 71 | # parse arguments 72 | given_args = parser.parse_args() 73 | host, port = given_args.host, given_args.port 74 | username, password = given_args.username, given_args.password 75 | run_server(host, port, username, password) 76 | -------------------------------------------------------------------------------- /Chapter07/7_3b_xmprpc_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 7 3 | # This program is optimized for Python 3.5.2. 4 | # To make it work with Python 2.7.12: 5 | # Follow through the code inline for some changes. 6 | # It may run on any other version with/without modifications. 7 | 8 | 9 | import argparse 10 | import xmlrpc 11 | # Comment out the above line and uncomment the below line for Python 2.x. 12 | #import xmlrpclib 13 | 14 | from xmlrpc.server import SimpleXMLRPCServer 15 | # Comment out the above line for Python 2.x. 16 | 17 | def run_client(host, port, username, password): 18 | server = xmlrpc.client.ServerProxy('http://%s:%s@%s:%s' %(username, password, host, port, )) 19 | # Comment out the above line and uncomment the below line for Python 2.x. 20 | #server = xmlrpclib.ServerProxy('http://%s:%s@%s:%s' %(username, password, host, port, )) 21 | msg = "hello server..." 22 | print ("Sending message to server: %s " %msg) 23 | print ("Got reply: %s" %server.echo(msg)) 24 | 25 | if __name__ == '__main__': 26 | parser = argparse.ArgumentParser(description='Multithreaded multicall XMLRPC Server/Proxy') 27 | parser.add_argument('--host', action="store", dest="host", default='localhost') 28 | parser.add_argument('--port', action="store", dest="port", default=8000, type=int) 29 | parser.add_argument('--username', action="store", dest="username", default='user') 30 | parser.add_argument('--password', action="store", dest="password", default='pass') 31 | # parse arguments 32 | given_args = parser.parse_args() 33 | host, port = given_args.host, given_args.port 34 | username, password = given_args.username, given_args.password 35 | run_client(host, port, username, password) 36 | -------------------------------------------------------------------------------- /Chapter07/7_4_get_flickr_photo_info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 7 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | # Supply Flickr API key via local_settings.py 6 | 7 | import argparse 8 | import json 9 | import requests 10 | 11 | try: 12 | from local_settings import flickr_apikey 13 | except ImportError: 14 | pass 15 | 16 | 17 | def collect_photo_info(api_key, tag, max_count): 18 | """Collects some interesting info about some photos from Flickr.com for a given tag """ 19 | photo_collection = [] 20 | url = "http://api.flickr.com/services/rest/?method=flickr.photos.search&tags=%s&format=json&nojsoncallback=1&api_key=%s" %(tag, api_key) 21 | resp = requests.get(url) 22 | results = resp.json() 23 | count = 0 24 | for p in results['photos']['photo']: 25 | if count >= max_count: 26 | return photo_collection 27 | print ('Processing photo: "%s"' % p['title']) 28 | photo = {} 29 | url = "http://api.flickr.com/services/rest/?method=flickr.photos.getInfo&photo_id=" + p['id'] + "&format=json&nojsoncallback=1&api_key=" + api_key 30 | info = requests.get(url).json() 31 | photo["flickrid"] = p['id'] 32 | photo["title"] = info['photo']['title']['_content'] 33 | photo["description"] = info['photo']['description']['_content'] 34 | photo["page_url"] = info['photo']['urls']['url'][0]['_content'] 35 | 36 | photo["farm"] = info['photo']['farm'] 37 | photo["server"] = info['photo']['server'] 38 | photo["secret"] = info['photo']['secret'] 39 | 40 | # comments 41 | numcomments = int(info['photo']['comments']['_content']) 42 | if numcomments: 43 | #print " Now reading comments (%d)..." % numcomments 44 | url = "http://api.flickr.com/services/rest/?method=flickr.photos.comments.getList&photo_id=" + p['id'] + "&format=json&nojsoncallback=1&api_key=" + api_key 45 | comments = requests.get(url).json() 46 | photo["comment"] = [] 47 | for c in comments['comments']['comment']: 48 | comment = {} 49 | comment["body"] = c['_content'] 50 | comment["authorid"] = c['author'] 51 | comment["authorname"] = c['authorname'] 52 | photo["comment"].append(comment) 53 | photo_collection.append(photo) 54 | count = count + 1 55 | return photo_collection 56 | 57 | 58 | if __name__ == '__main__': 59 | parser = argparse.ArgumentParser(description='Get photo info from Flickr') 60 | parser.add_argument('--api-key', action="store", dest="api_key", default=flickr_apikey) 61 | parser.add_argument('--tag', action="store", dest="tag", default='Python') 62 | parser.add_argument('--max-count', action="store", dest="max_count", default=3, type=int) 63 | # parse arguments 64 | given_args = parser.parse_args() 65 | api_key, tag, max_count = given_args.api_key, given_args.tag, given_args.max_count 66 | photo_info = collect_photo_info(api_key, tag, max_count) 67 | for photo in photo_info: 68 | for k,v in photo.iteritems(): 69 | if k == "title": 70 | print ("Showiing photo info....") 71 | elif k == "comment": 72 | "\tPhoto got %s comments." %len(v) 73 | else: 74 | print ("\t%s => %s" %(k,v)) 75 | 76 | -------------------------------------------------------------------------------- /Chapter07/7_5_search_amazonaws_with_soap.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook -- Chapter - 7 3 | # This program requires Python 2.7 or any later version 4 | # SOAPpy has discontinued its support for Python 3. 5 | # You may find more information and other potential libraries at https://stackoverflow.com/questions/7817303/what-soap-libraries-exist-for-python-3-x 6 | 7 | import SOAPpy 8 | 9 | TEST_URL = 'http://s3.amazonaws.com/ec2-downloads/2009-04-04.ec2.wsdl' 10 | 11 | 12 | def list_soap_methods(url): 13 | proxy = SOAPpy.WSDL.Proxy(url) 14 | 15 | print ('%d methods in WSDL:' % len(proxy.methods) + '\n') 16 | for key in proxy.methods.keys(): 17 | print ("Key Name: %s" %key) 18 | print ("Key Details:") 19 | for k,v in proxy.methods[key].__dict__.iteritems(): 20 | print ("%s ==> %s" %(k,v)) 21 | break 22 | 23 | if __name__ == '__main__': 24 | list_soap_methods(TEST_URL) 25 | -------------------------------------------------------------------------------- /Chapter07/7_6_search_amazon_for_books.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 7 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | # Supply the Amazon Access and Secret Keys via local_settings.py 6 | 7 | import argparse 8 | import bottlenose 9 | from xml.dom import minidom as xml 10 | 11 | try: 12 | from local_settings import amazon_account 13 | except ImportError: 14 | pass 15 | 16 | ACCESS_KEY = amazon_account['access_key'] 17 | SECRET_KEY = amazon_account['secret_key'] 18 | AFFILIATE_ID = amazon_account['affiliate_id'] 19 | 20 | 21 | def search_for_books(tag, index): 22 | """Search Amazon for Books """ 23 | amazon = bottlenose.Amazon(ACCESS_KEY, SECRET_KEY, AFFILIATE_ID) 24 | results = amazon.ItemSearch( 25 | SearchIndex = index, 26 | Sort = "relevancerank", 27 | Keywords = tag 28 | ) 29 | parsed_result = xml.parseString(results) 30 | 31 | all_items = [] 32 | attrs = ['Title','Author', 'URL'] 33 | 34 | for item in parsed_result.getElementsByTagName('Item'): 35 | parse_item = {} 36 | 37 | for attr in attrs: 38 | parse_item[attr] = "" 39 | try: 40 | parse_item[attr] = item.getElementsByTagName(attr)[0].childNodes[0].data 41 | except: 42 | pass 43 | all_items.append(parse_item) 44 | return all_items 45 | 46 | if __name__ == '__main__': 47 | parser = argparse.ArgumentParser(description='Search info from Amazon') 48 | parser.add_argument('--tag', action="store", dest="tag", default='Python') 49 | parser.add_argument('--index', action="store", dest="index", default='Books') 50 | # parse arguments 51 | given_args = parser.parse_args() 52 | books = search_for_books(given_args.tag, given_args.index) 53 | 54 | for book in books: 55 | for k,v in book.iteritems(): 56 | print ("%s: %s" %(k,v)) 57 | print ("-" * 80) 58 | -------------------------------------------------------------------------------- /Chapter07/7_7_create_restful_webservice.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 7 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | from flask import Flask 7 | app = Flask(__name__) 8 | 9 | @app.route('/') 10 | def index(num=1): 11 | return "Your Python Web Service
Fibonacci("+ str(num) + "): "+ str(fibonacci(num))+ "
Square("+ str(num) + "): "+ str(square(num)) 12 | 13 | def fibonacci(n): 14 | if n == 0: 15 | return 0 16 | elif n == 1: 17 | return 1 18 | else: 19 | return fibonacci(n-1) + fibonacci(n-2) 20 | 21 | 22 | def square(n): 23 | print ("Calculating for the number %s" %n) 24 | return n*n 25 | 26 | if __name__ == '__main__': 27 | app.run(debug=True) 28 | -------------------------------------------------------------------------------- /Chapter07/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Network-Programming-Cookbook-Second-Edition/7a2618500cd7a3a4ff527751664bd9b39bb63a7a/Chapter07/__init__.py -------------------------------------------------------------------------------- /Chapter07/local_settings.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook -- Chapter - 8 3 | # This program is optimized for Python 2.7. 4 | # It may run on any other version with/without modifications. 5 | 6 | # Make a copy of this file as local_settings.py 7 | # FILL IN THE VARIABLES BELOW WITH YOUR PERSONAL INFORMATION 8 | 9 | # Amazon API stuffs 10 | amazon_account = { 11 | 'access_key' : '', 12 | 'secret_key' : '', 13 | 'affiliate_id' : '' 14 | } 15 | 16 | flickr_apikey = '' 17 | -------------------------------------------------------------------------------- /Chapter07/local_settings.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Network-Programming-Cookbook-Second-Edition/7a2618500cd7a3a4ff527751664bd9b39bb63a7a/Chapter07/local_settings.pyc -------------------------------------------------------------------------------- /Chapter08/8_1_packet_sniffer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 8 3 | # This program is optimized for Python 2.7.12. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | import pcap 8 | from construct.protocols.ipstack import ip_stack 9 | 10 | 11 | def print_packet(pktlen, data, timestamp): 12 | """ Callback for priniting the packet payload""" 13 | if not data: 14 | return 15 | 16 | stack = ip_stack.parse(data) 17 | payload = stack.next.next.next 18 | print (payload) 19 | 20 | def main(): 21 | # setup commandline arguments 22 | parser = argparse.ArgumentParser(description='Packet Sniffer') 23 | parser.add_argument('--iface', action="store", dest="iface", default='eth0') 24 | parser.add_argument('--port', action="store", dest="port", default=80, type=int) 25 | # parse arguments 26 | given_args = parser.parse_args() 27 | iface, port = given_args.iface, given_args.port 28 | # start sniffing 29 | pc = pcap.pcapObject() 30 | pc.open_live(iface, 1600, 0, 100) 31 | pc.setfilter('dst port %d' %port, 0, 0) 32 | 33 | print ('Press CTRL+C to end capture') 34 | try: 35 | while True: 36 | pc.dispatch(1, print_packet) 37 | except KeyboardInterrupt: 38 | print ('Packet statistics: %d packets received, %d packets dropped, %d packets dropped by the interface' % pc.stats()) 39 | 40 | if __name__ == '__main__': 41 | main() 42 | 43 | -------------------------------------------------------------------------------- /Chapter08/8_2_save_packets_in_pcap_format.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 8 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | import os 8 | from scapy.all import * 9 | 10 | pkts = [] 11 | count = 0 12 | pcapnum = 0 13 | 14 | def write_cap(x): 15 | global pkts 16 | global count 17 | global pcapnum 18 | pkts.append(x) 19 | count += 1 20 | if count == 3: 21 | pcapnum += 1 22 | pname = "pcap%d.pcap" % pcapnum 23 | wrpcap(pname, pkts) 24 | pkts = [] 25 | count = 0 26 | 27 | def test_dump_file(): 28 | print ("Testing the dump file...") 29 | dump_file = "./pcap1.pcap" 30 | if os.path.exists(dump_file): 31 | print ("dump fie %s found." %dump_file) 32 | pkts = sniff(offline=dump_file) 33 | count = 0 34 | while (count <=2): 35 | print ("----Dumping pkt:%s----" %count) 36 | print (hexdump(pkts[count])) 37 | count += 1 38 | 39 | else: 40 | print ("dump fie %s not found." %dump_file) 41 | 42 | if __name__ == '__main__': 43 | print ("Started packet capturing and dumping... Press CTRL+C to exit") 44 | sniff(prn=write_cap) 45 | test_dump_file() 46 | 47 | -------------------------------------------------------------------------------- /Chapter08/8_3_add_an_extra_header_in_http_packet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 8 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | from scapy.all import * 8 | 9 | def modify_packet_header(pkt): 10 | """ Parse the header and add an extra header""" 11 | if pkt.haslayer(TCP) and pkt.getlayer(TCP).dport == 80 and pkt.haslayer(Raw): 12 | hdr = pkt[TCP].payload.__dict__ 13 | extra_item = {'Extra Header' : ' extra value'} 14 | hdr.update(extra_item) 15 | send_hdr = '\r\n'.join(hdr) 16 | pkt[TCP].payload = send_hdr 17 | 18 | pkt.show() 19 | 20 | del pkt[IP].chksum 21 | send(pkt) 22 | 23 | if __name__ == '__main__': 24 | # start sniffing 25 | sniff(filter="tcp and ( port 80 )", prn=modify_packet_header) 26 | -------------------------------------------------------------------------------- /Chapter08/8_4_scan_port_of_a_remote_host.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 8 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | import socket 8 | import sys 9 | 10 | def scan_ports(host, start_port, end_port): 11 | """ Scan remote hosts """ 12 | #Create socket 13 | try: 14 | sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 15 | except socket.error as err_msg: 16 | print ('Socket creation failed. Error code: '+ str(err_msg[0]) + ' Error mesage: ' + err_msg[1]) 17 | sys.exit() 18 | 19 | #Get IP of remote host 20 | try: 21 | remote_ip = socket.gethostbyname(host) 22 | except socket.error as error_msg: 23 | print (error_msg) 24 | sys.exit() 25 | 26 | #Scan ports 27 | end_port += 1 28 | for port in range(start_port,end_port): 29 | try: 30 | sock.connect((remote_ip,port)) 31 | print ('Port ' + str(port) + ' is open') 32 | sock.close() 33 | sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 34 | except socket.error: 35 | pass # skip various socket errors 36 | 37 | if __name__ == '__main__': 38 | # setup commandline arguments 39 | parser = argparse.ArgumentParser(description='Remote Port Scanner') 40 | parser.add_argument('--host', action="store", dest="host", default='localhost') 41 | parser.add_argument('--start-port', action="store", dest="start_port", default=1, type=int) 42 | parser.add_argument('--end-port', action="store", dest="end_port", default=100, type=int) 43 | # parse arguments 44 | given_args = parser.parse_args() 45 | host, start_port, end_port = given_args.host, given_args.start_port, given_args.end_port 46 | scan_ports(host, start_port, end_port) 47 | 48 | 49 | -------------------------------------------------------------------------------- /Chapter08/8_5_modify_ip_in_a_packet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 8 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | import argparse 8 | import sys 9 | import re 10 | from random import randint 11 | 12 | from scapy.all import IP,TCP,UDP,conf,send 13 | 14 | 15 | def send_packet(protocol=None, src_ip=None, src_port=None, flags=None, dst_ip=None, dst_port=None, iface=None): 16 | """Modify and send an IP packet.""" 17 | if protocol == 'tcp': 18 | packet = IP(src=src_ip, dst=dst_ip)/TCP(flags=flags, sport=src_port, dport=dst_port) 19 | elif protocol == 'udp': 20 | if flags: raise Exception(" Flags are not supported for udp") 21 | packet = IP(src=src_ip, dst=dst_ip)/UDP(sport=src_port, dport=dst_port) 22 | else: 23 | raise Exception("Unknown protocol %s" % protocol) 24 | 25 | send(packet, iface=iface) 26 | 27 | 28 | if __name__ == '__main__': 29 | # setup commandline arguments 30 | parser = argparse.ArgumentParser(description='Packet Modifier') 31 | parser.add_argument('--iface', action="store", dest="iface", default='eth0') 32 | parser.add_argument('--protocol', action="store", dest="protocol", default='tcp') 33 | parser.add_argument('--src-ip', action="store", dest="src_ip", default='1.1.1.1') 34 | parser.add_argument('--src-port', action="store", dest="src_port", default=randint(0, 65535)) 35 | parser.add_argument('--dst-ip', action="store", dest="dst_ip", default='192.168.1.51') 36 | parser.add_argument('--dst-port', action="store", dest="dst_port", default=randint(0, 65535)) 37 | parser.add_argument('--flags', action="store", dest="flags", default=None) 38 | # parse arguments 39 | given_args = parser.parse_args() 40 | iface, protocol, src_ip, src_port, dst_ip, dst_port, flags = given_args.iface, given_args.protocol, given_args.src_ip,\ 41 | given_args.src_port, given_args.dst_ip, given_args.dst_port, given_args.flags 42 | send_packet(protocol, src_ip, src_port, flags, dst_ip, dst_port, iface) 43 | 44 | -------------------------------------------------------------------------------- /Chapter08/8_6_replay_traffic.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 8 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | import argparse 8 | from scapy.all import * 9 | 10 | 11 | def send_packet(recvd_pkt, src_ip, dst_ip, count): 12 | """ Send modified packets""" 13 | pkt_cnt = 0 14 | p_out = [] 15 | 16 | for p in recvd_pkt: 17 | pkt_cnt += 1 18 | new_pkt = p.payload 19 | new_pkt[IP].dst = dst_ip 20 | new_pkt[IP].src = src_ip 21 | del new_pkt[IP].chksum 22 | p_out.append(new_pkt) 23 | if pkt_cnt % count == 0: 24 | send(PacketList(p_out)) 25 | p_out = [] 26 | 27 | # Send rest of packet 28 | send(PacketList(p_out)) 29 | print ("Total packets sent: %d" %pkt_cnt) 30 | 31 | if __name__ == '__main__': 32 | # setup commandline arguments 33 | parser = argparse.ArgumentParser(description='Packet Sniffer') 34 | parser.add_argument('--infile', action="store", dest="infile", default='pcap1.pcap') 35 | parser.add_argument('--src-ip', action="store", dest="src_ip", default='1.1.1.1') 36 | parser.add_argument('--dst-ip', action="store", dest="dst_ip", default='2.2.2.2') 37 | parser.add_argument('--count', action="store", dest="count", default=100, type=int) 38 | # parse arguments 39 | given_args = ga = parser.parse_args() 40 | global src_ip, dst_ip 41 | infile, src_ip, dst_ip, count = ga.infile, ga.src_ip, ga.dst_ip, ga.count 42 | try: 43 | pkt_reader = PcapReader(infile) 44 | send_packet(pkt_reader, src_ip, dst_ip, count) 45 | except IOError: 46 | print ("Failed reading file %s contents" % infile) 47 | sys.exit(1) 48 | -------------------------------------------------------------------------------- /Chapter08/8_7_broadcast_scanning.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 8 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | from scapy.all import * 8 | import os 9 | captured_data = dict() 10 | 11 | END_PORT = 1000 12 | 13 | def monitor_packet(pkt): 14 | if IP in pkt: 15 | if pkt[IP].src not in captured_data: 16 | captured_data[pkt[IP].src] = [] 17 | 18 | if TCP in pkt: 19 | if pkt[TCP].sport <= END_PORT: 20 | if not str(pkt[TCP].sport) in captured_data[pkt[IP].src]: 21 | captured_data[pkt[IP].src].append(str(pkt[TCP].sport)) 22 | 23 | os.system('clear') 24 | ip_list = sorted(captured_data.keys()) 25 | for key in ip_list: 26 | ports=', '.join(captured_data[key]) 27 | if len (captured_data[key]) == 0: 28 | print ('%s' % key) 29 | else: 30 | print ('%s (%s)' % (key, ports)) 31 | 32 | if __name__ == '__main__': 33 | sniff(prn=monitor_packet, store=0) 34 | -------------------------------------------------------------------------------- /Chapter08/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Network-Programming-Cookbook-Second-Edition/7a2618500cd7a3a4ff527751664bd9b39bb63a7a/Chapter08/__init__.py -------------------------------------------------------------------------------- /Chapter09/9_1_ns3_simulation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 9 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import ns.applications 7 | import ns.core 8 | import ns.internet 9 | import ns.network 10 | import ns.point_to_point 11 | import argparse 12 | 13 | 14 | def simulate(ipv4add, ipv4mask): 15 | # Enabling logs at INFO level for both the server and the client. 16 | ns.core.LogComponentEnable("UdpEchoClientApplication", ns.core.LOG_LEVEL_INFO) 17 | ns.core.LogComponentEnable("UdpEchoServerApplication", ns.core.LOG_LEVEL_INFO) 18 | 19 | # Create the 2 nodes. 20 | nodes = ns.network.NodeContainer() 21 | nodes.Create(2) 22 | 23 | pointToPoint = ns.point_to_point.PointToPointHelper() 24 | 25 | devices = pointToPoint.Install(nodes) 26 | 27 | stack = ns.internet.InternetStackHelper() 28 | stack.Install(nodes) 29 | 30 | # Set addresses based on the input args. 31 | address = ns.internet.Ipv4AddressHelper() 32 | address.SetBase(ns.network.Ipv4Address(ipv4add), ns.network.Ipv4Mask(ipv4mask)) 33 | 34 | interfaces = address.Assign(devices) 35 | 36 | # Running the echo server 37 | echoServer = ns.applications.UdpEchoServerHelper(9) 38 | serverApps = echoServer.Install(nodes.Get(1)) 39 | 40 | # Running the echo client 41 | echoClient = ns.applications.UdpEchoClientHelper(interfaces.GetAddress(1), 3) 42 | clientApps = echoClient.Install(nodes.Get(0)) 43 | 44 | # Running the simulator 45 | ns.core.Simulator.Run() 46 | ns.core.Simulator.Destroy() 47 | 48 | 49 | if __name__ == '__main__': 50 | parser = argparse.ArgumentParser(description='NS-3 Simple Simulation') 51 | parser.add_argument('--ipv4add', action="store", dest="ipv4add", type=str, required=True) 52 | parser.add_argument('--ipv4mask', action="store", dest="ipv4mask", type=str, required=True) 53 | given_args = parser.parse_args() 54 | simulate(given_args.ipv4add, given_args.ipv4mask) 55 | 56 | -------------------------------------------------------------------------------- /Chapter09/9_2_mininet_emulation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 9 3 | # This program is optimized for Python 2.7.12. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | from mininet.net import Mininet 8 | from mininet.topolib import TreeTopo 9 | 10 | # Emulate a network with depth of depth_ and fanout of fanout_ 11 | def emulate(depth_, fanout_): 12 | 13 | # Create a network with tree topology 14 | tree_ = TreeTopo(depth=depth_,fanout=fanout_) 15 | 16 | # Initiating the Mininet instance 17 | net = Mininet(topo=tree_) 18 | 19 | # Start Execution of the Emulated System. 20 | net.start() 21 | 22 | # Name two of the instances as h1 and h2. 23 | h1, h2 = net.hosts[0], net.hosts[depth_] 24 | 25 | # Ping from an instance to another, and print the output. 26 | print (h1.cmd('ping -c1 %s' % h2.IP())) 27 | 28 | # Stop the Mininet Emulation. 29 | net.stop() 30 | 31 | if __name__ == '__main__': 32 | parser = argparse.ArgumentParser(description='Mininet Simple Emulation') 33 | parser.add_argument('--depth', action="store", dest="depth", type=int, required=True) 34 | parser.add_argument('--fanout', action="store", dest="fanout", type=int, required=True) 35 | given_args = parser.parse_args() 36 | emulate(given_args.depth, given_args.fanout) 37 | 38 | -------------------------------------------------------------------------------- /Chapter09/9_3_maxinet_emulation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 9 3 | # This program is optimized for Python 2.7.12. 4 | # It may run on any other version with/without modifications. 5 | 6 | import sys 7 | import maxinet 8 | from mininet.topolib import TreeTopo 9 | 10 | # Emulate a network with depth of depth_ and fanout of fanout_ 11 | def emulate(depth_, fanout_): 12 | # Start the MaxiNet as a Mininet cluster. 13 | cluster = maxinet.MininetCluster("pc1","pc2","pc3") 14 | cluster.start() 15 | 16 | # Emulate the network topology. 17 | emu = maxinet.Emulation(cluster, TreeTopo(depth_,fanout_)) 18 | 19 | # Start Execution of the Emulated System. 20 | emu.setup() 21 | 22 | # Name two of the instances as h1 and h2. 23 | h1, h2 = net.hosts[0], net.hosts[depth_] 24 | 25 | # Ping from an instance to another, and print the output. 26 | print (h1.cmd('ping -c1 %s' % h2.IP())) 27 | 28 | # Stop the MaxiNet Emulation. 29 | emu.stop() 30 | cluster.stop() 31 | 32 | if __name__ == '__main__': 33 | parser = argparse.ArgumentParser(description='Maxinet Simple Emulation') 34 | parser.add_argument('--depth', action="store", dest="depth", type=int, required=True) 35 | parser.add_argument('--fanout', action="store", dest="fanout", type=int, required=True) 36 | given_args = parser.parse_args() 37 | emulate(given_args.depth, given_args.fanout) 38 | 39 | -------------------------------------------------------------------------------- /Chapter09/9_4_mininet_wifi_emulation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 9 3 | # This program is optimized for Python 2.7.12. 4 | # It may run on any other version with/without modifications. 5 | 6 | from mininet.net import Mininet 7 | from mininet.node import Controller, OVSKernelAP 8 | from mininet.link import TCLink 9 | from mininet.cli import CLI 10 | from mininet.log import setLogLevel 11 | 12 | def emulate(): 13 | # Setting the position of nodes and providing mobility 14 | 15 | # Create a network. 16 | net = Mininet(controller=Controller, link=TCLink, accessPoint=OVSKernelAP) 17 | 18 | print ("*** Creating nodes") 19 | # Add the host 20 | h1 = net.addHost('h1', mac='00:00:00:00:00:01', ip='10.0.0.1/8') 21 | 22 | # Add 3 mobile stations, sta1, sta2, sta3. 23 | sta1 = net.addStation('sta1', mac='00:00:00:00:00:02', ip='10.0.0.2/8') 24 | sta2 = net.addStation('sta2', mac='00:00:00:00:00:03', ip='10.0.0.3/8') 25 | sta3 = net.addStation('sta3', mac='00:00:00:00:00:04', ip='10.0.0.4/8') 26 | 27 | # Add an access point 28 | ap1 = net.addAccessPoint('ap1', ssid='new-ssid', mode='g', channel='1', position='45,40,30') 29 | 30 | # Add a controller 31 | c1 = net.addController('c1', controller=Controller) 32 | 33 | print ("*** Configuring wifi nodes") 34 | net.configureWifiNodes() 35 | 36 | print ("*** Associating and Creating links") 37 | net.addLink(ap1, h1) 38 | net.addLink(ap1, sta1) 39 | net.addLink(ap1, sta2) 40 | net.addLink(ap1, sta3) 41 | 42 | print ("*** Starting network") 43 | net.build() 44 | c1.start() 45 | ap1.start([c1]) 46 | 47 | # Plot a 3-dimensional graph. 48 | net.plotGraph(max_x=100, max_y=100, max_z=200) 49 | 50 | # Start the mobility at the start of the emulation. 51 | net.startMobility(time=0) 52 | 53 | # Start the mobile stations from their initial positions. 54 | net.mobility(sta1, 'start', time=1, position='40.0,30.0,20.0') 55 | net.mobility(sta2, 'start', time=2, position='40.0,40.0,90.0') 56 | net.mobility(sta3, 'start', time=3, position='50.0,50.0,160.0') 57 | 58 | # Indicate the final destination of the mobile stations during the emulation. 59 | net.mobility(sta1, 'stop', time=12, position='31.0,10.0,50.0') 60 | net.mobility(sta2, 'stop', time=22, position='55.0,31.0,30.0') 61 | net.mobility(sta3, 'stop', time=32, position='75.0,99.0,120.0') 62 | 63 | # Stop the mobility at certain time. 64 | net.stopMobility(time=33) 65 | 66 | print ("*** Running CLI") 67 | CLI(net) 68 | 69 | print ("*** Stopping network") 70 | net.stop() 71 | 72 | if __name__ == '__main__': 73 | setLogLevel('info') 74 | emulate() 75 | -------------------------------------------------------------------------------- /Chapter09/9_5_containernet_emulation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 9 3 | # This program is optimized for Python 2.7.12. 4 | # It may run on any other version with/without modifications. 5 | 6 | # Adopted from https://github.com/containernet/containernet/blob/master/examples/dockerhosts.py 7 | 8 | """ 9 | This example shows how to create a simple network and 10 | how to create docker containers (based on existing images) 11 | to it. 12 | """ 13 | 14 | from mininet.net import Containernet 15 | from mininet.node import Controller, Docker, OVSSwitch 16 | from mininet.cli import CLI 17 | from mininet.log import setLogLevel, info 18 | from mininet.link import TCLink, Link 19 | 20 | 21 | def emulate(): 22 | 23 | "Create a network with some docker containers acting as hosts." 24 | 25 | net = Containernet(controller=Controller) 26 | 27 | info('*** Adding controller\n') 28 | net.addController('c0') 29 | 30 | info('*** Adding hosts\n') 31 | h1 = net.addHost('h1') 32 | h2 = net.addHost('h2') 33 | 34 | info('*** Adding docker containers\n') 35 | d1 = net.addDocker('d1', ip='10.0.0.251', dimage="ubuntu:trusty") 36 | 37 | # A container with more specific params: cpu period and cpu quota 38 | d2 = net.addDocker('d2', ip='10.0.0.252', dimage="ubuntu:trusty", cpu_period=50000, cpu_quota=25000) 39 | 40 | # Add a container as a host, using Docker class option. 41 | d3 = net.addHost('d3', ip='11.0.0.253', cls=Docker, dimage="ubuntu:trusty", cpu_shares=20) 42 | 43 | # Add a container with a specific volume. 44 | d5 = net.addDocker('d5', dimage="ubuntu:trusty", volumes=["/:/mnt/vol1:rw"]) 45 | 46 | info('*** Adding switch\n') 47 | s1 = net.addSwitch('s1') 48 | s2 = net.addSwitch('s2', cls=OVSSwitch) 49 | s3 = net.addSwitch('s3') 50 | 51 | info('*** Creating links\n') 52 | net.addLink(h1, s1) 53 | net.addLink(s1, d1) 54 | net.addLink(h2, s2) 55 | net.addLink(d2, s2) 56 | net.addLink(s1, s2) 57 | 58 | # try to add a second interface to a docker container 59 | net.addLink(d2, s3, params1={"ip": "11.0.0.254/8"}) 60 | net.addLink(d3, s3) 61 | 62 | info('*** Starting network\n') 63 | net.start() 64 | 65 | # The typical ping example, with two docker instances in place of hosts. 66 | net.ping([d1, d2]) 67 | 68 | # our extended ping functionality 69 | net.ping([d1], manualdestip="10.0.0.252") 70 | net.ping([d2, d3], manualdestip="11.0.0.254") 71 | 72 | info('*** Dynamically add a container at runtime\n') 73 | d4 = net.addDocker('d4', dimage="ubuntu:trusty") 74 | 75 | # we have to specify a manual ip when we add a link at runtime 76 | net.addLink(d4, s1, params1={"ip": "10.0.0.254/8"}) 77 | 78 | # Ping docker instance d1. 79 | net.ping([d1], manualdestip="10.0.0.254") 80 | 81 | info('*** Running CLI\n') 82 | CLI(net) 83 | 84 | info('*** Stopping network') 85 | net.stop() 86 | 87 | if __name__ == '__main__': 88 | setLogLevel('info') 89 | emulate() 90 | -------------------------------------------------------------------------------- /Chapter09/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Recipes for Network Modelling 3 | """ 4 | -------------------------------------------------------------------------------- /Chapter10/10_2_sdn_opendaylight.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 10 3 | # This program is optimized for Python 2.7.12. 4 | # It may run on any other version with/without modifications. 5 | 6 | from mininet.net import Mininet 7 | from mininet.node import OVSSwitch, Controller, RemoteController 8 | from mininet.cli import CLI 9 | from mininet.log import setLogLevel 10 | 11 | def execute(): 12 | 13 | # Create Mininet instance. 14 | net = Mininet() 15 | 16 | # Add the SDN controller to the network. 17 | c1 = net.addController(name='c1', controller=RemoteController, 18 | ip='127.0.0.1') 19 | 20 | # Add hosts to the network. 21 | h0=net.addHost('h0') 22 | h1=net.addHost('h1') 23 | 24 | # Add switches to the network. 25 | s0=net.addSwitch('s0') 26 | s1=net.addSwitch('s1') 27 | s2=net.addSwitch('s2') 28 | 29 | # Creating links between the switches in the network 30 | net.addLink(s0, s1) 31 | net.addLink(s1, s2) 32 | net.addLink(s0, s2) 33 | 34 | # Connect hosts to the relevant switches in the network. 35 | net.addLink(h0, s0) 36 | net.addLink(h1, s1) 37 | 38 | # Start execution. 39 | net.start() 40 | 41 | CLI( net ) 42 | 43 | if __name__ == '__main__': 44 | setLogLevel( 'info' ) # for CLI output 45 | execute() 46 | -------------------------------------------------------------------------------- /Chapter10/10_3_sdn_onos.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 10 3 | # This program is optimized for Python 2.7.12. 4 | # It may run on any other version with/without modifications. 5 | 6 | from mininet.net import Mininet 7 | from mininet.node import Controller, RemoteController, OVSController 8 | from mininet.node import CPULimitedHost, Host, Node 9 | from mininet.node import OVSKernelSwitch, UserSwitch 10 | from mininet.cli import CLI 11 | from mininet.log import setLogLevel, info 12 | from mininet.link import TCLink, Intf 13 | from subprocess import call 14 | 15 | def myNetwork(): 16 | 17 | net = Mininet( topo=None, 18 | build=False, 19 | ipBase='10.0.0.0/8') 20 | 21 | info( '*** Adding controller\n' ) 22 | c0=net.addController(name='c0', 23 | controller=RemoteController, 24 | ip='127.0.0.1', 25 | protocol='tcp', 26 | port=6653) 27 | 28 | info( '*** Add switches\n') 29 | s2 = net.addSwitch('s2', cls=OVSKernelSwitch) 30 | s1 = net.addSwitch('s1', cls=OVSKernelSwitch) 31 | s5 = net.addSwitch('s5', cls=OVSKernelSwitch, failMode='standalone') 32 | 33 | info( '*** Add hosts\n') 34 | h2 = net.addHost('h2', cls=Host, ip='10.0.0.2', defaultRoute=None) 35 | h1 = net.addHost('h1', cls=Host, ip='10.0.0.1', defaultRoute=None) 36 | h4 = net.addHost('h4', cls=Host, ip='10.0.0.4', defaultRoute=None) 37 | h3 = net.addHost('h3', cls=Host, ip='10.0.0.3', defaultRoute=None) 38 | 39 | info( '*** Add links\n') 40 | s1s2 = {'bw':400,'loss':0} 41 | net.addLink(s1, s2, cls=TCLink , **s1s2) 42 | s2h1 = {'bw':1000,'loss':10,'max_queue_size':10,'speedup':40} 43 | net.addLink(s2, h1, cls=TCLink , **s2h1) 44 | s2h2 = {'bw':120,'loss':0} 45 | net.addLink(s2, h2, cls=TCLink , **s2h2) 46 | s2h3 = {'bw':400,'loss':20} 47 | net.addLink(s2, h3, cls=TCLink , **s2h3) 48 | s1s5 = {'bw':200,'delay':'12','loss':10} 49 | net.addLink(s1, s5, cls=TCLink , **s1s5) 50 | s5h4 = {'bw':100,'loss':50} 51 | net.addLink(s5, h4, cls=TCLink , **s5h4) 52 | 53 | info( '*** Starting network\n') 54 | net.build() 55 | info( '*** Starting controllers\n') 56 | for controller in net.controllers: 57 | controller.start() 58 | 59 | info( '*** Starting switches\n') 60 | net.get('s2').start([c0]) 61 | net.get('s1').start([c0]) 62 | net.get('s5').start([]) 63 | 64 | info( '*** Post configure switches and hosts\n') 65 | 66 | CLI(net) 67 | net.stop() 68 | 69 | if __name__ == '__main__': 70 | setLogLevel( 'info' ) 71 | myNetwork() 72 | 73 | -------------------------------------------------------------------------------- /Chapter10/10_4_sdn_floodlight.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 10 3 | # This program is optimized for Python 2.7.12. 4 | # It may run on any other version with/without modifications. 5 | 6 | from mininet.net import Mininet 7 | from mininet.node import Controller, RemoteController, OVSController 8 | from mininet.node import CPULimitedHost, Host, Node 9 | from mininet.node import OVSKernelSwitch, UserSwitch 10 | from mininet.node import IVSSwitch 11 | from mininet.cli import CLI 12 | from mininet.log import setLogLevel, info 13 | from mininet.link import TCLink, Intf 14 | from subprocess import call 15 | 16 | def myNetwork(): 17 | 18 | net = Mininet( topo=None, 19 | build=False, 20 | ipBase='10.0.0.0/8') 21 | 22 | info( '*** Adding controller\n' ) 23 | c0=net.addController(name='c0', 24 | controller=RemoteController, 25 | ip='127.0.0.1', 26 | protocol='tcp', 27 | port=6653) 28 | 29 | info( '*** Add switches\n') 30 | s2 = net.addSwitch('s2', cls=OVSKernelSwitch) 31 | s1 = net.addSwitch('s1', cls=IVSSwitch) 32 | 33 | info( '*** Add hosts\n') 34 | h2 = net.addHost('h2', cls=Host, ip='10.0.0.2', defaultRoute=None) 35 | h1 = net.addHost('h1', cls=Host, ip='10.0.0.1', defaultRoute=None) 36 | h3 = net.addHost('h3', cls=Host, ip='10.0.0.3', defaultRoute=None) 37 | 38 | info( '*** Add links\n') 39 | s1s2 = {'bw':400,'loss':0} 40 | net.addLink(s1, s2, cls=TCLink , **s1s2) 41 | s2h1 = {'bw':1000,'loss':10,'max_queue_size':10,'speedup':40} 42 | net.addLink(s2, h1, cls=TCLink , **s2h1) 43 | s2h2 = {'bw':120,'loss':0} 44 | net.addLink(s2, h2, cls=TCLink , **s2h2) 45 | s2h3 = {'bw':400,'loss':20} 46 | net.addLink(s2, h3, cls=TCLink , **s2h3) 47 | 48 | info( '*** Starting network\n') 49 | net.build() 50 | info( '*** Starting controllers\n') 51 | for controller in net.controllers: 52 | controller.start() 53 | 54 | info( '*** Starting switches\n') 55 | net.get('s2').start([c0]) 56 | net.get('s1').start([c0]) 57 | 58 | info( '*** Post configure switches and hosts\n') 59 | 60 | CLI(net) 61 | net.stop() 62 | 63 | if __name__ == '__main__': 64 | setLogLevel( 'info' ) 65 | myNetwork() 66 | 67 | -------------------------------------------------------------------------------- /Chapter10/10_5_sdn_ryu.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 10 3 | # This program is optimized for Python 2.7.12. 4 | # It may run on any other version with/without modifications. 5 | # Adopted from https://github.com/osrg/ryu/blob/master/ryu/app/ws_topology.py 6 | 7 | from socket import error as SocketError 8 | from tinyrpc.exc import InvalidReplyError 9 | from ryu.app.wsgi import ( 10 | ControllerBase, 11 | WSGIApplication, 12 | websocket, 13 | WebSocketRPCClient 14 | ) 15 | from ryu.base import app_manager 16 | from ryu.topology import event, switches 17 | from ryu.controller.handler import set_ev_cls 18 | 19 | 20 | class WebSocketTopology(app_manager.RyuApp): 21 | _CONTEXTS = { 22 | 'wsgi': WSGIApplication, 23 | 'switches': switches.Switches, 24 | } 25 | 26 | def __init__(self, *args, **kwargs): 27 | super(WebSocketTopology, self).__init__(*args, **kwargs) 28 | 29 | self.rpc_clients = [] 30 | 31 | wsgi = kwargs['wsgi'] 32 | wsgi.register(WebSocketTopologyController, {'app': self}) 33 | 34 | # Monitor the events / topology changes 35 | # EventSwitchEnter and EventSwitchLeave for switches entering and leaving. 36 | # EventLinkAdd and EventLinkDelete for links addition and deletion. 37 | # EventHostAdd for hosts addition. 38 | 39 | # Event - Link added 40 | @set_ev_cls(event.EventLinkAdd) 41 | def _event_link_add_handler(self, ev): 42 | msg = ev.link.to_dict() 43 | self._rpc_broadcall('event_link_add', msg) 44 | 45 | # Event - Link deleted 46 | @set_ev_cls(event.EventLinkDelete) 47 | def _event_link_delete_handler(self, ev): 48 | msg = ev.link.to_dict() 49 | self._rpc_broadcall('event_link_delete', msg) 50 | 51 | 52 | def _rpc_broadcall(self, func_name, msg): 53 | disconnected_clients = [] 54 | for rpc_client in self.rpc_clients: 55 | rpc_server = rpc_client.get_proxy() 56 | try: 57 | getattr(rpc_server, func_name)(msg) 58 | except SocketError: 59 | self.logger.debug('WebSocket disconnected: %s', rpc_client.ws) 60 | disconnected_clients.append(rpc_client) 61 | except InvalidReplyError as e: 62 | self.logger.error(e) 63 | 64 | for client in disconnected_clients: 65 | self.rpc_clients.remove(client) 66 | 67 | 68 | class WebSocketTopologyController(ControllerBase): 69 | 70 | def __init__(self, req, link, data, **config): 71 | super(WebSocketTopologyController, self).__init__( 72 | req, link, data, **config) 73 | self.app = data['app'] 74 | 75 | @websocket('topology', '/v1.0/topology/ws') 76 | def _websocket_handler(self, ws): 77 | rpc_client = WebSocketRPCClient(ws) 78 | self.app.rpc_clients.append(rpc_client) 79 | rpc_client.serve_forever() 80 | 81 | -------------------------------------------------------------------------------- /Chapter10/10_6_sdn_pox.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 10 3 | # This program is optimized for Python 2.7.12. 4 | # It may run on any other version with/without modifications. 5 | # Adopted from https://github.com/noxrepo/pox/blob/carp/pox/forwarding/hub.py 6 | # For more examples and tutorials: 7 | # https://github.com/noxrepo/pox/tree/carp/pox 8 | 9 | from pox.core import core 10 | import pox.openflow.libopenflow_01 as of 11 | from pox.lib.util import dpidToStr 12 | 13 | log = core.getLogger() 14 | 15 | # The listener definition: A simple and stupid hub. 16 | def _handle_ConnectionUp (event): 17 | msg = of.ofp_flow_mod() 18 | msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD)) 19 | event.connection.send(msg) 20 | # log the action. 21 | log.info("Hubifying %s", dpidToStr(event.dpid)) 22 | 23 | 24 | # When the application is launched with POX. 25 | def launch (): 26 | #Add a listener (defined above) to the pox.core openflow. 27 | core.openflow.addListenerByName("ConnectionUp", _handle_ConnectionUp) 28 | log.info("Hub is running.") 29 | -------------------------------------------------------------------------------- /Chapter10/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Recipes for SDN 3 | """ 4 | -------------------------------------------------------------------------------- /Chapter10/__pycache__/10_5_sdn_ryu.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Network-Programming-Cookbook-Second-Edition/7a2618500cd7a3a4ff527751664bd9b39bb63a7a/Chapter10/__pycache__/10_5_sdn_ryu.cpython-35.pyc -------------------------------------------------------------------------------- /Chapter11/11_10_requests_throttling.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 11 3 | # This program is optimized for Python 2.7.12. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | import requests 8 | from throttler.base_throttler import BaseThrottler 9 | 10 | 11 | def main(address): 12 | 13 | # Throttle the requests with the BaseThrottler, delaying 1.5s. 14 | bt = BaseThrottler(name='base-throttler', delay=1.5) 15 | 16 | # Visit the address provided by the user. Complete URL only. 17 | r = requests.Request(method='GET', url=address) 18 | 19 | # 10 requests. 20 | reqs = [r for i in range(0, 10)] 21 | 22 | # Submit the requests with the required throttling. 23 | with bt: 24 | throttled_requests = bt.submit(reqs) 25 | 26 | # Print the response for each of the requests. 27 | for r in throttled_requests: 28 | print (r.response) 29 | 30 | # Final status of the requests. 31 | print ("Success: {s}, Failures: {f}".format(s=bt.successes, f=bt.failures)) 32 | 33 | 34 | if __name__ == '__main__': 35 | parser = argparse.ArgumentParser(description='Requests Throttling') 36 | parser.add_argument('--address', action="store", dest="address", default='http://www.google.com') 37 | given_args = parser.parse_args() 38 | address = given_args.address 39 | main (address) 40 | 41 | -------------------------------------------------------------------------------- /Chapter11/11_10_requests_throttling.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################## 3 | # Python Network Programming Cookbook, Second Edition -- Chapter - 11 4 | ############################################################################## 5 | 6 | 7 | # Download and extract RequestsThrottler 8 | wget https://pypi.python.org/packages/d5/db/fc7558a14efa163cd2d3e4515cdfbbfc2dacc1d2c4285b095104c58065c7/RequestsThrottler-0.1.0.tar.gz 9 | tar -xvf RequestsThrottler-0.1.0.tar.gz 10 | cd RequestsThrottler-0.1.0 11 | 12 | # Copy our recipe into the folder 13 | cp ../11_10_requests_throttling.py requests_throttler 14 | 15 | # Configure and Install RequestsThrottling 16 | python setup.py build 17 | sudo python setup.py install 18 | 19 | -------------------------------------------------------------------------------- /Chapter11/11_1_dns_names_with_dnspython.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 11 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | import argparse 8 | import dns.name 9 | 10 | def main(site1, site2): 11 | _site1 = dns.name.from_text(site1) 12 | _site2 = dns.name.from_text(site2) 13 | print("site1 is subdomain of site2: ", _site1.is_subdomain(_site2)) 14 | print("site1 is superdomain of site2: ", _site1.is_superdomain(_site2)) 15 | print("site1 labels: ", _site1.labels) 16 | print("site2 labels: ", _site2.labels) 17 | 18 | if __name__ == '__main__': 19 | parser = argparse.ArgumentParser(description='DNS Python') 20 | parser.add_argument('--site1', action="store", dest="site1", default='www.dnspython.org') 21 | parser.add_argument('--site2', action="store", dest="site2", default='dnspython.org') 22 | given_args = parser.parse_args() 23 | site1 = given_args.site1 24 | site2 = given_args.site2 25 | main (site1, site2) 26 | 27 | -------------------------------------------------------------------------------- /Chapter11/11_2_dns_host_with_dnspython.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 11 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | import argparse 8 | import dns.reversename 9 | import dns.resolver 10 | 11 | def main(address): 12 | n = dns.reversename.from_address(address) 13 | print(n) 14 | print(dns.reversename.to_address(n)) 15 | 16 | try: 17 | # Pointer records (PTR) maps a network interface (IP) to the host name. 18 | domain = str(dns.resolver.query(n,"PTR")[0]) 19 | print(domain) 20 | except Exception as e: 21 | print ("Error while resolving %s: %s" %(address, e)) 22 | 23 | 24 | if __name__ == '__main__': 25 | parser = argparse.ArgumentParser(description='DNS Python') 26 | parser.add_argument('--address', action="store", dest="address", default='127.0.0.1') 27 | given_args = parser.parse_args() 28 | address = given_args.address 29 | main (address) 30 | 31 | -------------------------------------------------------------------------------- /Chapter11/11_3_find_dns_rr_details.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 11 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | import dns.zone 8 | import dns.resolver 9 | import socket 10 | 11 | def main(address): 12 | # IPv4 DNS Records 13 | answer = dns.resolver.query(address, 'A') 14 | for i in xrange(0, len(answer)): 15 | print("Default: ", answer[i]) 16 | 17 | # IPv6 DNS Records 18 | try: 19 | answer6 = dns.resolver.query(address, 'AAAA') 20 | for i in xrange(0, len(answer6)): 21 | print("Default: ", answer6[i]) 22 | except dns.resolver.NoAnswer as e: 23 | print("Exception in resolving the IPv6 Resource Record:", e) 24 | 25 | # MX (Mail Exchanger) Records 26 | try: 27 | mx = dns.resolver.query(address, 'MX') 28 | for i in xrange(0, len(mx)): 29 | print("Default: ", mx[i]) 30 | except dns.resolver.NoAnswer as e: 31 | print("Exception in resolving the MX Resource Record:", e) 32 | 33 | try: 34 | cname_answer = dns.resolver.query(address, 'CNAME') 35 | print("CNAME: ", cname_answer) 36 | except dns.resolver.NoAnswer as e: 37 | print('Exception retrieving CNAME', e) 38 | 39 | try: 40 | ns_answer = dns.resolver.query(address, 'NS') 41 | print(ns_answer) 42 | except dns.resolver.NoAnswer as e: 43 | print("Exception in resolving the NS Resource Record:", e) 44 | 45 | try: 46 | sig_answer = dns.resolver.query(address, 'SIG') 47 | print("SIG: ", sig_answer) 48 | except dns.resolver.NoAnswer as e: 49 | print('Exception retrieving SIG', e) 50 | 51 | try: 52 | key_answer = dns.resolver.query(address, 'KEY') 53 | print("KEY: ", key_answer) 54 | except dns.resolver.NoAnswer as e: 55 | print('Exception retrieving KEY', e) 56 | 57 | soa_answer = dns.resolver.query(address, 'SOA') 58 | print("SOA Answer: ", soa_answer[0].mname) 59 | master_answer = dns.resolver.query(soa_answer[0].mname, 'A') 60 | print("Master Answer: ", master_answer[0].address) 61 | 62 | 63 | if __name__ == '__main__': 64 | parser = argparse.ArgumentParser(description='DNS Python') 65 | parser.add_argument('--address', action="store", dest="address", default='dnspython.org') 66 | given_args = parser.parse_args() 67 | address = given_args.address 68 | main (address) 69 | 70 | -------------------------------------------------------------------------------- /Chapter11/11_4_dns_zone_transfer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 11 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | import dns.zone 8 | import dns.resolver 9 | import socket 10 | 11 | def main(address): 12 | soa_answer = dns.resolver.query(address, 'SOA') 13 | master_answer = dns.resolver.query(soa_answer[0].mname, 'A') 14 | try: 15 | z = dns.zone.from_xfr(dns.query.xfr(master_answer[0].address, address)) 16 | names = z.nodes.keys() 17 | names.sort() 18 | for n in names: 19 | print(z[n].to_text(n)) 20 | except socket.error as e: 21 | print('Failed to perform zone transfer:', e) 22 | except dns.exception.FormError as e: 23 | print('Failed to perform zone transfer:', e) 24 | 25 | 26 | if __name__ == '__main__': 27 | parser = argparse.ArgumentParser(description='DNS Python') 28 | parser.add_argument('--address', action="store", dest="address", default='dnspython.org') 29 | given_args = parser.parse_args() 30 | address = given_args.address 31 | main (address) 32 | 33 | -------------------------------------------------------------------------------- /Chapter11/11_5_query_ntp_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 11 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | import ntplib 8 | from time import ctime 9 | 10 | 11 | def main(address, v): 12 | c = ntplib.NTPClient() 13 | response = c.request(address, version=v) 14 | print("Response Offset: ", response.offset) 15 | print("Version: ", response.version) 16 | print("Response (Time): ", ctime(response.tx_time)) 17 | print("Leap: ", ntplib.leap_to_text(response.leap)) 18 | print("Root Delay: ", response.root_delay) 19 | print(ntplib.ref_id_to_text(response.ref_id)) 20 | 21 | 22 | if __name__ == '__main__': 23 | parser = argparse.ArgumentParser(description='Query NTP Server') 24 | parser.add_argument('--address', action="store", dest="address", default='pool.ntp.org') 25 | parser.add_argument('--version', action="store", dest="version", type=int, default=3) 26 | given_args = parser.parse_args() 27 | address = given_args.address 28 | version = given_args.version 29 | main (address, version) 30 | 31 | -------------------------------------------------------------------------------- /Chapter11/11_6_connect_ldap_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 11 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | from ldap3 import Server, Connection, ALL 8 | 9 | 10 | def main(address): 11 | # Create the Server object with the given address. 12 | # Get ALL information. 13 | server = Server(address, get_info=ALL) 14 | #Create a connection object, and bind with auto bind set to true. 15 | conn = Connection(server, auto_bind=True) 16 | 17 | # Print the LDAP Server Information. 18 | print('******************Server Info**************') 19 | print(server.info) 20 | 21 | # Print the LDAP Server Detailed Schema. 22 | print('******************Server Schema**************') 23 | print(server.schema) 24 | 25 | if __name__ == '__main__': 26 | parser = argparse.ArgumentParser(description='Query LDAP Server') 27 | parser.add_argument('--address', action="store", dest="address", default='ipa.demo1.freeipa.org') 28 | given_args = parser.parse_args() 29 | address = given_args.address 30 | main (address) 31 | 32 | -------------------------------------------------------------------------------- /Chapter11/11_7_query_ldap_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 11 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | from ldap3 import Server, Connection, ALL, core 8 | 9 | 10 | def main(address, dn, password): 11 | # Create the Server object with the given address. 12 | server = Server(address, get_info=ALL) 13 | #Create a connection object, and bind with the given DN and password. 14 | try: 15 | conn = Connection(server, dn, password, auto_bind=True) 16 | print('LDAP Bind Successful.') 17 | print(conn) 18 | except core.exceptions.LDAPBindError as e: 19 | # If the LDAP bind failed for reasons such as authentication failure. 20 | print('LDAP Bind Failed: ', e) 21 | 22 | if __name__ == '__main__': 23 | parser = argparse.ArgumentParser(description='Query LDAP Server') 24 | parser.add_argument('--address', action="store", dest="address", default='ldap.forumsys.com') 25 | parser.add_argument('--dn', action="store", dest="dn", default='cn=read-only-admin,dc=example,dc=com') 26 | parser.add_argument('--password', action="store", dest="password", default='password') 27 | given_args = parser.parse_args() 28 | address = given_args.address 29 | dn = given_args.dn 30 | password = given_args.password 31 | main (address, dn, password) 32 | 33 | -------------------------------------------------------------------------------- /Chapter11/11_7_query_ldap_server_b.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 11 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import argparse 7 | from ldap3 import Server, Connection, ALL, core 8 | 9 | 10 | def main(address, dn, password): 11 | # Create the Server object with the given address. 12 | server = Server(address, get_info=ALL) 13 | #Create a connection object, and bind with the given DN and password. 14 | try: 15 | conn = Connection(server, dn, password, auto_bind=True) 16 | print('LDAP Bind Successful.') 17 | # Perform a search for a pre-defined criteria. 18 | # Mention the search filter / filter type and attributes. 19 | conn.search('dc=example,dc=com', '(&(uid=euler))' , attributes=['sn']) 20 | # Print the resulting entries. 21 | print(conn.entries[0]) 22 | except core.exceptions.LDAPBindError as e: 23 | # If the LDAP bind failed for reasons such as authentication failure. 24 | print('LDAP Bind Failed: ', e) 25 | 26 | if __name__ == '__main__': 27 | parser = argparse.ArgumentParser(description='Query LDAP Server') 28 | parser.add_argument('--address', action="store", dest="address", default='ldap.forumsys.com') 29 | parser.add_argument('--dn', action="store", dest="dn", default='cn=read-only-admin,dc=example,dc=com') 30 | parser.add_argument('--password', action="store", dest="password", default='password') 31 | given_args = parser.parse_args() 32 | address = given_args.address 33 | dn = given_args.dn 34 | password = given_args.password 35 | main (address, dn, password) 36 | 37 | -------------------------------------------------------------------------------- /Chapter11/11_8_read_ldap_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 11 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | # Adopted from http://ldap3.readthedocs.io/tutorial_abstraction_basic.html 6 | 7 | from ldap3 import Server, Connection, ObjectDef, AttrDef, Reader, Writer, ALL 8 | 9 | 10 | def main(): 11 | server = Server('ipa.demo1.freeipa.org', get_info=ALL) 12 | conn = Connection(server, 'uid=admin,cn=users,cn=accounts,dc=demo1,dc=freeipa,dc=org', 'Secret123', auto_bind=True) 13 | person = ObjectDef('person', conn) 14 | r = Reader(conn, person, 'ou=ldap3-tutorial,dc=demo1,dc=freeipa,dc=org') 15 | print(r) 16 | print('************') 17 | person+='uid' 18 | print(r) 19 | 20 | if __name__ == '__main__': 21 | main () 22 | 23 | -------------------------------------------------------------------------------- /Chapter11/11_9_eve_basic_auth.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 11 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | from eve import Eve 7 | from eve.auth import BasicAuth 8 | 9 | class MyBasicAuth(BasicAuth): 10 | def check_auth(self, username, password, allowed_roles, resource, 11 | method): 12 | return username == 'admin' and password == 'secret' 13 | 14 | def run_server(): 15 | app = Eve(auth=MyBasicAuth) 16 | app.run() 17 | 18 | if __name__ == '__main__': 19 | run_server() 20 | 21 | 22 | -------------------------------------------------------------------------------- /Chapter11/settings.py: -------------------------------------------------------------------------------- 1 | DOMAIN = {'people': {}} 2 | -------------------------------------------------------------------------------- /Chapter12/12_4_open_contrail_control_node.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################## 3 | # Python Network Programming Cookbook, Second Edition -- Chapter - 12 4 | # Adopted from https://github.com/Juniper/contrail-controller/wiki/Install-and-Configure-OpenContrail-1.06 5 | ############################################################################## 6 | 7 | # Configue the Ubuntu repositories. 8 | echo "deb http://ppa.launchpad.net/opencontrail/ppa/ubuntu precise main" | sudo tee -a /etc/apt/sources.list.d/opencontrail.list 9 | sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 16BD83506839FE77 10 | sudo apt-get update 11 | 12 | # Install Contrail Control 13 | sudo apt-get install contrail-control 14 | -------------------------------------------------------------------------------- /Chapter12/12_5_open_contrail_analytics_node.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################## 3 | # Python Network Programming Cookbook, Second Edition -- Chapter - 12 4 | # Adopted from https://github.com/Juniper/contrail-controller/wiki/Install-and-Configure-OpenContrail-1.06 5 | ############################################################################## 6 | 7 | # Get the redis server binary from http://ftp.ksu.edu.tw/FTP/Linux/ubuntu/ubuntu/pool/universe/r/redis/ 8 | # You may use any other working mirror as well. 9 | wget http://ftp.ksu.edu.tw/FTP/Linux/ubuntu/ubuntu/pool/universe/r/redis/redis-server_2.6.13-1_amd64.deb 10 | sudo apt-get install libjemalloc1 11 | 12 | # Install redis server 13 | sudo dpkg -i redis-server_2.6.13-1_amd64.deb 14 | 15 | echo "deb http://ppa.launchpad.net/opencontrail/ppa/ubuntu precise main" | sudo tee -a /etc/apt/sources.list.d/opencontrail.list 16 | sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 16BD83506839FE77 17 | sudo apt-get update 18 | 19 | # Install Contrail Analytics 20 | sudo apt-get install contrail-analytics 21 | -------------------------------------------------------------------------------- /Chapter12/12_5_open_contrail_compute_node.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################## 3 | # Python Network Programming Cookbook, Second Edition -- Chapter - 12 4 | # Adopted from https://github.com/Juniper/contrail-controller/wiki/Install-and-Configure-OpenContrail-1.06 5 | ############################################################################## 6 | 7 | # Configue the Ubuntu repositories. 8 | echo "deb http://ppa.launchpad.net/opencontrail/ppa/ubuntu precise main" | sudo tee -a /etc/apt/sources.list.d/opencontrail.list 9 | sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 16BD83506839FE77 10 | sudo apt-get update 11 | 12 | # Install Contrail Virtual Rouer Agent 13 | sudo apt-get install contrail-vrouter-agent 14 | 15 | sudo modprobe vrouter 16 | echo "vrouter" | sudo tee -a /etc/modules 17 | -------------------------------------------------------------------------------- /Chapter12/12_5_open_contrail_configuration_node.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################## 3 | # Python Network Programming Cookbook, Second Edition -- Chapter - 12 4 | # Adopted from https://github.com/Juniper/contrail-controller/wiki/Install-and-Configure-OpenContrail-1.06 5 | ############################################################################## 6 | 7 | # Download and manually install python-support, as it is dropped from Ubuntu 16.04. 8 | wget http://launchpadlibrarian.net/109052632/python-support_1.0.15_all.deb 9 | sudo dpkg -i python-support_1.0.15_all.deb 10 | 11 | # Configuring the package list. 12 | echo "deb http://ppa.launchpad.net/opencontrail/ppa/ubuntu precise main" | sudo tee -a /etc/apt/sources.list.d/opencontrail.list 13 | sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 16BD83506839FE77 14 | echo "deb http://debian.datastax.com/community stable main" | sudo tee -a /etc/apt/sources.list.d/cassandra.sources.list 15 | curl -L http://debian.datastax.com/debian/repo_key | sudo apt-key add - 16 | 17 | # Run update 18 | sudo apt-get update 19 | 20 | # Install dependencies 21 | sudo apt-get install cassandra=1.2.18 zookeeperd rabbitmq-server ifmap-server 22 | 23 | # Install Contrail Config 24 | sudo apt-get install contrail-config 25 | 26 | # Configre ifmap-server 27 | echo "control:control" | sudo tee -a /etc/ifmap-server/basicauthusers.properties 28 | sudo service ifmap-server restart 29 | -------------------------------------------------------------------------------- /Chapter12/12_7_cisco_spark_api.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 12 3 | # This program is optimized for Python 3.5.2 and Python 2.7.12. 4 | # It may run on any other version with/without modifications. 5 | 6 | 7 | from ciscosparkapi import CiscoSparkAPI 8 | 9 | api = CiscoSparkAPI() 10 | 11 | # Create a new demo room 12 | demo_room = api.rooms.create('ciscosparkapi Demonstration') 13 | print('Successfully Created the Room') 14 | 15 | # Post a message to the new room, and upload an image from a web url. 16 | api.messages.create(demo_room.id, text="Welcome to the room!", 17 | files=["https://3.bp.blogspot.com/-wWHD9LVAI7c/WVeyurRmeDI/AAAAAAAADXc/CDY17VfYBdAMbI4GS6dGm2Tc4pHBvmpngCLcBGAs/s1600/IMG_4469.JPG"]) 18 | print('Successfully Posted the Message and the Image to the Room') 19 | -------------------------------------------------------------------------------- /Chapter12/etc/contrail/contrail-analytics-api.conf: -------------------------------------------------------------------------------- 1 | [REDIS] 2 | server=127.0.0.1 3 | redis_server_port=6381 4 | redis_query_port=6381 5 | 6 | -------------------------------------------------------------------------------- /Chapter12/etc/contrail/contrail-collector.conf: -------------------------------------------------------------------------------- 1 | [DISCOVERY] 2 | port=5998 3 | server=127.0.0.1 4 | 5 | [REDIS] 6 | port=6381 7 | server=127.0.0.1 8 | -------------------------------------------------------------------------------- /Chapter12/etc/contrail/contrail-query-engine.conf: -------------------------------------------------------------------------------- 1 | [DISCOVERY] 2 | port=5998 3 | server=127.0.0.1 4 | 5 | [REDIS] 6 | port=6381 7 | server=127.0.0.1 8 | -------------------------------------------------------------------------------- /Chapter12/etc/contrail/contrail-vrouter-agent.conf: -------------------------------------------------------------------------------- 1 | # IP address of discovery server 2 | server=10.8.1.10 3 | 4 | [VIRTUAL-HOST-INTERFACE] 5 | # Everything in this section is mandatory 6 | 7 | # name of virtual host interface 8 | name=vhost0 9 | 10 | # IP address and prefix in ip/prefix_len format 11 | ip=10.8.1.11/24 12 | 13 | # Gateway IP address for virtual host 14 | gateway=10.8.1.254 15 | 16 | # Physical interface name to which virtual host interface maps to 17 | physical_interface=eth1 18 | -------------------------------------------------------------------------------- /Chapter12/etc/contrail/control-node.conf: -------------------------------------------------------------------------------- 1 | [DISCOVERY] 2 | port=5998 3 | server=127.0.0.1 # discovery_server IP address 4 | 5 | [IFMAP] 6 | password=control 7 | user=control 8 | -------------------------------------------------------------------------------- /Chapter12/etc/network/interfaces: -------------------------------------------------------------------------------- 1 | auto eth1 2 | iface eth1 inet static 3 | address 0.0.0.0 4 | up ifconfig $IFACE up 5 | down ifconfig $IFACE down 6 | 7 | auto vhost0 8 | iface vhost0 inet static 9 | pre-up vif --create vhost0 --mac $(cat /sys/class/net/eth1/address) 10 | pre-up vif --add vhost0 --mac $(cat /sys/class/net/eth1/address) --vrf 0 --mode x --type vhost 11 | pre-up vif --add eth1 --mac $(cat /sys/class/net/eth1/address) --vrf 0 --mode x --type physical 12 | address 10.8.1.11 13 | netmask 255.255.255.0 14 | #network 10.8.1.0 15 | #broadcast 10.8.1.255 16 | #gateway 10.8.1.254 17 | # dns-* options are implemented by the resolvconf package, if installed 18 | dns-nameservers 8.8.8.8 19 | -------------------------------------------------------------------------------- /Chapter12/nsx.ini: -------------------------------------------------------------------------------- 1 | # [nsxraml] 2 | # nsxraml_file = <> 3 | # Uncomment the above section and add the path to the raml spec you want to use instead of the bundled version 4 | 5 | [nsxv] 6 | nsx_manager = 7 | nsx_username = admin 8 | nsx_password = 9 | 10 | [vcenter] 11 | vcenter = 12 | vcenter_user = administrator@domain.local 13 | vcenter_passwd = 14 | 15 | [defaults] 16 | transport_zone = 17 | datacenter_name = 18 | edge_datastore = 19 | edge_cluster = 20 | -------------------------------------------------------------------------------- /Chapter13/13_1_quickstart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################## 3 | # Python Network Programming Cookbook, Second Edition -- Chapter - 13 4 | ############################################################################## 5 | 6 | sudo apt-get update 7 | sudo apt-get install -y git 8 | # To offer the capability for sys-admins to restrict program capabilities 9 | # with per-program profiles. 10 | sudo apt-get install -y apparmor 11 | 12 | # Pyyaml is a required package for the configuration scripts. 13 | sudo pip2 install pyyaml 14 | 15 | # Cheetah is a required package for the templates and code generation. 16 | sudo pip2 install cheetah 17 | 18 | git clone https://gerrit.opnfv.org/gerrit/compass4nfv 19 | 20 | cd compass4nfv 21 | 22 | CURRENT_DIR=$PWD 23 | SCENARIO=${SCENARIO:-os-nosdn-nofeature-ha.yml} 24 | 25 | # The build script builds the iso file. 26 | # You could also have downloaded the iso file: such as, 27 | # $ wget http://artifacts.opnfv.org/compass4nfv/danube/opnfv-2017-07-19_08-55-09.iso 28 | ./build.sh 29 | 30 | export TAR_URL=file://$CURRENT_DIR/work/building/compass.tar.gz 31 | 32 | # Export the below locations. 33 | export DHA=$CURRENT_DIR/deploy/conf/vm_environment/$SCENARIO 34 | export NETWORK=$CURRENT_DIR/deploy/conf/vm_environment/network.yml 35 | # Otherwise, your installation will fail with an error message similar to the below: 36 | # + check_input_para 37 | # + python /home/pradeeban/programs/opnfv/util/check_valid.py '' '' 38 | # DHA file doesn't exist 39 | # + '[' 1 -ne 0 ']' 40 | # + exit 1 41 | 42 | 43 | # If you were following the offline installation, you also need to download a jumpshot environment bundle. 44 | # It consists of the dependencies. 45 | # $ wget http://artifacts.opnfv.org/compass4nfv/package/master/jh_env_package.tar.gz 46 | # Now export the absolute path for these directions (following the below example): 47 | # export ISO_URL=file:///home/compass/compass4nfv.iso 48 | # export JHPKG_URL=file:///home/compass/jh_env_package.tar.gz 49 | 50 | # This is the command that is common for both online and offline installations. 51 | ./deploy.sh 52 | -------------------------------------------------------------------------------- /Chapter13/13_2_quickstart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################## 3 | # Python Network Programming Cookbook, Second Edition -- Chapter - 13 4 | ############################################################################## 5 | 6 | # Install Dependencies 7 | sudo apt-get install libpcap-dev 8 | 9 | # Get DPDK 10 | wget http://fast.dpdk.org/rel/dpdk-17.05.1.tar.xz 11 | tar -xvf dpdk-17.05.1.tar.xz 12 | cd dpdk-stable-17.05.1 13 | 14 | # Build DPDK 15 | make config T=x86_64-native-linuxapp-gcc 16 | sed -ri 's,(PMD_PCAP=).*,\1y,' build/.config 17 | make 18 | 19 | # Install DPDK 20 | sudo make install 21 | printf "DPDK Installation Complete.\n" 22 | -------------------------------------------------------------------------------- /Chapter13/13_3_install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################## 3 | # Python Network Programming Cookbook, Second Edition -- Chapter - 13 4 | ############################################################################## 5 | 6 | 7 | # Install Dependencies 8 | sudo apt-get install python-dev python-pip libsnappy-dev 9 | sudo pip install python-snappy kafka-python pyyaml 10 | 11 | # Install SNAS Python API 12 | git clone https://github.com/OpenBMP/openbmp-python-api-message.git 13 | cd openbmp-python-api-message 14 | sudo pip install . 15 | 16 | # Go back to the root directory. 17 | cd .. 18 | 19 | # Download Apache Kafka 20 | wget http://apache.belnet.be/kafka/0.11.0.0/kafka_2.11-0.11.0.0.tgz 21 | 22 | tar -xzf kafka_2.11-0.11.0.0.tgz 23 | 24 | -------------------------------------------------------------------------------- /Chapter13/13_3_quickstart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################## 3 | # Python Network Programming Cookbook, Second Edition -- Chapter - 13 4 | ############################################################################## 5 | 6 | 7 | # Start Zookeeper. To view the logs real time, in a terminal: "tail -f zk-server.out". 8 | 9 | nohup kafka_2.11-0.11.0.0/bin/zookeeper-server-start.sh kafka_2.11-0.11.0.0/config/zookeeper.properties > zk-server.out & 10 | 11 | 12 | # Start Kafka-Server. To view the logs real time, in a terminal: "tail -f kafka-server.out". 13 | nohup kafka_2.11-0.11.0.0/bin/kafka-server-start.sh kafka_2.11-0.11.0.0/config/server.properties > kafka-server.out & 14 | -------------------------------------------------------------------------------- /Chapter13/13_4_dronekit_sitl_simulation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 13 3 | # This program is optimized for Python 2.7.12. 4 | # It may run on any other version with/without modifications. 5 | 6 | import dronekit_sitl 7 | from dronekit import connect, VehicleMode 8 | 9 | # Connect to the default sitl, if not one running. 10 | sitl = dronekit_sitl.start_default() 11 | connection_string = sitl.connection_string() 12 | 13 | # Connect to the Vehicle. 14 | print("Connected: %s" % (connection_string)) 15 | vehicle = connect(connection_string, wait_ready=True) 16 | 17 | print ("GPS: %s" % vehicle.gps_0) 18 | print ("Battery: %s" % vehicle.battery) 19 | print ("Last Heartbeat: %s" % vehicle.last_heartbeat) 20 | print ("Is Armable?: %s" % vehicle.is_armable) 21 | print ("System status: %s" % vehicle.system_status.state) 22 | print ("Mode: %s" % vehicle.mode.name) 23 | 24 | # Close vehicle object before exiting script 25 | vehicle.close() 26 | 27 | print("Completed") 28 | -------------------------------------------------------------------------------- /Chapter13/13_5_pnda_aws_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################## 3 | # Python Network Programming Cookbook, Second Edition -- Chapter - 13 4 | ############################################################################## 5 | 6 | # Clone the Platform Salt 7 | git clone https://github.com/pndaproject/platform-salt.git 8 | cd platform-salt 9 | git checkout release/3.4.1 10 | 11 | cd .. 12 | 13 | # Clone the PNDA AWS Template latest release tag 14 | git clone git@github.com:pndaproject/pnda-aws-templates.git 15 | cd pnda-aws-templates 16 | git checkout release/3.4.1 17 | 18 | # Copy the sample pnda_env.yaml to the project after modifying as in the recipe. 19 | cp ../pnda_env.yaml pnda_env.yaml 20 | 21 | # Install Dependencies 22 | cd cli 23 | sudo pip install -r requirements.txt 24 | 25 | 26 | -------------------------------------------------------------------------------- /Chapter13/config.yaml: -------------------------------------------------------------------------------- 1 | # Kafka server address 2 | bootstrap_servers: localhost:9092 3 | -------------------------------------------------------------------------------- /Chapter14/14_1_healthcheck.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Python Network Programming Cookbook, Second Edition -- Chapter - 14 3 | # This program is optimized for Python 2.7.12 and Python 3.5.2. 4 | # It may run on any other version with/without modifications. 5 | 6 | import socket 7 | from sys import stdout 8 | from time import sleep 9 | import argparse 10 | 11 | def is_alive(address, port): 12 | # Create a socket object to connect with 13 | s = socket.socket() 14 | 15 | # Now try connecting, passing in a tuple with address & port 16 | try: 17 | s.connect((address, port)) 18 | return True 19 | except socket.error: 20 | return False 21 | finally: 22 | s.close() 23 | 24 | 25 | def confirm(addres, port): 26 | while True: 27 | if is_alive(address, port): 28 | stdout.write(address + ":" + str(port) + ' is alive\n') 29 | stdout.flush() 30 | else: 31 | stdout.write(address + ":" + str(port) + ' is dead\n') 32 | stdout.flush() 33 | sleep(10) 34 | 35 | 36 | if __name__ == '__main__': 37 | # setup commandline arguments 38 | parser = argparse.ArgumentParser(description='Health Checker') 39 | parser.add_argument('--address', action="store", dest="address") 40 | parser.add_argument('--port', action="store", dest="port", default=80, type=int) 41 | # parse arguments 42 | given_args = parser.parse_args() 43 | address, port = given_args.address, given_args.port 44 | confirm(address, port) 45 | 46 | 47 | -------------------------------------------------------------------------------- /Chapter14/14_2_benchmark_with_bgperf/.gitignore: -------------------------------------------------------------------------------- 1 | *.py[co] 2 | *~ 3 | *.egg-info/ 4 | *.swp 5 | build/ 6 | dist/ 7 | 8 | GTAGS 9 | GRTAGS 10 | GPATH 11 | GSYMS 12 | *.log 13 | .venv/ 14 | .tox/ 15 | .coverage 16 | covhtml/ 17 | coverage.xml 18 | nosetests.xml 19 | -------------------------------------------------------------------------------- /Chapter14/14_2_benchmark_with_bgperf/README.md: -------------------------------------------------------------------------------- 1 | bgperf 2 | ======== 3 | 4 | bgperf is a performance measurement tool for BGP implementation. 5 | 6 | * [How to install](#how_to_install) 7 | * [How to use](#how_to_use) 8 | * [How bgperf works](https://github.com/osrg/bgperf/blob/master/docs/how_bgperf_works.md) 9 | * [Benchmark remote target](https://github.com/osrg/bgperf/blob/master/docs/benchmark_remote_target.md) 10 | * [MRT injection](https://github.com/osrg/bgperf/blob/master/docs/mrt.md) 11 | 12 | ## Prerequisites 13 | 14 | * Python 3.5 or later 15 | * Docker 16 | 17 | ## How to install 18 | 19 | ```bash 20 | $ git clone https://github.com/pradeeban/bgperf 21 | $ cd bgperf 22 | $ pip install -r pip-requirements.txt 23 | $ sudo python3 bgperf.py --help 24 | usage: bgperf.py [-h] [-b BENCH_NAME] [-d DIR] 25 | {doctor,prepare,update,bench,config} ... 26 | 27 | BGP performance measuring tool 28 | 29 | positional arguments: 30 | {doctor,prepare,update,bench,config} 31 | doctor check env 32 | prepare prepare env 33 | update pull bgp docker images 34 | bench run benchmarks 35 | config generate config 36 | 37 | optional arguments: 38 | -h, --help show this help message and exit 39 | -b BENCH_NAME, --bench-name BENCH_NAME 40 | -d DIR, --dir DIR 41 | $ sudo python3 bgperf.py prepare 42 | $ sudo python3 bgperf.py doctor 43 | docker version ... ok (1.9.1) 44 | bgperf image ... ok 45 | gobgp image ... ok 46 | bird image ... ok 47 | quagga image ... ok 48 | ``` 49 | 50 | ## How to use 51 | 52 | Use `bench` command to start benchmark test. 53 | By default, `bgperf` benchmarks [GoBGP](https://github.com/pradeeban/gobgp). 54 | `bgperf` boots 100 BGP test peers each advertises 100 routes to `GoBGP`. 55 | 56 | ```bash 57 | $ sudo python3 bgperf.py bench 58 | run tester 59 | tester booting.. (100/100) 60 | run gobgp 61 | elapsed: 16sec, cpu: 0.20%, mem: 580.90MB 62 | elapsed time: 11sec 63 | ``` 64 | 65 | To change a target implementation, use `-t` option. 66 | Currently, `bgperf` supports [BIRD](http://bird.network.cz/) and [Quagga](http://www.nongnu.org/quagga/) 67 | other than GoBGP. 68 | 69 | ```bash 70 | $ sudo python3 bgperf.py bench -t bird 71 | run tester 72 | tester booting.. (100/100) 73 | run bird 74 | elapsed: 16sec, cpu: 0.00%, mem: 147.55MB 75 | elapsed time: 11sec 76 | $ sudo python3 bgperf.py bench -t quagga 77 | run tester 78 | tester booting.. (100/100) 79 | run quagga 80 | elapsed: 33sec, cpu: 0.02%, mem: 477.93MB 81 | elapsed time: 28sec 82 | ``` 83 | 84 | To change a load, use following options. 85 | 86 | * `-n` : the number of BGP test peer (default 100) 87 | * `-p` : the number of prefix each peer advertise (default 100) 88 | * `-a` : the number of as-path filter (default 0) 89 | * `-e` : the number of prefix-list filter (default 0) 90 | * `-c` : the number of community-list filter (default 0) 91 | * `-x` : the number of ext-community-list filter (default 0) 92 | 93 | ```bash 94 | $ sudo python3 bgperf.py bench -n 200 -p 50 95 | run tester 96 | tester booting.. (200/200) 97 | run gobgp 98 | elapsed: 23sec, cpu: 0.02%, mem: 1.26GB 99 | elapsed time: 18sec 100 | ``` 101 | 102 | For a comprehensive list of options, run `sudo python3 bgperf.py bench --help`. 103 | -------------------------------------------------------------------------------- /Chapter14/14_2_benchmark_with_bgperf/docs/benchmark_remote_target.md: -------------------------------------------------------------------------------- 1 | # Benchmark remote target 2 | 3 | ![architecture of bgperf](./bgperf_remote.jpg) 4 | 5 | To benchmark remote bgp target, make bgperf configuration file manually and 6 | add `remote: true` to the `target` configuration. 7 | 8 | ```shell 9 | $ cat scenario.yaml 10 | local_prefix: 192.168.10.0/24 11 | monitor: 12 | as: 1001 13 | check-points: [20] 14 | local-address: 192.168.10.2 15 | router-id: 10.10.0.2 16 | target: {as: 1000, local-address: 192.168.10.1, router-id: 10.10.0.1, remote: true} 17 | testers: 18 | - neighbors: 19 | 10.10.0.3: 20 | as: 1003 21 | local-address: 192.168.10.3 22 | paths: [100.0.0.0/32, 100.0.0.1/32, 100.0.0.2/32, 100.0.0.3/32, 100.0.0.4/32, 23 | 100.0.0.5/32, 100.0.0.6/32, 100.0.0.7/32, 100.0.0.8/32, 100.0.0.9/32] 24 | router-id: 10.10.0.3 25 | 10.10.0.4: 26 | as: 1004 27 | local-address: 192.168.10.4 28 | paths: [100.0.0.10/32, 100.0.0.11/32, 100.0.0.12/32, 100.0.0.13/32, 100.0.0.14/32, 29 | 100.0.0.15/32, 100.0.0.16/32, 100.0.0.17/32, 100.0.0.18/32, 100.0.0.19/32] 30 | router-id: 10.10.0.4 31 | ``` 32 | 33 | Use `-f` option to pass the configuration. 34 | 35 | ```shell 36 | $ sudo ./bgperf.py bench -f scenario.yaml 37 | ``` 38 | 39 | For remote benchmarking, bgperf.py can't collect cpu/memory stats. 40 | -------------------------------------------------------------------------------- /Chapter14/14_2_benchmark_with_bgperf/docs/bgperf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Network-Programming-Cookbook-Second-Edition/7a2618500cd7a3a4ff527751664bd9b39bb63a7a/Chapter14/14_2_benchmark_with_bgperf/docs/bgperf.jpg -------------------------------------------------------------------------------- /Chapter14/14_2_benchmark_with_bgperf/docs/bgperf_remote.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Python-Network-Programming-Cookbook-Second-Edition/7a2618500cd7a3a4ff527751664bd9b39bb63a7a/Chapter14/14_2_benchmark_with_bgperf/docs/bgperf_remote.jpg -------------------------------------------------------------------------------- /Chapter14/14_2_benchmark_with_bgperf/docs/how_bgperf_works.md: -------------------------------------------------------------------------------- 1 | # How bgperf works 2 | 3 | ![architecture of bgperf](./bgperf.jpg) 4 | 5 | When `bench` command issued, `bgperf` boots three (or more) docker containers, 6 | `target`, `monitor` and one or more `tester` and connect them via a bridge (`bgperf-br` by default). 7 | 8 | By default, `bgperf` stores all configuration files and log files under `/tmp/bgperf`. 9 | Here is what you can see after issuing `bgperf.py bench -n 10`. 10 | 11 | ```shell 12 | $ tree /tmp/bgperf 13 | /tmp/bgperf 14 | ├── gobgp 15 | │   ├── gobgpd.conf 16 | │   ├── gobgpd.log 17 | │   └── start.sh 18 | ├── monitor 19 | │   ├── gobgpd.conf 20 | │   ├── gobgpd.log 21 | │   └── start.sh 22 | ├── scenario.yaml 23 | └── tester 24 | ├── 10.10.0.10.conf 25 | ├── 10.10.0.10.log 26 | ├── 10.10.0.11.conf 27 | ├── 10.10.0.11.log 28 | ├── 10.10.0.12.conf 29 | ├── 10.10.0.12.log 30 | ├── 10.10.0.3.conf 31 | ├── 10.10.0.3.log 32 | ├── 10.10.0.4.conf 33 | ├── 10.10.0.4.log 34 | ├── 10.10.0.5.conf 35 | ├── 10.10.0.5.log 36 | ├── 10.10.0.6.conf 37 | ├── 10.10.0.6.log 38 | ├── 10.10.0.7.conf 39 | ├── 10.10.0.7.log 40 | ├── 10.10.0.8.conf 41 | ├── 10.10.0.8.log 42 | ├── 10.10.0.9.conf 43 | ├── 10.10.0.9.log 44 | └── start.sh 45 | 46 | 3 directories, 28 files 47 | ``` 48 | 49 | `scenario.yaml` controls all the configuration of benchmark. You can pass your own scenario by using `-f` option. 50 | By default, `bgperf` creates it automatically and places it under `/tmp/bgperf` like above. Let's see what's inside `scenario.yaml`. 51 | 52 | ```shell 53 | $ cat /tmp/bgperf/scenario.yaml 54 | <% 55 | import netaddr 56 | from itertools import islice 57 | 58 | it = netaddr.iter_iprange('100.0.0.0','160.0.0.0') 59 | 60 | def gen_paths(num): 61 | return list('{0}/32'.format(ip) for ip in islice(it, num)) 62 | %> 63 | local_prefix: 10.10.0.0/24 64 | monitor: 65 | as: 1001 66 | check-points: [1000] 67 | local-address: 10.10.0.2 68 | router-id: 10.10.0.2 69 | target: {as: 1000, local-address: 10.10.0.1, router-id: 10.10.0.1} 70 | testers: 71 | - name: tester 72 | neighbors: 73 | 10.10.0.10: 74 | as: 1010 75 | filter: 76 | in: &id001 [] 77 | local-address: 10.10.0.10 78 | paths: ${gen_paths(100)} 79 | router-id: 10.10.0.10 80 | 10.10.0.100: 81 | as: 1100 82 | filter: 83 | in: *id001 84 | local-address: 10.10.0.100 85 | paths: ${gen_paths(100)} 86 | router-id: 10.10.0.100 87 | 10.10.0.101: 88 | as: 1101 89 | filter: 90 | in: *id001 91 | local-address: 10.10.0.101 92 | paths: ${gen_paths(100)} 93 | router-id: 10.10.0.101 94 | ...(snip)... 95 | ``` 96 | 97 | It describes local address, AS number and router-id of each cast. 98 | With regard to tester, it also describes the routes to advertise to the target. 99 | 100 | `check-points` field of `monitor` control when to end the benchmark. 101 | During the benchmark, `bgperf.py` continuously checks how many routes `monitor` have got. 102 | Benchmark ends when the number of received routes gets equal to check-point value. 103 | 104 | As you may notice, `scenario.yaml` is [mako](http://www.makotemplates.org/) templated. You can use mako templating to simplify 105 | your scenario. 106 | -------------------------------------------------------------------------------- /Chapter14/14_2_benchmark_with_bgperf/exabgp.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2016 Nippon Telegraph and Telephone Corporation. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 | # implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | from base import * 17 | 18 | class ExaBGP(Container): 19 | 20 | GUEST_DIR = '/root/config' 21 | 22 | def __init__(self, name, host_dir, conf, image='bgperf/exabgp'): 23 | super(ExaBGP, self).__init__('bgperf_exabgp_' + name, image, host_dir, self.GUEST_DIR, conf) 24 | 25 | @classmethod 26 | def build_image(cls, force=False, tag='bgperf/exabgp', checkout='HEAD', nocache=False): 27 | cls.dockerfile = ''' 28 | FROM ubuntu:latest 29 | WORKDIR /root 30 | RUN apt-get update && apt-get install -qy git python python-setuptools gcc python-dev 31 | RUN easy_install pip 32 | RUN git clone https://github.com/Exa-Networks/exabgp && \ 33 | (cd exabgp && git checkout {0} && pip install six && pip install -r requirements.txt && python setup.py install) 34 | RUN ln -s /root/exabgp /exabgp 35 | '''.format(checkout) 36 | super(ExaBGP, cls).build_image(force, tag, nocache) 37 | 38 | 39 | class ExaBGP_MRTParse(Container): 40 | 41 | GUEST_DIR = '/root/config' 42 | 43 | def __init__(self, name, host_dir, conf, image='bgperf/exabgp_mrtparse'): 44 | super(ExaBGP_MRTParse, self).__init__('bgperf_exabgp_mrtparse_' + name, image, host_dir, self.GUEST_DIR, conf) 45 | 46 | @classmethod 47 | def build_image(cls, force=False, tag='bgperf/exabgp_mrtparse', checkout='HEAD', nocache=False): 48 | cls.dockerfile = ''' 49 | FROM ubuntu:latest 50 | WORKDIR /root 51 | RUN apt-get update && apt-get install -qy git python python-setuptools gcc python-dev 52 | RUN easy_install pip 53 | RUN git clone https://github.com/Exa-Networks/exabgp && \ 54 | (cd exabgp && git checkout {0} && pip install six && pip install -r requirements.txt && python setup.py install) 55 | RUN ln -s /root/exabgp /exabgp 56 | RUN git clone https://github.com/t2mune/mrtparse.git && \ 57 | (cd mrtparse && python setup.py install) 58 | '''.format(checkout) 59 | super(ExaBGP_MRTParse, cls).build_image(force, tag, nocache) 60 | -------------------------------------------------------------------------------- /Chapter14/14_2_benchmark_with_bgperf/monitor.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2016 Nippon Telegraph and Telephone Corporation. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 | # implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | from gobgp import GoBGP 17 | import os 18 | from settings import dckr 19 | import yaml 20 | import json 21 | from threading import Thread 22 | import time 23 | 24 | class Monitor(GoBGP): 25 | 26 | CONTAINER_NAME = 'bgperf_monitor' 27 | 28 | def run(self, conf, dckr_net_name=''): 29 | ctn = super(GoBGP, self).run(dckr_net_name) 30 | config = {} 31 | config['global'] = { 32 | 'config': { 33 | 'as': conf['monitor']['as'], 34 | 'router-id': conf['monitor']['router-id'], 35 | }, 36 | } 37 | config ['neighbors'] = [{'config': {'neighbor-address': conf['target']['local-address'], 38 | 'peer-as': conf['target']['as']}, 39 | 'transport': {'config': {'local-address': conf['monitor']['local-address']}}, 40 | 'timers': {'config': {'connect-retry': 10}}}] 41 | with open('{0}/{1}'.format(self.host_dir, 'gobgpd.conf'), 'w') as f: 42 | f.write(yaml.dump(config)) 43 | self.config_name = 'gobgpd.conf' 44 | startup = '''#!/bin/bash 45 | ulimit -n 65536 46 | gobgpd -t yaml -f {1}/{2} -l {3} > {1}/gobgpd.log 2>&1 47 | '''.format(conf['monitor']['local-address'], self.guest_dir, self.config_name, 'info') 48 | filename = '{0}/start.sh'.format(self.host_dir) 49 | with open(filename, 'w') as f: 50 | f.write(startup) 51 | os.chmod(filename, 0o777) 52 | i = dckr.exec_create(container=self.name, cmd='{0}/start.sh'.format(self.guest_dir)) 53 | dckr.exec_start(i['Id'], detach=True, socket=True) 54 | self.config = conf 55 | return ctn 56 | 57 | def wait_established(self, neighbor): 58 | while True: 59 | neigh = json.loads(self.local('gobgp neighbor {0} -j'.format(neighbor)).decode('utf-8')) 60 | if neigh['state']['session-state'] == 'established': 61 | return 62 | time.sleep(1) 63 | 64 | def stats(self, queue): 65 | def stats(): 66 | cps = self.config['monitor']['check-points'] if 'check-points' in self.config['monitor'] else [] 67 | while True: 68 | info = json.loads(self.local('gobgp neighbor -j').decode('utf-8'))[0] 69 | info['who'] = self.name 70 | state = info['state'] 71 | if 'adj-table' in state and 'accepted' in state['adj-table'] and len(cps) > 0 and int(cps[0]) == int(state['adj-table']['accepted']): 72 | cps.pop(0) 73 | info['checked'] = True 74 | else: 75 | info['checked'] = False 76 | queue.put(info) 77 | time.sleep(1) 78 | 79 | t = Thread(target=stats) 80 | t.daemon = True 81 | t.start() 82 | -------------------------------------------------------------------------------- /Chapter14/14_2_benchmark_with_bgperf/pip-requirements.txt: -------------------------------------------------------------------------------- 1 | docker 2 | pyyaml 3 | pyroute2 4 | nsenter 5 | netaddr 6 | mako 7 | six 8 | packaging 9 | -------------------------------------------------------------------------------- /Chapter14/14_2_benchmark_with_bgperf/settings.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2016 Nippon Telegraph and Telephone Corporation. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 | # implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | try: 18 | from docker import Client 19 | except ImportError: 20 | from docker import APIClient as Client 21 | 22 | dckr = Client(version='auto') 23 | -------------------------------------------------------------------------------- /Chapter14/14_2_benchmark_with_bgperf/tester.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2016 Nippon Telegraph and Telephone Corporation. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 | # implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | from base import Tester 17 | from exabgp import ExaBGP 18 | import os 19 | from settings import dckr 20 | 21 | def rm_line(): 22 | print ('\x1b[1A\x1b[2K\x1b[1D\x1b[1A') 23 | 24 | 25 | class ExaBGPTester(Tester, ExaBGP): 26 | 27 | CONTAINER_NAME_PREFIX = 'bgperf_exabgp_tester_' 28 | 29 | def __init__(self, name, host_dir, conf, image='bgperf/exabgp'): 30 | super(ExaBGPTester, self).__init__(name, host_dir, conf, image) 31 | 32 | def configure_neighbors(self, target_conf): 33 | peers = list(self.conf.get('neighbors', {}).values()) 34 | 35 | for p in peers: 36 | with open('{0}/{1}.conf'.format(self.host_dir, p['router-id']), 'w') as f: 37 | local_address = p['local-address'] 38 | config = '''neighbor {0} {{ 39 | peer-as {1}; 40 | router-id {2}; 41 | local-address {3}; 42 | local-as {4}; 43 | static {{ 44 | '''.format(target_conf['local-address'], target_conf['as'], 45 | p['router-id'], local_address, p['as']) 46 | f.write(config) 47 | for path in p['paths']: 48 | f.write(' route {0} next-hop {1};\n'.format(path, local_address)) 49 | f.write(''' } 50 | }''') 51 | 52 | def get_startup_cmd(self): 53 | startup = ['''#!/bin/bash 54 | ulimit -n 65536'''] 55 | 56 | peers = list(self.conf.get('neighbors', {}).values()) 57 | for p in peers: 58 | startup.append('''env exabgp.log.destination={0}/{1}.log \ 59 | exabgp.daemon.daemonize=true \ 60 | exabgp.daemon.user=root \ 61 | exabgp {0}/{1}.conf'''.format(self.guest_dir, p['router-id'])) 62 | 63 | return '\n'.join(startup) 64 | -------------------------------------------------------------------------------- /Chapter14/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Recipes for BGP 3 | """ 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | --------------------------------------------------------------------------------