| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  | import re | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import socket | 
					
						
							|  |  |  | import time | 
					
						
							|  |  |  | import struct | 
					
						
							| 
									
										
										
										
											2018-12-04 08:32:48 +01:00
										 |  |  | import dpkt | 
					
						
							|  |  |  | import dpkt.dns | 
					
						
							| 
									
										
										
										
											2019-06-19 13:20:58 +02:00
										 |  |  | from threading import Thread, Event | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # this is a test case write with tiny-test-fw. | 
					
						
							|  |  |  | # to run test cases outside tiny-test-fw, | 
					
						
							|  |  |  | # we need to set environment variable `TEST_FW_PATH`, | 
					
						
							|  |  |  | # then get and insert `TEST_FW_PATH` to sys path before import FW module | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-04 08:32:48 +01:00
										 |  |  | try: | 
					
						
							|  |  |  |     import IDF | 
					
						
							| 
									
										
										
										
											2019-08-29 17:54:14 +08:00
										 |  |  |     from IDF.IDFDUT import ESP32DUT | 
					
						
							| 
									
										
										
										
											2018-12-04 08:32:48 +01:00
										 |  |  | except ImportError: | 
					
						
							|  |  |  |     test_fw_path = os.getenv("TEST_FW_PATH") | 
					
						
							|  |  |  |     if test_fw_path and test_fw_path not in sys.path: | 
					
						
							|  |  |  |         sys.path.insert(0, test_fw_path) | 
					
						
							|  |  |  |     import IDF | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-04 08:32:48 +01:00
										 |  |  | import DUT | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 13:20:58 +02:00
										 |  |  | # g_run_server = True | 
					
						
							|  |  |  | # g_done = False | 
					
						
							|  |  |  | stop_mdns_server = Event() | 
					
						
							|  |  |  | esp_answered = Event() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_dns_query_for_esp(esp_host): | 
					
						
							|  |  |  |     dns = dpkt.dns.DNS(b'\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01') | 
					
						
							|  |  |  |     dns.qd[0].name = esp_host + u'.local' | 
					
						
							|  |  |  |     print("Created query for esp host: {} ".format(dns.__repr__())) | 
					
						
							|  |  |  |     return dns.pack() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_dns_answer_to_mdns(tester_host): | 
					
						
							|  |  |  |     dns = dpkt.dns.DNS(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') | 
					
						
							|  |  |  |     dns.op = dpkt.dns.DNS_QR | dpkt.dns.DNS_AA | 
					
						
							|  |  |  |     dns.rcode = dpkt.dns.DNS_RCODE_NOERR | 
					
						
							|  |  |  |     arr = dpkt.dns.DNS.RR() | 
					
						
							|  |  |  |     arr.cls = dpkt.dns.DNS_IN | 
					
						
							|  |  |  |     arr.type = dpkt.dns.DNS_A | 
					
						
							|  |  |  |     arr.name = tester_host | 
					
						
							|  |  |  |     arr.ip = socket.inet_aton('127.0.0.1') | 
					
						
							|  |  |  |     dns. an.append(arr) | 
					
						
							|  |  |  |     print("Created answer to mdns query: {} ".format(dns.__repr__())) | 
					
						
							|  |  |  |     return dns.pack() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_dns_answer_to_mdns_lwip(tester_host, id): | 
					
						
							|  |  |  |     dns = dpkt.dns.DNS(b"\x5e\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x0a\x64\x61\x76\x69\x64" | 
					
						
							|  |  |  |                        b"\x2d\x63\x6f\x6d\x70\x05\x6c\x6f\x63\x61\x6c\x00\x00\x01\x00\x01\xc0\x0c" | 
					
						
							|  |  |  |                        b"\x00\x01\x00\x01\x00\x00\x00\x0a\x00\x04\xc0\xa8\x0a\x6c") | 
					
						
							|  |  |  |     dns.qd[0].name = tester_host | 
					
						
							|  |  |  |     dns.an[0].name = tester_host | 
					
						
							|  |  |  |     dns.an[0].ip = socket.inet_aton('127.0.0.1') | 
					
						
							|  |  |  |     dns.an[0].rdata = socket.inet_aton('127.0.0.1') | 
					
						
							|  |  |  |     dns.id = id | 
					
						
							|  |  |  |     print("Created answer to mdns (lwip) query: {} ".format(dns.__repr__())) | 
					
						
							|  |  |  |     return dns.pack() | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-04 08:32:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  | def mdns_server(esp_host): | 
					
						
							| 
									
										
										
										
											2019-06-19 13:20:58 +02:00
										 |  |  |     global esp_answered | 
					
						
							| 
									
										
										
										
											2018-12-04 08:32:48 +01:00
										 |  |  |     UDP_IP = "0.0.0.0" | 
					
						
							|  |  |  |     UDP_PORT = 5353 | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  |     MCAST_GRP = '224.0.0.251' | 
					
						
							| 
									
										
										
										
											2019-06-19 13:20:58 +02:00
										 |  |  |     TESTER_NAME = u'tinytester.local' | 
					
						
							|  |  |  |     TESTER_NAME_LWIP = u'tinytester-lwip.local' | 
					
						
							| 
									
										
										
										
											2018-12-04 08:32:48 +01:00
										 |  |  |     sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  |     sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | 
					
						
							|  |  |  |     sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) | 
					
						
							| 
									
										
										
										
											2018-12-04 08:32:48 +01:00
										 |  |  |     sock.bind((UDP_IP,UDP_PORT)) | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  |     mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) | 
					
						
							|  |  |  |     sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) | 
					
						
							|  |  |  |     sock.settimeout(30) | 
					
						
							| 
									
										
										
										
											2019-06-19 13:20:58 +02:00
										 |  |  |     while not stop_mdns_server.is_set(): | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2019-06-19 13:20:58 +02:00
										 |  |  |             if not esp_answered.is_set(): | 
					
						
							|  |  |  |                 sock.sendto(get_dns_query_for_esp(esp_host), (MCAST_GRP,UDP_PORT)) | 
					
						
							|  |  |  |                 time.sleep(0.2) | 
					
						
							|  |  |  |             data, addr = sock.recvfrom(1024) | 
					
						
							|  |  |  |             dns = dpkt.dns.DNS(data) | 
					
						
							| 
									
										
										
										
											2018-12-04 08:32:48 +01:00
										 |  |  |             if len(dns.qd) > 0 and dns.qd[0].type == dpkt.dns.DNS_A: | 
					
						
							| 
									
										
										
										
											2019-06-19 13:20:58 +02:00
										 |  |  |                 if dns.qd[0].name == TESTER_NAME: | 
					
						
							|  |  |  |                     print("Received query: {} ".format(dns.__repr__())) | 
					
						
							|  |  |  |                     sock.sendto(get_dns_answer_to_mdns(TESTER_NAME), (MCAST_GRP,UDP_PORT)) | 
					
						
							|  |  |  |                 elif dns.qd[0].name == TESTER_NAME_LWIP: | 
					
						
							|  |  |  |                     print("Received query: {} ".format(dns.__repr__())) | 
					
						
							|  |  |  |                     sock.sendto(get_dns_answer_to_mdns_lwip(TESTER_NAME_LWIP, dns.id), addr) | 
					
						
							| 
									
										
										
										
											2018-12-04 08:32:48 +01:00
										 |  |  |             if len(dns.an) > 0 and dns.an[0].type == dpkt.dns.DNS_A: | 
					
						
							|  |  |  |                 if dns.an[0].name == esp_host + u'.local': | 
					
						
							| 
									
										
										
										
											2019-06-19 13:20:58 +02:00
										 |  |  |                     print("Received answer to esp32-mdns query: {}".format(dns.__repr__())) | 
					
						
							|  |  |  |                     esp_answered.set() | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  |         except socket.timeout: | 
					
						
							|  |  |  |             break | 
					
						
							| 
									
										
										
										
											2019-01-25 20:24:30 +01:00
										 |  |  |         except dpkt.UnpackError: | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-04 08:32:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  | @IDF.idf_example_test(env_tag="Example_WIFI") | 
					
						
							|  |  |  | def test_examples_protocol_mdns(env, extra_data): | 
					
						
							| 
									
										
										
										
											2019-06-19 13:20:58 +02:00
										 |  |  |     global stop_mdns_server | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     steps: | | 
					
						
							|  |  |  |       1. join AP + init mdns example | 
					
						
							|  |  |  |       2. get the dut host name (and IP address) | 
					
						
							|  |  |  |       3. check the mdns name is accessible | 
					
						
							|  |  |  |       4. check DUT output if mdns advertized host is resolved | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2019-08-29 17:54:14 +08:00
										 |  |  |     dut1 = env.get_dut("mdns-test", "examples/protocols/mdns", dut_class=ESP32DUT) | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  |     # check and log bin size | 
					
						
							|  |  |  |     binary_file = os.path.join(dut1.app.binary_path, "mdns-test.bin") | 
					
						
							|  |  |  |     bin_size = os.path.getsize(binary_file) | 
					
						
							| 
									
										
										
										
											2018-12-04 08:32:48 +01:00
										 |  |  |     IDF.log_performance("mdns-test_bin_size", "{}KB".format(bin_size // 1024)) | 
					
						
							|  |  |  |     IDF.check_performance("mdns-test_bin_size", bin_size // 1024) | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  |     # 1. start mdns application | 
					
						
							|  |  |  |     dut1.start_app() | 
					
						
							|  |  |  |     # 2. get the dut host name (and IP address) | 
					
						
							|  |  |  |     specific_host = dut1.expect(re.compile(r"mdns hostname set to: \[([^\]]+)\]"), timeout=30) | 
					
						
							|  |  |  |     specific_host = str(specific_host[0]) | 
					
						
							| 
									
										
										
										
											2019-01-25 20:24:30 +01:00
										 |  |  |     thread1 = Thread(target=mdns_server, args=(specific_host,)) | 
					
						
							|  |  |  |     thread1.start() | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  |     try: | 
					
						
							| 
									
										
										
										
											2018-12-04 08:32:48 +01:00
										 |  |  |         dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  |     except DUT.ExpectTimeout: | 
					
						
							| 
									
										
										
										
											2019-06-19 13:20:58 +02:00
										 |  |  |         stop_mdns_server.set() | 
					
						
							| 
									
										
										
										
											2019-01-25 20:24:30 +01:00
										 |  |  |         thread1.join() | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  |         raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') | 
					
						
							|  |  |  |     # 3. check the mdns name is accessible | 
					
						
							| 
									
										
										
										
											2019-06-19 13:20:58 +02:00
										 |  |  |     if not esp_answered.wait(timeout=30): | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  |         raise ValueError('Test has failed: did not receive mdns answer within timeout') | 
					
						
							|  |  |  |     # 4. check DUT output if mdns advertized host is resolved | 
					
						
							| 
									
										
										
										
											2019-01-25 20:24:30 +01:00
										 |  |  |     try: | 
					
						
							|  |  |  |         dut1.expect(re.compile(r"mdns-test: Query A: tinytester.local resolved to: 127.0.0.1"), timeout=30) | 
					
						
							| 
									
										
										
										
											2019-06-19 13:20:58 +02:00
										 |  |  |         dut1.expect(re.compile(r"mdns-test: gethostbyname: tinytester-lwip.local resolved to: 127.0.0.1"), timeout=30) | 
					
						
							|  |  |  |         dut1.expect(re.compile(r"mdns-test: getaddrinfo: tinytester-lwip.local resolved to: 127.0.0.1"), timeout=30) | 
					
						
							| 
									
										
										
										
											2019-01-25 20:24:30 +01:00
										 |  |  |     finally: | 
					
						
							| 
									
										
										
										
											2019-06-19 13:20:58 +02:00
										 |  |  |         stop_mdns_server.set() | 
					
						
							| 
									
										
										
										
											2019-01-25 20:24:30 +01:00
										 |  |  |         thread1.join() | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-04 08:32:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-12 16:45:52 +02:00
										 |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     test_examples_protocol_mdns() |