3 import clientsubnetoption
8 from dnsdisttests
import DNSDistTest
10 class TestBrokenTCPFastOpen(DNSDistTest
):
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
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"})
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)
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
))
44 (conn
, _
) = sock
.accept()
51 (datalen
,) = struct
.unpack("!H", data
)
52 data
= conn
.recv(datalen
)
59 def startResponders(cls
):
60 print("Launching responders..")
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()
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()
72 def testTCOFastOpenOnCloseAfterRead(self
):
74 TCP Fast Open: Close after read
76 name
= 'close-after-read.tfo.tests.powerdns.com.'
77 query
= dns
.message
.make_query(name
, 'A', 'IN')
79 (receivedQuery
, receivedResponse
) = self
.sendTCPQuery(query
, response
=None, useQueue
=False)
80 self
.assertFalse(receivedQuery
)
81 self
.assertFalse(receivedResponse
)
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
)
87 self
.assertEqual(r
.status_code
, 200)
88 self
.assertTrue(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
)