| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  | # This example code is in the Public Domain (or CC0 licensed, at your option.) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Unless required by applicable law or agreed to in writing, this | 
					
						
							|  |  |  | # software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR | 
					
						
							|  |  |  | # CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # -*- coding: utf-8 -*- | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  | from __future__ import print_function, unicode_literals | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  | import os | 
					
						
							|  |  |  | import re | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  | import socket | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  | import sys | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  | from builtins import input | 
					
						
							|  |  |  | from threading import Event, Thread | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  | import netifaces | 
					
						
							|  |  |  | import ttfw_idf | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # -----------  Config  ---------- | 
					
						
							|  |  |  | PORT = 3333 | 
					
						
							|  |  |  | INTERFACE = 'eth0' | 
					
						
							|  |  |  | # ------------------------------- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_my_ip(type): | 
					
						
							|  |  |  |     for i in netifaces.ifaddresses(INTERFACE)[type]: | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |         return i['addr'].replace('%{}'.format(INTERFACE), '') | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TcpServer: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, port, family_addr, persist=False): | 
					
						
							|  |  |  |         self.port = port | 
					
						
							|  |  |  |         self.socket = socket.socket(family_addr, socket.SOCK_STREAM) | 
					
						
							|  |  |  |         self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | 
					
						
							| 
									
										
										
										
											2020-12-23 10:15:27 +01:00
										 |  |  |         self.socket.settimeout(60.0) | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  |         self.shutdown = Event() | 
					
						
							|  |  |  |         self.persist = persist | 
					
						
							|  |  |  |         self.family_addr = family_addr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __enter__(self): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             self.socket.bind(('', self.port)) | 
					
						
							|  |  |  |         except socket.error as e: | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |             print('Bind failed:{}'.format(e)) | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  |             raise | 
					
						
							|  |  |  |         self.socket.listen(1) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |         print('Starting server on port={} family_addr={}'.format(self.port, self.family_addr)) | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  |         self.server_thread = Thread(target=self.run_server) | 
					
						
							|  |  |  |         self.server_thread.start() | 
					
						
							|  |  |  |         return self | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __exit__(self, exc_type, exc_value, traceback): | 
					
						
							|  |  |  |         if self.persist: | 
					
						
							|  |  |  |             sock = socket.socket(self.family_addr, socket.SOCK_STREAM) | 
					
						
							|  |  |  |             sock.connect(('localhost', self.port)) | 
					
						
							|  |  |  |             sock.sendall(b'Stop', ) | 
					
						
							|  |  |  |             sock.close() | 
					
						
							|  |  |  |             self.shutdown.set() | 
					
						
							|  |  |  |         self.shutdown.set() | 
					
						
							|  |  |  |         self.server_thread.join() | 
					
						
							|  |  |  |         self.socket.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def run_server(self): | 
					
						
							|  |  |  |         while not self.shutdown.is_set(): | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 conn, address = self.socket.accept()  # accept new connection | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |                 print('Connection from: {}'.format(address)) | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  |                 conn.setblocking(1) | 
					
						
							|  |  |  |                 data = conn.recv(1024) | 
					
						
							|  |  |  |                 if not data: | 
					
						
							|  |  |  |                     return | 
					
						
							|  |  |  |                 data = data.decode() | 
					
						
							|  |  |  |                 print('Received data: ' + data) | 
					
						
							|  |  |  |                 reply = 'OK: ' + data | 
					
						
							|  |  |  |                 conn.send(reply.encode()) | 
					
						
							|  |  |  |                 conn.close() | 
					
						
							|  |  |  |             except socket.error as e: | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |                 print('Running server failed:{}'.format(e)) | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  |                 raise | 
					
						
							|  |  |  |             if not self.persist: | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-25 15:20:30 +05:30
										 |  |  | @ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') | 
					
						
							| 
									
										
										
										
											2020-12-23 10:15:27 +01:00
										 |  |  | def test_examples_protocol_socket_tcpclient(env, extra_data): | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     steps: | 
					
						
							|  |  |  |       1. join AP | 
					
						
							|  |  |  |       2. have the board connect to the server | 
					
						
							|  |  |  |       3. send and receive data | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |     dut1 = env.get_dut('tcp_client', 'examples/protocols/sockets/tcp_client', dut_class=ttfw_idf.ESP32DUT) | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  |     # check and log bin size | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |     binary_file = os.path.join(dut1.app.binary_path, 'tcp_client.bin') | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  |     bin_size = os.path.getsize(binary_file) | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |     ttfw_idf.log_performance('tcp_client_bin_size', '{}KB'.format(bin_size // 1024)) | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # start test | 
					
						
							|  |  |  |     dut1.start_app() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |     ipv4 = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30)[0] | 
					
						
							| 
									
										
										
										
											2020-12-23 10:15:27 +01:00
										 |  |  |     ipv6_r = r':'.join((r'[0-9a-fA-F]{4}',) * 8)    # expect all 8 octets from IPv6 (assumes it's printed in the long form) | 
					
						
							|  |  |  |     ipv6 = dut1.expect(re.compile(r' IPv6 address: ({})'.format(ipv6_r)), timeout=30)[0] | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |     print('Connected with IPv4={} and IPv6={}'.format(ipv4, ipv6)) | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # test IPv4 | 
					
						
							|  |  |  |     with TcpServer(PORT, socket.AF_INET): | 
					
						
							| 
									
										
										
										
											2020-12-23 10:15:27 +01:00
										 |  |  |         server_ip = get_my_ip(netifaces.AF_INET) | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |         print('Connect tcp client to server IP={}'.format(server_ip)) | 
					
						
							| 
									
										
										
										
											2020-12-23 10:15:27 +01:00
										 |  |  |         dut1.write(server_ip) | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |         dut1.expect(re.compile(r'OK: Message from ESP32')) | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  |     # test IPv6 | 
					
						
							|  |  |  |     with TcpServer(PORT, socket.AF_INET6): | 
					
						
							| 
									
										
										
										
											2020-12-23 10:15:27 +01:00
										 |  |  |         server_ip = get_my_ip(netifaces.AF_INET6) | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |         print('Connect tcp client to server IP={}'.format(server_ip)) | 
					
						
							| 
									
										
										
										
											2020-12-23 10:15:27 +01:00
										 |  |  |         dut1.write(server_ip) | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |         dut1.expect(re.compile(r'OK: Message from ESP32')) | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |     if sys.argv[1:] and sys.argv[1].startswith('IPv'):     # if additional arguments provided: | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  |         # Usage: example_test.py <IPv4|IPv6> | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |         family_addr = socket.AF_INET6 if sys.argv[1] == 'IPv6' else socket.AF_INET | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  |         with TcpServer(PORT, family_addr, persist=True) as s: | 
					
						
							| 
									
										
										
										
											2021-01-26 10:49:01 +08:00
										 |  |  |             print(input('Press Enter stop the server...')) | 
					
						
							| 
									
										
										
										
											2020-03-17 20:30:33 +01:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2020-12-23 10:15:27 +01:00
										 |  |  |         test_examples_protocol_socket_tcpclient() |