]>
git.ipfire.org Git - thirdparty/pdns.git/blob - regression-tests.dnsdist/test_TCPShort.py
7 from dnsdisttests
import DNSDistTest
14 class TestTCPShort(DNSDistTest
):
15 # this test suite uses a different responder port
16 # because, contrary to the other ones, its
17 # responders allow trailing data and multiple responses,
18 # and we don't want to mix things up.
19 _testServerPort
= 5361
20 _serverKey
= 'server.key'
21 _serverCert
= 'server.chain'
22 _serverName
= 'tls.tests.dnsdist.org'
26 _config_template
= """
27 newServer{address="127.0.0.1:%s"}
28 addTLSLocal("127.0.0.1:%s", "%s", "%s")
31 _config_params
= ['_testServerPort', '_tlsServerPort', '_serverCert', '_serverKey', '_tcpSendTimeout']
34 def startResponders(cls
):
35 print("Launching responders..")
37 cls
._UDPResponder
= threading
.Thread(name
='UDP Responder', target
=cls
.UDPResponder
, args
=[cls
._testServerPort
, cls
._toResponderQueue
, cls
._fromResponderQueue
, True])
38 cls
._UDPResponder
.setDaemon(True)
39 cls
._UDPResponder
.start()
41 cls
._TCPResponder
= threading
.Thread(name
='TCP Responder', target
=cls
.TCPResponder
, args
=[cls
._testServerPort
, cls
._toResponderQueue
, cls
._fromResponderQueue
, True, True])
42 cls
._TCPResponder
.setDaemon(True)
43 cls
._TCPResponder
.start()
45 def testTCPShortRead(self
):
47 TCP: Short read from client
49 name
= 'short-read.tcp-short.tests.powerdns.com.'
50 query
= dns
.message
.make_query(name
, 'A', 'IN')
51 expectedResponse
= dns
.message
.make_response(query
)
52 rrset
= dns
.rrset
.from_text(name
,
57 expectedResponse
.answer
.append(rrset
)
59 conn
= self
.openTCPConnection()
60 wire
= query
.to_wire()
61 # announce 7680 bytes (more than 4096, less than 8192 - the 512 bytes dnsdist is going to add)
63 paddingSize
= announcedSize
- len(wire
)
64 wire
= wire
+ (b
'A' * (paddingSize
- 1))
65 self
._toResponderQueue
.put(expectedResponse
, True, 2.0)
67 sizeBytes
= struct
.pack("!H", announcedSize
)
68 conn
.send(sizeBytes
[:1])
70 conn
.send(sizeBytes
[1:])
71 # send announcedSize bytes minus 1 so we get a second read
75 conn
.send(b
'A' * 1024)
77 (receivedQuery
, receivedResponse
) = self
.recvTCPResponseOverConnection(conn
, True)
80 self
.assertTrue(receivedQuery
)
81 self
.assertTrue(receivedResponse
)
82 receivedQuery
.id = query
.id
83 self
.assertEquals(query
, receivedQuery
)
84 self
.assertEquals(receivedResponse
, expectedResponse
)
86 def testTCPTLSShortRead(self
):
88 TCP/TLS: Short read from client
90 name
= 'short-read-tls.tcp-short.tests.powerdns.com.'
91 query
= dns
.message
.make_query(name
, 'A', 'IN')
92 expectedResponse
= dns
.message
.make_response(query
)
93 rrset
= dns
.rrset
.from_text(name
,
98 expectedResponse
.answer
.append(rrset
)
100 conn
= self
.openTLSConnection(self
._tlsServerPort
, self
._serverName
, self
._caCert
)
101 wire
= query
.to_wire()
102 # announce 7680 bytes (more than 4096, less than 8192 - the 512 bytes dnsdist is going to add)
104 paddingSize
= announcedSize
- len(wire
)
105 wire
= wire
+ (b
'A' * (paddingSize
- 1))
106 self
._toResponderQueue
.put(expectedResponse
, True, 2.0)
108 sizeBytes
= struct
.pack("!H", announcedSize
)
109 conn
.send(sizeBytes
[:1])
111 conn
.send(sizeBytes
[1:])
112 # send announcedSize bytes minus 1 so we get a second read
116 conn
.send(b
'A' * 1024)
118 (receivedQuery
, receivedResponse
) = self
.recvTCPResponseOverConnection(conn
, True)
121 self
.assertTrue(receivedQuery
)
122 self
.assertTrue(receivedResponse
)
123 receivedQuery
.id = query
.id
124 self
.assertEquals(query
, receivedQuery
)
125 self
.assertEquals(receivedResponse
, expectedResponse
)
127 def testTCPShortWrite(self
):
129 TCP: Short write to client
131 name
= 'short-write.tcp-short.tests.powerdns.com.'
132 query
= dns
.message
.make_query(name
, 'AXFR', 'IN')
134 # we prepare a large AXFR answer
135 # SOA + 200 dns messages of one huge TXT RRset each + SOA
137 soa
= dns
.rrset
.from_text(name
,
141 'ns.' + name
+ ' hostmaster.' + name
+ ' 1 3600 3600 3600 60')
143 soaResponse
= dns
.message
.make_response(query
)
144 soaResponse
.use_edns(edns
=False)
145 soaResponse
.answer
.append(soa
)
146 responses
.append(soaResponse
)
148 response
= dns
.message
.make_response(query
)
149 response
.use_edns(edns
=False)
153 content
= content
+ ', '
154 content
= content
+ (str(i
)*50)
156 rrset
= dns
.rrset
.from_text(name
,
161 response
.answer
.append(rrset
)
164 responses
.append(response
)
166 responses
.append(soaResponse
)
168 conn
= self
.openTCPConnection()
170 for response
in responses
:
171 self
._toResponderQueue
.put(response
, True, 2.0)
173 self
.sendTCPQueryOverConnection(conn
, query
)
175 # we sleep for one second, making sure that dnsdist
176 # will fill its TCP window and buffers, which will result
177 # in some short writes
180 # we then read the messages
181 receivedResponses
= []
183 datalen
= conn
.recv(2)
187 (datalen
,) = struct
.unpack("!H", datalen
)
190 got
= conn
.recv(remaining
)
193 if len(data
) == datalen
:
195 remaining
= remaining
- len(got
)
198 got
= conn
.recv(remaining
)
200 if data
and len(data
) == datalen
:
201 receivedResponse
= dns
.message
.from_wire(data
)
202 receivedResponses
.append(receivedResponse
)
205 if not self
._fromResponderQueue
.empty():
206 receivedQuery
= self
._fromResponderQueue
.get(True, 2.0)
210 # and check that everything is good
211 self
.assertTrue(receivedQuery
)
212 receivedQuery
.id = query
.id
213 self
.assertEquals(query
, receivedQuery
)
214 self
.assertEquals(receivedResponses
, responses
)
216 def testTCPTLSShortWrite(self
):
218 TCP/TLS: Short write to client
220 # same as testTCPShortWrite but over TLS this time
221 name
= 'short-write-tls.tcp-short.tests.powerdns.com.'
222 query
= dns
.message
.make_query(name
, 'AXFR', 'IN')
224 soa
= dns
.rrset
.from_text(name
,
228 'ns.' + name
+ ' hostmaster.' + name
+ ' 1 3600 3600 3600 60')
230 soaResponse
= dns
.message
.make_response(query
)
231 soaResponse
.use_edns(edns
=False)
232 soaResponse
.answer
.append(soa
)
233 responses
.append(soaResponse
)
235 response
= dns
.message
.make_response(query
)
236 response
.use_edns(edns
=False)
240 content
= content
+ ', '
241 content
= content
+ (str(i
)*50)
243 rrset
= dns
.rrset
.from_text(name
,
248 response
.answer
.append(rrset
)
251 responses
.append(response
)
253 responses
.append(soaResponse
)
255 conn
= self
.openTLSConnection(self
._tlsServerPort
, self
._serverName
, self
._caCert
)
257 for response
in responses
:
258 self
._toResponderQueue
.put(response
, True, 2.0)
260 self
.sendTCPQueryOverConnection(conn
, query
)
264 receivedResponses
= []
266 datalen
= conn
.recv(2)
270 (datalen
,) = struct
.unpack("!H", datalen
)
273 got
= conn
.recv(remaining
)
276 if len(data
) == datalen
:
278 remaining
= remaining
- len(got
)
281 got
= conn
.recv(remaining
)
283 if data
and len(data
) == datalen
:
284 receivedResponse
= dns
.message
.from_wire(data
)
285 receivedResponses
.append(receivedResponse
)
288 if not self
._fromResponderQueue
.empty():
289 receivedQuery
= self
._fromResponderQueue
.get(True, 2.0)
293 self
.assertTrue(receivedQuery
)
294 receivedQuery
.id = query
.id
295 self
.assertEquals(query
, receivedQuery
)
296 self
.assertEquals(len(receivedResponses
), len(responses
))
297 self
.assertEquals(receivedResponses
, responses
)