]> git.ipfire.org Git - thirdparty/pdns.git/blame - regression-tests.dnsdist/test_TCPFastOpen.py
Merge pull request #13515 from rgacogne/ddist-suffix-visitor-set-action
[thirdparty/pdns.git] / regression-tests.dnsdist / test_TCPFastOpen.py
CommitLineData
1573e7b8
RG
1#!/usr/bin/env python
2import threading
3import clientsubnetoption
4import dns
5import requests
6import socket
7import struct
630eb526 8from dnsdisttests import DNSDistTest, pickAvailablePort
1573e7b8
RG
9
10class 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
630eb526 16 _testServerPort = pickAvailablePort()
1573e7b8
RG
17 _testServerRetries = 5
18 _webTimeout = 2.0
630eb526 19 _webServerPort = pickAvailablePort()
1573e7b8 20 _webServerBasicAuthPassword = 'secret'
2c0392a5 21 _webServerBasicAuthPasswordHashed = '$scrypt$ln=10,p=1,r=8$6DKLnvUYEeXWh3JNOd3iwg==$kSrhdHaRbZ7R74q3lGBqO1xetgxRxhmWzYJ2Qvfm7JM='
1573e7b8 22 _webServerAPIKey = 'apisecret'
2c0392a5 23 _webServerAPIKeyHashed = '$scrypt$ln=10,p=1,r=8$9v8JxDfzQVyTpBkTbkUqYg==$bDQzAOHeK1G9UvTPypNhrX48w974ZXbFPtRKS34+aso='
412f99ef 24 _config_params = ['_testServerPort', '_testServerRetries', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKeyHashed']
1573e7b8
RG
25 _config_template = """
26 newServer{address="127.0.0.1:%s", useClientSubnet=true, tcpFastOpen=true, retries=%d }
fa7e8b5d 27 webserver("127.0.0.1:%s")
cfe95ada 28 setWebserverConfig({password="%s", apiKey="%s"})
1573e7b8
RG
29 """
30
31 @classmethod
32 def BrokenTCPResponder(cls, port):
7373e3a6 33 cls._backgroundThreads[threading.get_native_id()] = True
1573e7b8
RG
34 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
35 sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
36 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
37 try:
38 sock.bind(("127.0.0.1", port))
39 except socket.error as e:
40 print("Error binding in the TCP responder: %s" % str(e))
41 sys.exit(1)
42
43 sock.listen(100)
7373e3a6 44 sock.settimeout(1.0)
1573e7b8 45 while True:
7373e3a6
RG
46 try:
47 (conn, _) = sock.accept()
48 except socket.timeout:
49 if cls._backgroundThreads.get(threading.get_native_id(), False) == False:
50 del cls._backgroundThreads[threading.get_native_id()]
51 break
52 else:
53 continue
54
1573e7b8
RG
55 conn.settimeout(5.0)
56 data = conn.recv(2)
57 if not data:
58 conn.close()
59 continue
60
61 (datalen,) = struct.unpack("!H", data)
62 data = conn.recv(datalen)
63 conn.close()
64 continue
65
66 sock.close()
67
68 @classmethod
69 def startResponders(cls):
70 print("Launching responders..")
71
72 # Normal responder
73 cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
630eb526 74 cls._UDPResponder.daemon = True
1573e7b8
RG
75 cls._UDPResponder.start()
76
77 # Close the connection right after reading the query
78 cls._TCPResponder = threading.Thread(name='Broken TCP Responder', target=cls.BrokenTCPResponder, args=[cls._testServerPort])
630eb526 79 cls._TCPResponder.daemon = True
1573e7b8
RG
80 cls._TCPResponder.start()
81
82 def testTCOFastOpenOnCloseAfterRead(self):
83 """
84 TCP Fast Open: Close after read
85 """
86 name = 'close-after-read.tfo.tests.powerdns.com.'
87 query = dns.message.make_query(name, 'A', 'IN')
88
89 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False)
90 self.assertFalse(receivedQuery)
91 self.assertFalse(receivedResponse)
92
93 headers = {'x-api-key': self._webServerAPIKey}
94 url = 'http://127.0.0.1:' + str(self._webServerPort) + '/api/v1/servers/localhost'
95 r = requests.get(url, headers=headers, timeout=self._webTimeout)
96 self.assertTrue(r)
4bfebc93 97 self.assertEqual(r.status_code, 200)
1573e7b8
RG
98 self.assertTrue(r.json())
99 content = r.json()
100 self.assertTrue(len(content['servers']), 1)
101 server = content['servers'][0]
102 self.assertIn('tcpDiedReadingResponse', server)
4bfebc93 103 self.assertEqual(server['tcpDiedReadingResponse'], self._testServerRetries)