├── .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 |
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 | 
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 | 
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 |
--------------------------------------------------------------------------------