/work/testing/support/doubles/fake_network_tcp_test.cc
Line | Count | Source |
1 | | #include <gtest/gtest.h> |
2 | | |
3 | | #include "fake_sockets.hh" |
4 | | #include "network_universe.hh" |
5 | | |
6 | | namespace tox::test { |
7 | | namespace { |
8 | | |
9 | | class FakeNetworkTcpTest : public ::testing::Test { |
10 | | protected: |
11 | | NetworkUniverse universe; |
12 | | |
13 | | IP make_ip(uint8_t a, uint8_t b, uint8_t c, uint8_t d) |
14 | 18 | { |
15 | 18 | IP ip; |
16 | 18 | ip_init(&ip, false); |
17 | 18 | ip.ip.v4.uint8[0] = a; |
18 | 18 | ip.ip.v4.uint8[1] = b; |
19 | 18 | ip.ip.v4.uint8[2] = c; |
20 | 18 | ip.ip.v4.uint8[3] = d; |
21 | 18 | return ip; |
22 | 18 | } |
23 | | }; |
24 | | |
25 | | TEST_F(FakeNetworkTcpTest, MultipleConnectionsToSamePort) |
26 | 1 | { |
27 | 1 | universe.set_verbose(true); |
28 | 1 | IP server_ip = make_ip(10, 0, 0, 1); |
29 | 1 | uint16_t server_port = 12345; |
30 | | |
31 | 1 | FakeTcpSocket server(universe); |
32 | 1 | server.set_ip(server_ip); |
33 | 1 | IP_Port server_addr{server_ip, net_htons(server_port)}; |
34 | 1 | ASSERT_EQ(server.bind(&server_addr), 0); |
35 | 1 | ASSERT_EQ(server.listen(5), 0); |
36 | | |
37 | | // Client 1 |
38 | 1 | IP client1_ip = make_ip(10, 0, 0, 2); |
39 | 1 | FakeTcpSocket client1(universe); |
40 | 1 | client1.set_ip(client1_ip); |
41 | 1 | client1.connect(&server_addr); |
42 | | |
43 | | // Client 2 (same IP as client 1, different port) |
44 | 1 | FakeTcpSocket client2(universe); |
45 | 1 | client2.set_ip(client1_ip); |
46 | 1 | client2.connect(&server_addr); |
47 | | |
48 | | // Handshake for both |
49 | | // 1. SYNs |
50 | 1 | universe.process_events(0); |
51 | 1 | universe.process_events(0); |
52 | | |
53 | | // 2. SYN-ACKs |
54 | 1 | universe.process_events(0); |
55 | 1 | universe.process_events(0); |
56 | | |
57 | | // 3. ACKs |
58 | 1 | universe.process_events(0); |
59 | 1 | universe.process_events(0); |
60 | | |
61 | 1 | auto accepted1 = server.accept(nullptr); |
62 | 1 | auto accepted2 = server.accept(nullptr); |
63 | | |
64 | 1 | ASSERT_NE(accepted1, nullptr); |
65 | 1 | ASSERT_NE(accepted2, nullptr); |
66 | | |
67 | 1 | EXPECT_EQ( |
68 | 1 | static_cast<FakeTcpSocket *>(accepted1.get())->state(), FakeTcpSocket::ESTABLISHED); |
69 | 1 | EXPECT_EQ( |
70 | 1 | static_cast<FakeTcpSocket *>(accepted2.get())->state(), FakeTcpSocket::ESTABLISHED); |
71 | | |
72 | | // Verify data isolation |
73 | 1 | const char *msg1 = "Message 1"; |
74 | 1 | const char *msg2 = "Message 2"; |
75 | | |
76 | 1 | client1.send(reinterpret_cast<const uint8_t *>(msg1), strlen(msg1)); |
77 | 1 | client2.send(reinterpret_cast<const uint8_t *>(msg2), strlen(msg2)); |
78 | | |
79 | 1 | universe.process_events(0); |
80 | 1 | universe.process_events(0); |
81 | | |
82 | 1 | uint8_t buf[100]; |
83 | 1 | int len1 = accepted1->recv(buf, sizeof(buf)); |
84 | 1 | EXPECT_EQ(len1, strlen(msg1)); |
85 | 1 | int len2 = accepted2->recv(buf, sizeof(buf)); |
86 | 1 | EXPECT_EQ(len2, strlen(msg2)); |
87 | 1 | } |
88 | | |
89 | | TEST_F(FakeNetworkTcpTest, DuplicateSynCreatesDuplicateConnections) |
90 | 1 | { |
91 | 1 | universe.set_verbose(true); |
92 | 1 | IP server_ip = make_ip(10, 0, 0, 1); |
93 | 1 | uint16_t server_port = 12345; |
94 | | |
95 | 1 | FakeTcpSocket server(universe); |
96 | 1 | server.set_ip(server_ip); |
97 | 1 | IP_Port server_addr{server_ip, net_htons(server_port)}; |
98 | 1 | server.bind(&server_addr); |
99 | 1 | server.listen(5); |
100 | | |
101 | 1 | IP client_ip = make_ip(10, 0, 0, 2); |
102 | 1 | IP_Port client_addr{client_ip, net_htons(33445)}; |
103 | | |
104 | 1 | Packet p{}; |
105 | 1 | p.from = client_addr; |
106 | 1 | p.to = server_addr; |
107 | 1 | p.is_tcp = true; |
108 | 1 | p.tcp_flags = 0x02; // SYN |
109 | 1 | p.seq = 100; |
110 | | |
111 | 1 | universe.send_packet(p); |
112 | 1 | universe.send_packet(p); // Duplicate SYN |
113 | | |
114 | 1 | universe.process_events(0); |
115 | 1 | universe.process_events(0); |
116 | | |
117 | | // Now send ACK from client |
118 | 1 | Packet ack{}; |
119 | 1 | ack.from = client_addr; |
120 | 1 | ack.to = server_addr; |
121 | 1 | ack.is_tcp = true; |
122 | 1 | ack.tcp_flags = 0x10; // ACK |
123 | 1 | ack.ack = 101; |
124 | | |
125 | 1 | universe.send_packet(ack); |
126 | 1 | universe.process_events(0); |
127 | | |
128 | 1 | auto accepted1 = server.accept(nullptr); |
129 | 1 | auto accepted2 = server.accept(nullptr); |
130 | | |
131 | 1 | ASSERT_NE(accepted1, nullptr); |
132 | 1 | EXPECT_EQ(accepted2, nullptr); // This should pass now |
133 | 1 | } |
134 | | |
135 | | TEST_F(FakeNetworkTcpTest, PeerCloseClearsConnection) |
136 | 1 | { |
137 | 1 | universe.set_verbose(true); |
138 | 1 | IP server_ip = make_ip(10, 0, 0, 1); |
139 | 1 | uint16_t server_port = 12345; |
140 | | |
141 | 1 | FakeTcpSocket server(universe); |
142 | 1 | server.set_ip(server_ip); |
143 | 1 | IP_Port server_addr{server_ip, net_htons(server_port)}; |
144 | 1 | server.bind(&server_addr); |
145 | 1 | server.listen(5); |
146 | | |
147 | 1 | IP client_ip = make_ip(10, 0, 0, 2); |
148 | 1 | FakeTcpSocket client(universe); |
149 | 1 | client.set_ip(client_ip); |
150 | 1 | client.connect(&server_addr); |
151 | | |
152 | | // Handshake |
153 | 1 | universe.process_events(0); // SYN |
154 | 1 | universe.process_events(0); // SYN-ACK |
155 | 1 | universe.process_events(0); // ACK |
156 | | |
157 | 1 | auto accepted = server.accept(nullptr); |
158 | 1 | ASSERT_NE(accepted, nullptr); |
159 | 1 | EXPECT_EQ( |
160 | 1 | static_cast<FakeTcpSocket *>(accepted.get())->state(), FakeTcpSocket::ESTABLISHED); |
161 | | |
162 | | // Client closes |
163 | 1 | client.close(); |
164 | 1 | universe.process_events(0); // Deliver RST/FIN |
165 | | |
166 | | // Server should no longer be ESTABLISHED |
167 | 1 | EXPECT_EQ(static_cast<FakeTcpSocket *>(accepted.get())->state(), FakeTcpSocket::CLOSED); |
168 | | |
169 | | // Now if client reconnects with same port |
170 | 1 | FakeTcpSocket client2(universe); |
171 | 1 | client2.set_ip(client_ip); |
172 | 1 | client2.connect(&server_addr); |
173 | 1 | universe.process_events(0); // Deliver SYN |
174 | | |
175 | | // Node 2 port 20002 should have: 1 LISTEN, 0 ESTABLISHED (old one gone), 1 SYN_RECEIVED |
176 | | // (new one) Total targets should be 2. |
177 | 1 | } |
178 | | |
179 | | TEST_F(FakeNetworkTcpTest, DataNotProcessedByMultipleSockets) |
180 | 1 | { |
181 | 1 | universe.set_verbose(true); |
182 | 1 | IP server_ip = make_ip(10, 0, 0, 1); |
183 | 1 | uint16_t server_port = 12345; |
184 | | |
185 | 1 | FakeTcpSocket server(universe); |
186 | 1 | server.set_ip(server_ip); |
187 | 1 | IP_Port server_addr{server_ip, net_htons(server_port)}; |
188 | 1 | server.bind(&server_addr); |
189 | 1 | server.listen(5); |
190 | | |
191 | 1 | IP client_ip = make_ip(10, 0, 0, 2); |
192 | 1 | IP_Port client_addr{client_ip, net_htons(33445)}; |
193 | | |
194 | | // Manually create two "established" sockets on the same port for the same peer |
195 | | // This simulates a bug where duplicate connections were allowed. |
196 | 1 | auto sock1 = FakeTcpSocket::create_connected(universe, client_addr, server_port); |
197 | 1 | sock1->set_ip(server_ip); |
198 | 1 | auto sock2 = FakeTcpSocket::create_connected(universe, client_addr, server_port); |
199 | 1 | sock2->set_ip(server_ip); |
200 | | |
201 | 1 | universe.bind_tcp(server_ip, server_port, sock1.get()); |
202 | 1 | universe.bind_tcp(server_ip, server_port, sock2.get()); |
203 | | |
204 | | // Send data from client to server |
205 | 1 | Packet p{}; |
206 | 1 | p.from = client_addr; |
207 | 1 | p.to = server_addr; |
208 | 1 | p.is_tcp = true; |
209 | 1 | p.tcp_flags = 0x10; // ACK (Data) |
210 | 1 | const char *data = "Unique"; |
211 | 1 | p.data.assign(data, data + strlen(data)); |
212 | | |
213 | 1 | universe.send_packet(p); |
214 | 1 | universe.process_events(0); |
215 | | |
216 | | // Only ONE of them should have received it, or at least they shouldn't BOTH have it |
217 | | // in a way that suggests duplicate delivery. |
218 | 1 | EXPECT_TRUE((sock1->recv_buffer_size() == strlen(data)) |
219 | 1 | ^ (sock2->recv_buffer_size() == strlen(data))); |
220 | 1 | } |
221 | | |
222 | | TEST_F(FakeNetworkTcpTest, ConnectionCollision) |
223 | 1 | { |
224 | 1 | universe.set_verbose(true); |
225 | 1 | IP server_ip = make_ip(10, 0, 0, 1); |
226 | 1 | uint16_t server_port = 12345; |
227 | | |
228 | 1 | FakeTcpSocket server(universe); |
229 | 1 | server.set_ip(server_ip); |
230 | 1 | IP_Port server_addr{server_ip, net_htons(server_port)}; |
231 | 1 | server.bind(&server_addr); |
232 | 1 | server.listen(5); |
233 | | |
234 | 1 | IP client_ip = make_ip(10, 0, 0, 2); |
235 | | |
236 | 1 | FakeTcpSocket client1(universe); |
237 | 1 | client1.set_ip(client_ip); |
238 | | // Bind to specific port to force collision later |
239 | 1 | IP_Port client_bind_addr{client_ip, net_htons(33445)}; |
240 | 1 | client1.bind(&client_bind_addr); |
241 | 1 | client1.connect(&server_addr); |
242 | | |
243 | | // Handshake 1 |
244 | 1 | universe.process_events(0); // SYN |
245 | 1 | universe.process_events(0); // SYN-ACK |
246 | 1 | universe.process_events(0); // ACK |
247 | | |
248 | 1 | auto accepted1 = server.accept(nullptr); |
249 | 1 | ASSERT_NE(accepted1, nullptr); |
250 | 1 | EXPECT_EQ( |
251 | 1 | static_cast<FakeTcpSocket *>(accepted1.get())->state(), FakeTcpSocket::ESTABLISHED); |
252 | | |
253 | | // Now client 1 "reconnects" (e.g. after a crash or timeout, but using same port) |
254 | 1 | FakeTcpSocket client2(universe); |
255 | 1 | client2.set_ip(client_ip); |
256 | 1 | client2.bind(&client_bind_addr); // Forced collision |
257 | 1 | client2.connect(&server_addr); |
258 | | |
259 | | // Deliver new SYN |
260 | 1 | universe.process_events(0); |
261 | | |
262 | | // server_addr port 12345 now has: |
263 | | // 1. LISTEN socket |
264 | | // 2. accepted1 (ESTABLISHED with 10.0.0.2:33445) |
265 | | |
266 | | // In our simplified simulation, the ESTABLISHED socket now handles the SYN by returning |
267 | | // true (ignoring it). So no new connection is created. |
268 | 1 | auto accepted2 = server.accept(nullptr); |
269 | 1 | EXPECT_EQ(accepted2, nullptr); |
270 | | |
271 | 1 | const char *msg1 = "Data 1"; |
272 | 1 | client1.send(reinterpret_cast<const uint8_t *>(msg1), strlen(msg1)); |
273 | 1 | universe.process_events(0); |
274 | | |
275 | | // Data should still go to accepted1 |
276 | 1 | EXPECT_EQ(accepted1->recv_buffer_size(), strlen(msg1)); |
277 | 1 | } |
278 | | |
279 | | TEST_F(FakeNetworkTcpTest, LoopbackConnection) |
280 | 1 | { |
281 | 1 | universe.set_verbose(true); |
282 | 1 | IP node_ip = make_ip(10, 0, 0, 1); |
283 | 1 | uint16_t port = 12345; |
284 | | |
285 | 1 | FakeTcpSocket server(universe); |
286 | 1 | server.set_ip(node_ip); |
287 | 1 | IP_Port listen_addr{node_ip, net_htons(port)}; |
288 | 1 | server.bind(&listen_addr); |
289 | 1 | server.listen(5); |
290 | | |
291 | 1 | FakeTcpSocket client(universe); |
292 | 1 | client.set_ip(node_ip); |
293 | 1 | IP loopback_ip; |
294 | 1 | ip_init(&loopback_ip, false); |
295 | 1 | loopback_ip.ip.v4.uint32 = net_htonl(0x7F000001); |
296 | 1 | IP_Port server_loopback_addr{loopback_ip, net_htons(port)}; |
297 | | |
298 | 1 | client.connect(&server_loopback_addr); |
299 | | |
300 | | // SYN (Client -> 127.0.0.1:12345) |
301 | 1 | universe.process_events(0); |
302 | | |
303 | | // SYN-ACK (Server -> Client) |
304 | 1 | universe.process_events(0); |
305 | | |
306 | | // ACK (Client -> Server) |
307 | 1 | universe.process_events(0); |
308 | | |
309 | 1 | EXPECT_EQ(client.state(), FakeTcpSocket::ESTABLISHED); |
310 | 1 | auto accepted = server.accept(nullptr); |
311 | 1 | ASSERT_NE(accepted, nullptr); |
312 | 1 | EXPECT_EQ( |
313 | 1 | static_cast<FakeTcpSocket *>(accepted.get())->state(), FakeTcpSocket::ESTABLISHED); |
314 | | |
315 | | // Data Transfer |
316 | 1 | const char *msg = "Loopback"; |
317 | 1 | client.send(reinterpret_cast<const uint8_t *>(msg), strlen(msg)); |
318 | 1 | universe.process_events(0); |
319 | | |
320 | 1 | uint8_t buf[100]; |
321 | 1 | int len = accepted->recv(buf, sizeof(buf)); |
322 | 1 | ASSERT_EQ(len, strlen(msg)); |
323 | 1 | EXPECT_EQ(std::string(reinterpret_cast<char *>(buf), len), msg); |
324 | 1 | } |
325 | | |
326 | | TEST_F(FakeNetworkTcpTest, SimultaneousConnect) |
327 | 1 | { |
328 | 1 | universe.set_verbose(true); |
329 | 1 | IP ipA = make_ip(10, 0, 0, 1); |
330 | 1 | IP ipB = make_ip(10, 0, 0, 2); |
331 | 1 | uint16_t portA = 10001; |
332 | 1 | uint16_t portB = 10002; |
333 | | |
334 | 1 | FakeTcpSocket sockA(universe); |
335 | 1 | sockA.set_ip(ipA); |
336 | 1 | IP_Port addrA{ipA, net_htons(portA)}; |
337 | 1 | sockA.bind(&addrA); |
338 | 1 | sockA.listen(5); |
339 | | |
340 | 1 | FakeTcpSocket sockB(universe); |
341 | 1 | sockB.set_ip(ipB); |
342 | 1 | IP_Port addrB{ipB, net_htons(portB)}; |
343 | 1 | sockB.bind(&addrB); |
344 | 1 | sockB.listen(5); |
345 | | |
346 | | // A connects to B |
347 | 1 | sockA.connect(&addrB); |
348 | | // B connects to A |
349 | 1 | sockB.connect(&addrA); |
350 | | |
351 | | // This is "simultaneous open" in TCP but here they are also LISTENing. |
352 | | // Toxcore uses this pattern sometimes. |
353 | | |
354 | 1 | universe.process_events(0); // SYN from A to B |
355 | 1 | universe.process_events(0); // SYN from B to A |
356 | | |
357 | 1 | universe.process_events(0); // SYN-ACK from B to A (for A's SYN) |
358 | 1 | universe.process_events(0); // SYN-ACK from A to B (for B's SYN) |
359 | | |
360 | 1 | universe.process_events(0); // ACK from A to B |
361 | 1 | universe.process_events(0); // ACK from B to A |
362 | | |
363 | 1 | EXPECT_EQ(sockA.state(), FakeTcpSocket::ESTABLISHED); |
364 | 1 | EXPECT_EQ(sockB.state(), FakeTcpSocket::ESTABLISHED); |
365 | 1 | } |
366 | | |
367 | | TEST_F(FakeNetworkTcpTest, DataInHandshakeAck) |
368 | 1 | { |
369 | 1 | universe.set_verbose(true); |
370 | 1 | IP server_ip = make_ip(10, 0, 0, 1); |
371 | 1 | uint16_t server_port = 12345; |
372 | | |
373 | 1 | FakeTcpSocket server(universe); |
374 | 1 | server.set_ip(server_ip); |
375 | 1 | IP_Port server_addr{server_ip, net_htons(server_port)}; |
376 | 1 | server.bind(&server_addr); |
377 | 1 | server.listen(5); |
378 | | |
379 | 1 | IP client_ip = make_ip(10, 0, 0, 2); |
380 | 1 | IP_Port client_addr{client_ip, net_htons(33445)}; |
381 | | |
382 | | // 1. SYN |
383 | 1 | Packet syn{}; |
384 | 1 | syn.from = client_addr; |
385 | 1 | syn.to = server_addr; |
386 | 1 | syn.is_tcp = true; |
387 | 1 | syn.tcp_flags = 0x02; |
388 | 1 | universe.send_packet(syn); |
389 | 1 | universe.process_events(0); |
390 | | |
391 | | // 2. SYN-ACK (Server -> Client) |
392 | 1 | universe.process_events(0); |
393 | | |
394 | | // 3. ACK + Data (Client -> Server) |
395 | 1 | Packet ack{}; |
396 | 1 | ack.from = client_addr; |
397 | 1 | ack.to = server_addr; |
398 | 1 | ack.is_tcp = true; |
399 | 1 | ack.tcp_flags = 0x10; |
400 | 1 | const char *data = "HandshakeData"; |
401 | 1 | ack.data.assign(data, data + strlen(data)); |
402 | 1 | universe.send_packet(ack); |
403 | 1 | universe.process_events(0); |
404 | | |
405 | 1 | auto accepted = server.accept(nullptr); |
406 | 1 | ASSERT_NE(accepted, nullptr); |
407 | 1 | EXPECT_EQ(accepted->recv_buffer_size(), strlen(data)); |
408 | 1 | } |
409 | | |
410 | | TEST_F(FakeNetworkTcpTest, DataInSynAck) |
411 | 1 | { |
412 | 1 | universe.set_verbose(true); |
413 | 1 | IP ipA = make_ip(10, 0, 0, 1); |
414 | 1 | IP ipB = make_ip(10, 0, 0, 2); |
415 | 1 | uint16_t portA = 10001; |
416 | 1 | uint16_t portB = 10002; |
417 | | |
418 | 1 | FakeTcpSocket sockA(universe); |
419 | 1 | sockA.set_ip(ipA); |
420 | 1 | IP_Port addrA{ipA, net_htons(portA)}; |
421 | 1 | sockA.bind(&addrA); |
422 | 1 | sockA.listen(5); |
423 | | |
424 | 1 | FakeTcpSocket sockB(universe); |
425 | 1 | sockB.set_ip(ipB); |
426 | 1 | IP_Port addrB{ipB, net_htons(portB)}; |
427 | 1 | sockB.bind(&addrB); |
428 | 1 | sockB.listen(5); |
429 | | |
430 | | // A connects to B |
431 | 1 | sockA.connect(&addrB); |
432 | | // B connects to A |
433 | 1 | sockB.connect(&addrA); |
434 | | |
435 | 1 | universe.process_events(0); // SYN from A to B |
436 | 1 | universe.process_events(0); // SYN from B to A |
437 | | |
438 | | // Now A receives B's SYN and transitions to SYN_RECEIVED, sending SYN-ACK. |
439 | | // We want to simulate B sending SYN-ACK WITH DATA to A. |
440 | 1 | Packet syn_ack_data{}; |
441 | 1 | syn_ack_data.from = addrB; |
442 | 1 | syn_ack_data.to = addrA; |
443 | 1 | syn_ack_data.is_tcp = true; |
444 | 1 | syn_ack_data.tcp_flags = 0x12; // SYN | ACK |
445 | 1 | const char *msg = "SynAckData"; |
446 | 1 | syn_ack_data.data.assign(msg, msg + strlen(msg)); |
447 | | |
448 | 1 | universe.send_packet(syn_ack_data); |
449 | 1 | universe.process_events(0); // A receives SYN-ACK with data |
450 | | |
451 | 1 | EXPECT_EQ(sockA.state(), FakeTcpSocket::ESTABLISHED); |
452 | 1 | EXPECT_EQ(sockA.recv_buffer_size(), strlen(msg)); |
453 | 1 | } |
454 | | |
455 | | TEST_F(FakeNetworkTcpTest, LoopbackWithNodeIPMixed) |
456 | 1 | { |
457 | 1 | universe.set_verbose(true); |
458 | 1 | IP node_ip = make_ip(10, 0, 0, 1); |
459 | 1 | uint16_t port = 12345; |
460 | | |
461 | 1 | FakeTcpSocket server(universe); |
462 | 1 | server.set_ip(node_ip); |
463 | 1 | IP_Port listen_addr{node_ip, net_htons(port)}; |
464 | 1 | server.bind(&listen_addr); |
465 | 1 | server.listen(5); |
466 | | |
467 | 1 | FakeTcpSocket client(universe); |
468 | 1 | client.set_ip(node_ip); |
469 | 1 | IP loopback_ip; |
470 | 1 | ip_init(&loopback_ip, false); |
471 | 1 | loopback_ip.ip.v4.uint32 = net_htonl(0x7F000001); |
472 | 1 | IP_Port server_loopback_addr{loopback_ip, net_htons(port)}; |
473 | | |
474 | | // Client connects to 127.0.0.1 |
475 | 1 | client.connect(&server_loopback_addr); |
476 | | |
477 | 1 | universe.process_events(0); // SYN (Client -> 127.0.0.1) |
478 | 1 | universe.process_events(0); // SYN-ACK (Server -> Client) |
479 | 1 | universe.process_events(0); // ACK (Client -> Server) |
480 | | |
481 | 1 | EXPECT_EQ(client.state(), FakeTcpSocket::ESTABLISHED); |
482 | 1 | auto accepted = server.accept(nullptr); |
483 | 1 | ASSERT_NE(accepted, nullptr); |
484 | | |
485 | | // Now manually simulate a packet coming from the server's EXTERNAL IP to the client. |
486 | | // This happens because the server socket is bound to node_ip, so its packets might |
487 | | // be delivered as coming from node_ip even if the client connected to 127.0.0.1. |
488 | 1 | Packet p{}; |
489 | 1 | p.from = listen_addr; // node_ip:port |
490 | 1 | p.to.ip = node_ip; |
491 | 1 | p.to.port = net_htons(client.local_port()); |
492 | 1 | p.is_tcp = true; |
493 | 1 | p.tcp_flags = 0x10; // ACK |
494 | 1 | const char *msg = "MixedIP"; |
495 | 1 | p.data.assign(msg, msg + strlen(msg)); |
496 | | |
497 | 1 | universe.send_packet(p); |
498 | 1 | universe.process_events(0); |
499 | | |
500 | 1 | EXPECT_EQ(client.recv_buffer_size(), strlen(msg)); |
501 | 1 | } |
502 | | |
503 | | } |
504 | | } |