]> git.ipfire.org Git - thirdparty/pdns.git/blob - regression-tests.dnsdist/test_TCPFastOpen.py
updated KSK and ZSK Rollover procedures, small fixes in Algorithm Rollover procedure
[thirdparty/pdns.git] / regression-tests.dnsdist / test_TCPFastOpen.py
1 #!/usr/bin/env python
2 import threading
3 import clientsubnetoption
4 import dns
5 import requests
6 import socket
7 import struct
8 from dnsdisttests import DNSDistTest
9
10 class TestBrokenTCPFastOpen(DNSDistTest):
11
12 # this test suite uses a different responder port
13 # because, contrary to the other ones, its
14 # TCP responder will accept a connection, read the
15 # query then just close the connection right away
16 _testServerPort = 5410
17 _testServerRetries = 5
18 _webTimeout = 2.0
19 _webServerPort = 8083
20 _webServerBasicAuthPassword = 'secret'
21 _webServerBasicAuthPasswordHashed = '$scrypt$ln=10,p=1,r=8$6DKLnvUYEeXWh3JNOd3iwg==$kSrhdHaRbZ7R74q3lGBqO1xetgxRxhmWzYJ2Qvfm7JM='
22 _webServerAPIKey = 'apisecret'
23 _webServerAPIKeyHashed = '$scrypt$ln=10,p=1,r=8$9v8JxDfzQVyTpBkTbkUqYg==$bDQzAOHeK1G9UvTPypNhrX48w974ZXbFPtRKS34+aso='
24 _config_params = ['_testServerPort', '_testServerRetries', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKeyHashed']
25 _config_template = """
26 newServer{address="127.0.0.1:%s", useClientSubnet=true, tcpFastOpen=true, retries=%d }
27 webserver("127.0.0.1:%s")
28 setWebserverConfig({password="%s", apiKey="%s"})
29 """
30
31 @classmethod
32 def BrokenTCPResponder(cls, port):
33 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
34 sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
35 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
36 try:
37 sock.bind(("127.0.0.1", port))
38 except socket.error as e:
39 print("Error binding in the TCP responder: %s" % str(e))
40 sys.exit(1)
41
42 sock.listen(100)
43 while True:
44 (conn, _) = sock.accept()
45 conn.settimeout(5.0)
46 data = conn.recv(2)
47 if not data:
48 conn.close()
49 continue
50
51 (datalen,) = struct.unpack("!H", data)
52 data = conn.recv(datalen)
53 conn.close()
54 continue
55
56 sock.close()
57
58 @classmethod
59 def startResponders(cls):
60 print("Launching responders..")
61
62 # Normal responder
63 cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
64 cls._UDPResponder.setDaemon(True)
65 cls._UDPResponder.start()
66
67 # Close the connection right after reading the query
68 cls._TCPResponder = threading.Thread(name='Broken TCP Responder', target=cls.BrokenTCPResponder, args=[cls._testServerPort])
69 cls._TCPResponder.setDaemon(True)
70 cls._TCPResponder.start()
71
72 def testTCOFastOpenOnCloseAfterRead(self):
73 """
74 TCP Fast Open: Close after read
75 """
76 name = 'close-after-read.tfo.tests.powerdns.com.'
77 query = dns.message.make_query(name, 'A', 'IN')
78
79 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
80 self.assertFalse(receivedQuery)
81 self.assertFalse(receivedResponse)
82
83 headers = {'x-api-key': self._webServerAPIKey}
84 url = 'http://127.0.0.1:' + str(self._webServerPort) + '/api/v1/servers/localhost'
85 r = requests.get(url, headers=headers, timeout=self._webTimeout)
86 self.assertTrue(r)
87 self.assertEqual(r.status_code, 200)
88 self.assertTrue(r.json())
89 content = r.json()
90 self.assertTrue(len(content['servers']), 1)
91 server = content['servers'][0]
92 self.assertIn('tcpDiedReadingResponse', server)
93 self.assertEqual(server['tcpDiedReadingResponse'], self._testServerRetries)