mdns_example_test.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import re
  2. import os
  3. import socket
  4. import time
  5. import struct
  6. import dpkt
  7. import dpkt.dns
  8. from threading import Thread, Event
  9. from tiny_test_fw import DUT
  10. import ttfw_idf
  11. # g_run_server = True
  12. # g_done = False
  13. stop_mdns_server = Event()
  14. esp_answered = Event()
  15. def get_dns_query_for_esp(esp_host):
  16. dns = dpkt.dns.DNS(b'\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01')
  17. dns.qd[0].name = esp_host + u'.local'
  18. print("Created query for esp host: {} ".format(dns.__repr__()))
  19. return dns.pack()
  20. def get_dns_answer_to_mdns(tester_host):
  21. dns = dpkt.dns.DNS(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
  22. dns.op = dpkt.dns.DNS_QR | dpkt.dns.DNS_AA
  23. dns.rcode = dpkt.dns.DNS_RCODE_NOERR
  24. arr = dpkt.dns.DNS.RR()
  25. arr.cls = dpkt.dns.DNS_IN
  26. arr.type = dpkt.dns.DNS_A
  27. arr.name = tester_host
  28. arr.ip = socket.inet_aton('127.0.0.1')
  29. dns. an.append(arr)
  30. print("Created answer to mdns query: {} ".format(dns.__repr__()))
  31. return dns.pack()
  32. def get_dns_answer_to_mdns_lwip(tester_host, id):
  33. dns = dpkt.dns.DNS(b"\x5e\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x0a\x64\x61\x76\x69\x64"
  34. b"\x2d\x63\x6f\x6d\x70\x05\x6c\x6f\x63\x61\x6c\x00\x00\x01\x00\x01\xc0\x0c"
  35. b"\x00\x01\x00\x01\x00\x00\x00\x0a\x00\x04\xc0\xa8\x0a\x6c")
  36. dns.qd[0].name = tester_host
  37. dns.an[0].name = tester_host
  38. dns.an[0].ip = socket.inet_aton('127.0.0.1')
  39. dns.an[0].rdata = socket.inet_aton('127.0.0.1')
  40. dns.id = id
  41. print("Created answer to mdns (lwip) query: {} ".format(dns.__repr__()))
  42. return dns.pack()
  43. def mdns_server(esp_host):
  44. global esp_answered
  45. UDP_IP = "0.0.0.0"
  46. UDP_PORT = 5353
  47. MCAST_GRP = '224.0.0.251'
  48. TESTER_NAME = u'tinytester.local'
  49. TESTER_NAME_LWIP = u'tinytester-lwip.local'
  50. sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  51. sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  52. sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
  53. sock.bind((UDP_IP,UDP_PORT))
  54. mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)
  55. sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
  56. sock.settimeout(30)
  57. while not stop_mdns_server.is_set():
  58. try:
  59. if not esp_answered.is_set():
  60. sock.sendto(get_dns_query_for_esp(esp_host), (MCAST_GRP,UDP_PORT))
  61. time.sleep(0.2)
  62. data, addr = sock.recvfrom(1024)
  63. dns = dpkt.dns.DNS(data)
  64. if len(dns.qd) > 0 and dns.qd[0].type == dpkt.dns.DNS_A:
  65. if dns.qd[0].name == TESTER_NAME:
  66. print("Received query: {} ".format(dns.__repr__()))
  67. sock.sendto(get_dns_answer_to_mdns(TESTER_NAME), (MCAST_GRP,UDP_PORT))
  68. elif dns.qd[0].name == TESTER_NAME_LWIP:
  69. print("Received query: {} ".format(dns.__repr__()))
  70. sock.sendto(get_dns_answer_to_mdns_lwip(TESTER_NAME_LWIP, dns.id), addr)
  71. if len(dns.an) > 0 and dns.an[0].type == dpkt.dns.DNS_A:
  72. if dns.an[0].name == esp_host + u'.local':
  73. print("Received answer to esp32-mdns query: {}".format(dns.__repr__()))
  74. esp_answered.set()
  75. except socket.timeout:
  76. break
  77. except dpkt.UnpackError:
  78. continue
  79. @ttfw_idf.idf_example_test(env_tag="Example_WIFI")
  80. def test_examples_protocol_mdns(env, extra_data):
  81. global stop_mdns_server
  82. """
  83. steps: |
  84. 1. join AP + init mdns example
  85. 2. get the dut host name (and IP address)
  86. 3. check the mdns name is accessible
  87. 4. check DUT output if mdns advertized host is resolved
  88. """
  89. dut1 = env.get_dut("mdns-test", "examples/protocols/mdns", dut_class=ttfw_idf.ESP32DUT)
  90. # check and log bin size
  91. binary_file = os.path.join(dut1.app.binary_path, "mdns-test.bin")
  92. bin_size = os.path.getsize(binary_file)
  93. ttfw_idf.log_performance("mdns-test_bin_size", "{}KB".format(bin_size // 1024))
  94. ttfw_idf.check_performance("mdns-test_bin_size", bin_size // 1024, dut1.TARGET)
  95. # 1. start mdns application
  96. dut1.start_app()
  97. # 2. get the dut host name (and IP address)
  98. specific_host = dut1.expect(re.compile(r"mdns hostname set to: \[([^\]]+)\]"), timeout=30)
  99. specific_host = str(specific_host[0])
  100. thread1 = Thread(target=mdns_server, args=(specific_host,))
  101. thread1.start()
  102. try:
  103. dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30)
  104. except DUT.ExpectTimeout:
  105. stop_mdns_server.set()
  106. thread1.join()
  107. raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
  108. # 3. check the mdns name is accessible
  109. if not esp_answered.wait(timeout=30):
  110. raise ValueError('Test has failed: did not receive mdns answer within timeout')
  111. # 4. check DUT output if mdns advertized host is resolved
  112. try:
  113. dut1.expect(re.compile(r"mdns-test: Query A: tinytester.local resolved to: 127.0.0.1"), timeout=30)
  114. dut1.expect(re.compile(r"mdns-test: gethostbyname: tinytester-lwip.local resolved to: 127.0.0.1"), timeout=30)
  115. dut1.expect(re.compile(r"mdns-test: getaddrinfo: tinytester-lwip.local resolved to: 127.0.0.1"), timeout=30)
  116. finally:
  117. stop_mdns_server.set()
  118. thread1.join()
  119. if __name__ == '__main__':
  120. test_examples_protocol_mdns()