diff options
Diffstat (limited to 'src/stream/test_stream_local_halfclose.c')
-rw-r--r-- | src/stream/test_stream_local_halfclose.c | 677 |
1 files changed, 539 insertions, 138 deletions
diff --git a/src/stream/test_stream_local_halfclose.c b/src/stream/test_stream_local_halfclose.c index 61e531ae8..a9d794800 100644 --- a/src/stream/test_stream_local_halfclose.c +++ b/src/stream/test_stream_local_halfclose.c | |||
@@ -19,22 +19,28 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * @file stream/test_stream_local_halfclose.c | 22 | * @file stream/test_stream_local.c |
23 | * @brief Stream API testing between local peers with half closed connections | 23 | * @brief Testcases for Stream API halfclosed connections |
24 | * @author Sree Harsha Totakura | 24 | * @author Sree Harsha Totakura |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <string.h> | 27 | #include <string.h> |
28 | #include <sys/socket.h> /* For SHUT_RD, SHUT_WR */ | ||
29 | 28 | ||
30 | #include "platform.h" | 29 | #include "platform.h" |
31 | #include "gnunet_util_lib.h" | 30 | #include "gnunet_util_lib.h" |
32 | #include "gnunet_mesh_service.h" | 31 | #include "gnunet_mesh_service.h" |
33 | #include "gnunet_stream_lib.h" | 32 | #include "gnunet_stream_lib.h" |
33 | #include "gnunet_testing_lib.h" | ||
34 | #include "gnunet_scheduler_lib.h" | ||
34 | 35 | ||
35 | #define VERBOSE 1 | 36 | #define VERBOSE 1 |
36 | 37 | ||
37 | /** | 38 | /** |
39 | * Number of peers | ||
40 | */ | ||
41 | #define NUM_PEERS 2 | ||
42 | |||
43 | /** | ||
38 | * Structure for holding peer's sockets and IO Handles | 44 | * Structure for holding peer's sockets and IO Handles |
39 | */ | 45 | */ |
40 | struct PeerData | 46 | struct PeerData |
@@ -45,9 +51,24 @@ struct PeerData | |||
45 | struct GNUNET_STREAM_Socket *socket; | 51 | struct GNUNET_STREAM_Socket *socket; |
46 | 52 | ||
47 | /** | 53 | /** |
48 | * Peer's io handle | 54 | * Peer's io write handle |
55 | */ | ||
56 | struct GNUNET_STREAM_IOWriteHandle *io_write_handle; | ||
57 | |||
58 | /** | ||
59 | * Peer's io read handle | ||
60 | */ | ||
61 | struct GNUNET_STREAM_IOReadHandle *io_read_handle; | ||
62 | |||
63 | /** | ||
64 | * Peer's shutdown handle | ||
65 | */ | ||
66 | struct GNUNET_STREAM_ShutdownHandle *shutdown_handle; | ||
67 | |||
68 | /** | ||
69 | * Our Peer id | ||
49 | */ | 70 | */ |
50 | struct GNUNET_STREAM_IOHandle *io_handle; | 71 | struct GNUNET_PeerIdentity our_id; |
51 | 72 | ||
52 | /** | 73 | /** |
53 | * Bytes the peer has written | 74 | * Bytes the peer has written |
@@ -58,41 +79,300 @@ struct PeerData | |||
58 | * Byte the peer has read | 79 | * Byte the peer has read |
59 | */ | 80 | */ |
60 | unsigned int bytes_read; | 81 | unsigned int bytes_read; |
82 | |||
83 | /** | ||
84 | * GNUNET_YES if the peer has successfully completed the current test | ||
85 | */ | ||
86 | unsigned int test_ok; | ||
87 | |||
88 | /** | ||
89 | * The shutdown operation that has to be used by the stream_shutdown_task | ||
90 | */ | ||
91 | int shutdown_operation; | ||
61 | }; | 92 | }; |
62 | 93 | ||
63 | static struct GNUNET_OS_Process *arm_pid; | 94 | /** |
95 | * The current peer group | ||
96 | */ | ||
97 | static struct GNUNET_TESTING_PeerGroup *pg; | ||
98 | |||
99 | /** | ||
100 | * Peer 1 daemon | ||
101 | */ | ||
102 | static struct GNUNET_TESTING_Daemon *d1; | ||
103 | |||
104 | /** | ||
105 | * Peer 2 daemon | ||
106 | */ | ||
107 | static struct GNUNET_TESTING_Daemon *d2; | ||
108 | |||
109 | |||
110 | /** | ||
111 | * Peer1 writes first and then calls for SHUT_WR | ||
112 | * Peer2 reads first and then calls for SHUT_RD | ||
113 | * Attempt to write again by Peer1 should be rejected | ||
114 | * Attempt to read again by Peer2 should be rejected | ||
115 | * Peer1 then reads from Peer2 which writes | ||
116 | */ | ||
64 | static struct PeerData peer1; | 117 | static struct PeerData peer1; |
65 | static struct PeerData peer2; | 118 | static struct PeerData peer2; |
66 | static struct GNUNET_STREAM_ListenSocket *peer2_listen_socket; | 119 | static struct GNUNET_STREAM_ListenSocket *peer2_listen_socket; |
120 | static struct GNUNET_CONFIGURATION_Handle *config; | ||
67 | 121 | ||
68 | static GNUNET_SCHEDULER_TaskIdentifier abort_task; | 122 | static GNUNET_SCHEDULER_TaskIdentifier abort_task; |
69 | static GNUNET_SCHEDULER_TaskIdentifier test_task; | ||
70 | static GNUNET_SCHEDULER_TaskIdentifier read_task; | 123 | static GNUNET_SCHEDULER_TaskIdentifier read_task; |
71 | 124 | ||
72 | static char *data = "ABCD"; | 125 | static char *data = "ABCD"; |
73 | static int result; | 126 | static int result; |
74 | 127 | ||
75 | /** | 128 | /** |
76 | * Shutdown nicely | 129 | * Enumeration for various tests that are to be passed in the same order as |
130 | * below | ||
131 | */ | ||
132 | enum Test | ||
133 | { | ||
134 | /** | ||
135 | * Peer1 writing; Peer2 reading | ||
136 | */ | ||
137 | PEER1_WRITE, | ||
138 | |||
139 | /** | ||
140 | * Peer1 write shutdown; Peer2 should get an error when it tries to read; | ||
141 | */ | ||
142 | PEER1_WRITE_SHUTDOWN, | ||
143 | |||
144 | /** | ||
145 | * Peer1 reads; Peer2 writes (connection is halfclosed) | ||
146 | */ | ||
147 | PEER1_HALFCLOSE_READ, | ||
148 | |||
149 | /** | ||
150 | * Peer1 attempts to write; Should fail with stream already shutdown error | ||
151 | */ | ||
152 | PEER1_HALFCLOSE_WRITE_FAIL, | ||
153 | |||
154 | /** | ||
155 | * Peer1 read shutdown; Peer2 should get stream shutdown error during write | ||
156 | */ | ||
157 | PEER1_READ_SHUTDOWN, | ||
158 | |||
159 | /** | ||
160 | * All tests successfully finished | ||
161 | */ | ||
162 | SUCCESS | ||
163 | }; | ||
164 | |||
165 | /** | ||
166 | * Current running test | ||
167 | */ | ||
168 | enum Test current_test; | ||
169 | |||
170 | /** | ||
171 | * Input processor | ||
172 | * | ||
173 | * @param cls the closure from GNUNET_STREAM_write/read | ||
174 | * @param status the status of the stream at the time this function is called | ||
175 | * @param data traffic from the other side | ||
176 | * @param size the number of bytes available in data read | ||
177 | * @return number of bytes of processed from 'data' (any data remaining should be | ||
178 | * given to the next time the read processor is called). | ||
179 | */ | ||
180 | static size_t | ||
181 | input_processor (void *cls, | ||
182 | enum GNUNET_STREAM_Status status, | ||
183 | const void *input_data, | ||
184 | size_t size); | ||
185 | |||
186 | |||
187 | /** | ||
188 | * The transition function; responsible for the transitions among tests | ||
189 | */ | ||
190 | static void | ||
191 | transition(); | ||
192 | |||
193 | |||
194 | /** | ||
195 | * Task for calling STREAM_read | ||
196 | * | ||
197 | * @param cls the peer data entity | ||
198 | * @param tc the task context | ||
199 | */ | ||
200 | static void | ||
201 | stream_read_task (void *cls, | ||
202 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
203 | { | ||
204 | struct PeerData *peer = cls; | ||
205 | |||
206 | peer->io_read_handle = GNUNET_STREAM_read (peer->socket, | ||
207 | GNUNET_TIME_relative_multiply | ||
208 | (GNUNET_TIME_UNIT_SECONDS, 5), | ||
209 | &input_processor, | ||
210 | cls); | ||
211 | switch (current_test) | ||
212 | { | ||
213 | case PEER1_WRITE_SHUTDOWN: | ||
214 | GNUNET_assert (&peer2 == peer); | ||
215 | GNUNET_assert (NULL == peer->io_read_handle); | ||
216 | transition (); /* to PEER1_HALFCLOSE_READ */ | ||
217 | break; | ||
218 | default: | ||
219 | GNUNET_assert (NULL != peer->io_read_handle); | ||
220 | } | ||
221 | } | ||
222 | |||
223 | |||
224 | /** | ||
225 | * The write completion function; called upon writing some data to stream or | ||
226 | * upon error | ||
227 | * | ||
228 | * @param cls the closure from GNUNET_STREAM_write/read | ||
229 | * @param status the status of the stream at the time this function is called | ||
230 | * @param size the number of bytes read or written | ||
231 | */ | ||
232 | static void | ||
233 | write_completion (void *cls, | ||
234 | enum GNUNET_STREAM_Status status, | ||
235 | size_t size); | ||
236 | |||
237 | |||
238 | /** | ||
239 | * Task for calling STREAM_write | ||
240 | * | ||
241 | * @param cls the peer data entity | ||
242 | * @param tc the task context | ||
77 | */ | 243 | */ |
78 | static void | 244 | static void |
79 | do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 245 | stream_write_task (void *cls, |
246 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
80 | { | 247 | { |
81 | GNUNET_STREAM_close (peer1.socket); | 248 | struct PeerData *peer = cls; |
82 | GNUNET_STREAM_close (peer2.socket); | 249 | |
250 | peer->io_write_handle = | ||
251 | GNUNET_STREAM_write (peer->socket, | ||
252 | (void *) data, | ||
253 | strlen(data) - peer->bytes_wrote, | ||
254 | GNUNET_TIME_relative_multiply | ||
255 | (GNUNET_TIME_UNIT_SECONDS, 5), | ||
256 | &write_completion, | ||
257 | peer); | ||
258 | switch (current_test) | ||
259 | { | ||
260 | case PEER1_HALFCLOSE_WRITE_FAIL: | ||
261 | GNUNET_assert (&peer1 == peer); | ||
262 | GNUNET_assert (NULL == peer->io_write_handle); | ||
263 | transition(); /* To PEER1_READ_SHUTDOWN */ | ||
264 | break; | ||
265 | case PEER1_READ_SHUTDOWN: | ||
266 | GNUNET_assert (&peer2 == peer); | ||
267 | GNUNET_assert (NULL == peer->io_write_handle); | ||
268 | transition (); /* To SUCCESS */ | ||
269 | break; | ||
270 | default: | ||
271 | GNUNET_assert (NULL != peer->io_write_handle); | ||
272 | } | ||
273 | } | ||
274 | |||
275 | |||
276 | /** | ||
277 | * Check whether peers successfully shut down. | ||
278 | */ | ||
279 | static void | ||
280 | peergroup_shutdown_callback (void *cls, const char *emsg) | ||
281 | { | ||
282 | if (emsg != NULL) | ||
283 | { | ||
284 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
285 | "Shutdown of peers failed!\n"); | ||
286 | } | ||
287 | else | ||
288 | { | ||
289 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
290 | "All peers successfully shut down!\n"); | ||
291 | } | ||
292 | GNUNET_CONFIGURATION_destroy (config); | ||
293 | } | ||
294 | |||
295 | |||
296 | /** | ||
297 | * Close sockets and stop testing deamons nicely | ||
298 | */ | ||
299 | static void | ||
300 | do_close (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
301 | { | ||
302 | if (NULL != peer1.socket) | ||
303 | GNUNET_STREAM_close (peer1.socket); | ||
304 | if (NULL != peer2.socket) | ||
305 | GNUNET_STREAM_close (peer2.socket); | ||
306 | if (NULL != peer2_listen_socket) | ||
307 | GNUNET_STREAM_listen_close (peer2_listen_socket); | ||
308 | |||
83 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: shutdown\n"); | 309 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: shutdown\n"); |
84 | if (0 != abort_task) | 310 | if (0 != abort_task) |
85 | { | 311 | { |
86 | GNUNET_SCHEDULER_cancel (abort_task); | 312 | GNUNET_SCHEDULER_cancel (abort_task); |
87 | } | 313 | } |
88 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: arm\n"); | 314 | |
89 | if (0 != GNUNET_OS_process_kill (arm_pid, SIGTERM)) | ||
90 | { | ||
91 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); | ||
92 | } | ||
93 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Wait\n"); | 315 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Wait\n"); |
94 | GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (arm_pid)); | 316 | |
95 | GNUNET_OS_process_close (arm_pid); | 317 | GNUNET_TESTING_daemons_stop (pg, |
318 | GNUNET_TIME_relative_multiply | ||
319 | (GNUNET_TIME_UNIT_SECONDS, 5), | ||
320 | &peergroup_shutdown_callback, | ||
321 | NULL); | ||
322 | } | ||
323 | |||
324 | |||
325 | /** | ||
326 | * Completion callback for shutdown | ||
327 | * | ||
328 | * @param cls the closure from GNUNET_STREAM_shutdown call | ||
329 | * @param operation the operation that was shutdown (SHUT_RD, SHUT_WR, | ||
330 | * SHUT_RDWR) | ||
331 | */ | ||
332 | void | ||
333 | shutdown_completion (void *cls, | ||
334 | int operation) | ||
335 | { | ||
336 | switch (current_test) | ||
337 | { | ||
338 | case PEER1_WRITE: | ||
339 | GNUNET_assert (0); | ||
340 | case PEER1_WRITE_SHUTDOWN: | ||
341 | peer1.test_ok = GNUNET_YES; | ||
342 | /* Peer2 should read with error */ | ||
343 | peer2.bytes_read = 0; | ||
344 | GNUNET_SCHEDULER_add_now (&stream_read_task, &peer2); | ||
345 | break; | ||
346 | case PEER1_READ_SHUTDOWN: | ||
347 | peer1.test_ok = GNUNET_YES; | ||
348 | peer2.bytes_wrote = 0; | ||
349 | GNUNET_SCHEDULER_add_now (&stream_write_task, &peer2); | ||
350 | break; | ||
351 | case PEER1_HALFCLOSE_READ: | ||
352 | case PEER1_HALFCLOSE_WRITE_FAIL: | ||
353 | case SUCCESS: | ||
354 | GNUNET_assert (0); /* We shouldn't reach here */ | ||
355 | } | ||
356 | } | ||
357 | |||
358 | |||
359 | /** | ||
360 | * Task for calling STREAM_shutdown | ||
361 | * | ||
362 | * @param cls the peer entity | ||
363 | * @param tc the TaskContext | ||
364 | */ | ||
365 | static void | ||
366 | stream_shutdown_task (void *cls, | ||
367 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
368 | { | ||
369 | struct PeerData *peer = cls; | ||
370 | |||
371 | peer->shutdown_handle = GNUNET_STREAM_shutdown (peer->socket, | ||
372 | peer->shutdown_operation, | ||
373 | &shutdown_completion, | ||
374 | peer); | ||
375 | GNUNET_assert (NULL != peer->shutdown_handle); | ||
96 | } | 376 | } |
97 | 377 | ||
98 | 378 | ||
@@ -103,21 +383,72 @@ static void | |||
103 | do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 383 | do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
104 | { | 384 | { |
105 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: ABORT\n"); | 385 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: ABORT\n"); |
106 | if (0 != test_task) | ||
107 | { | ||
108 | GNUNET_SCHEDULER_cancel (test_task); | ||
109 | } | ||
110 | if (0 != read_task) | 386 | if (0 != read_task) |
111 | { | 387 | { |
112 | GNUNET_SCHEDULER_cancel (read_task); | 388 | GNUNET_SCHEDULER_cancel (read_task); |
113 | } | 389 | } |
114 | result = GNUNET_SYSERR; | 390 | result = GNUNET_SYSERR; |
115 | abort_task = 0; | 391 | abort_task = 0; |
116 | do_shutdown (cls, tc); | 392 | do_close (cls, tc); |
117 | } | 393 | } |
118 | 394 | ||
119 | 395 | ||
120 | /** | 396 | /** |
397 | * The transition function; responsible for the transitions among tests | ||
398 | */ | ||
399 | static void | ||
400 | transition() | ||
401 | { | ||
402 | if ((GNUNET_YES == peer1.test_ok) && (GNUNET_YES == peer2.test_ok)) | ||
403 | { | ||
404 | peer1.test_ok = GNUNET_NO; | ||
405 | peer2.test_ok = GNUNET_NO; | ||
406 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
407 | "TEST %d SUCCESSFULL\n", current_test); | ||
408 | switch (current_test) | ||
409 | { | ||
410 | case PEER1_WRITE: | ||
411 | current_test = PEER1_WRITE_SHUTDOWN; | ||
412 | /* Peer1 should shutdown writing */ | ||
413 | peer1.shutdown_operation = SHUT_WR; | ||
414 | GNUNET_SCHEDULER_add_now (&stream_shutdown_task, &peer1); | ||
415 | break; | ||
416 | case PEER1_WRITE_SHUTDOWN: | ||
417 | current_test = PEER1_HALFCLOSE_READ; | ||
418 | /* Peer2 should be able to write successfully */ | ||
419 | peer2.bytes_wrote = 0; | ||
420 | GNUNET_SCHEDULER_add_now (&stream_write_task, &peer2); | ||
421 | |||
422 | /* Peer1 should be able to read successfully */ | ||
423 | peer1.bytes_read = 0; | ||
424 | GNUNET_SCHEDULER_add_now (&stream_read_task, &peer1); | ||
425 | break; | ||
426 | case PEER1_HALFCLOSE_READ: | ||
427 | current_test = PEER1_HALFCLOSE_WRITE_FAIL; | ||
428 | peer1.bytes_wrote = 0; | ||
429 | peer2.bytes_read = 0; | ||
430 | peer2.test_ok = GNUNET_YES; | ||
431 | GNUNET_SCHEDULER_add_now (&stream_write_task, &peer1); | ||
432 | break; | ||
433 | case PEER1_HALFCLOSE_WRITE_FAIL: | ||
434 | current_test = PEER1_READ_SHUTDOWN; | ||
435 | peer1.shutdown_operation = SHUT_RD; | ||
436 | GNUNET_SCHEDULER_add_now (&stream_shutdown_task, &peer1); | ||
437 | break; | ||
438 | case PEER1_READ_SHUTDOWN: | ||
439 | current_test = SUCCESS; | ||
440 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
441 | "All tests successful\n"); | ||
442 | GNUNET_SCHEDULER_add_now (&do_close, NULL); | ||
443 | break; | ||
444 | case SUCCESS: | ||
445 | GNUNET_assert (0); /* We shouldn't reach here */ | ||
446 | |||
447 | } | ||
448 | } | ||
449 | } | ||
450 | |||
451 | /** | ||
121 | * The write completion function; called upon writing some data to stream or | 452 | * The write completion function; called upon writing some data to stream or |
122 | * upon error | 453 | * upon error |
123 | * | 454 | * |
@@ -130,37 +461,54 @@ write_completion (void *cls, | |||
130 | enum GNUNET_STREAM_Status status, | 461 | enum GNUNET_STREAM_Status status, |
131 | size_t size) | 462 | size_t size) |
132 | { | 463 | { |
133 | struct PeerData *peer; | 464 | struct PeerData *peer = cls; |
134 | |||
135 | peer = (struct PeerData *) cls; | ||
136 | GNUNET_assert (GNUNET_STREAM_OK == status); | ||
137 | GNUNET_assert (size < strlen (data)); | ||
138 | peer->bytes_wrote += size; | ||
139 | 465 | ||
140 | if (peer->bytes_wrote < strlen(data)) /* Have more data to send */ | 466 | switch (current_test) |
141 | { | ||
142 | peer->io_handle = GNUNET_STREAM_write (peer->socket, | ||
143 | (void *) data, | ||
144 | strlen(data) - peer->bytes_wrote, | ||
145 | GNUNET_TIME_relative_multiply | ||
146 | (GNUNET_TIME_UNIT_SECONDS, 5), | ||
147 | &write_completion, | ||
148 | cls); | ||
149 | GNUNET_assert (NULL != peer->io_handle); | ||
150 | } | ||
151 | else | ||
152 | { | 467 | { |
153 | if (&peer1 == peer) /* Peer1 has finished writing; should read now */ | 468 | case PEER1_WRITE: |
154 | { | 469 | case PEER1_HALFCLOSE_READ: |
155 | peer->io_handle = GNUNET_STREAM_read ((struct GNUNET_STREAM_Socket *) | 470 | |
156 | peer->socket, | 471 | GNUNET_assert (GNUNET_STREAM_OK == status); |
157 | GNUNET_TIME_relative_multiply | 472 | GNUNET_assert (size <= strlen (data)); |
158 | (GNUNET_TIME_UNIT_SECONDS, 5), | 473 | peer->bytes_wrote += size; |
159 | &input_processor, | 474 | |
160 | cls); | 475 | if (peer->bytes_wrote < strlen(data)) /* Have more data to send */ |
161 | GNUNET_assert (NULL!=peer->io_handle); | 476 | { |
162 | } | 477 | GNUNET_SCHEDULER_add_now (&stream_write_task, peer); |
163 | } | 478 | } |
479 | else | ||
480 | { | ||
481 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
482 | "Writing completed\n"); | ||
483 | |||
484 | if (&peer1 == peer) | ||
485 | { | ||
486 | peer1.test_ok = GNUNET_YES; | ||
487 | transition (); /* to PEER1_WRITE_SHUTDOWN */ | ||
488 | } | ||
489 | else /* This will happen during PEER1_HALFCLOSE_READ */ | ||
490 | { | ||
491 | peer2.test_ok = GNUNET_YES; | ||
492 | transition (); /* to PEER1_HALFCLOSE_WRITE_FAIL */ | ||
493 | } | ||
494 | } | ||
495 | break; | ||
496 | case PEER1_HALFCLOSE_WRITE_FAIL: | ||
497 | GNUNET_assert (peer == &peer1); | ||
498 | GNUNET_assert (GNUNET_STREAM_SHUTDOWN == status); | ||
499 | GNUNET_assert (0 == size); | ||
500 | peer1.test_ok = GNUNET_YES; | ||
501 | break; | ||
502 | case PEER1_READ_SHUTDOWN: | ||
503 | GNUNET_assert (peer == &peer2); | ||
504 | GNUNET_assert (GNUNET_STREAM_SHUTDOWN == status); | ||
505 | GNUNET_assert (0 == size); | ||
506 | peer2.test_ok = GNUNET_YES; | ||
507 | break; | ||
508 | case PEER1_WRITE_SHUTDOWN: | ||
509 | case SUCCESS: | ||
510 | GNUNET_assert (0); /* We shouldn't reach here */ | ||
511 | } | ||
164 | } | 512 | } |
165 | 513 | ||
166 | 514 | ||
@@ -176,18 +524,18 @@ stream_open_cb (void *cls, | |||
176 | { | 524 | { |
177 | struct PeerData *peer; | 525 | struct PeerData *peer; |
178 | 526 | ||
527 | GNUNET_assert (socket == peer1.socket); | ||
528 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
529 | "%s: Stream established from peer1\n", | ||
530 | GNUNET_i2s (&peer1.our_id)); | ||
179 | peer = (struct PeerData *) cls; | 531 | peer = (struct PeerData *) cls; |
180 | peer->bytes_wrote = 0; | 532 | peer->bytes_wrote = 0; |
181 | GNUNET_assert (socket == peer1.socket); | 533 | GNUNET_assert (socket == peer1.socket); |
182 | GNUNET_assert (socket == peer->socket); | 534 | GNUNET_assert (socket == peer->socket); |
183 | peer->io_handle = GNUNET_STREAM_write (peer->socket, /* socket */ | 535 | peer1.test_ok = GNUNET_NO; |
184 | (void *) data, /* data */ | 536 | peer2.test_ok = GNUNET_NO; |
185 | strlen(data), | 537 | current_test = PEER1_WRITE; |
186 | GNUNET_TIME_relative_multiply | 538 | GNUNET_SCHEDULER_add_now (&stream_write_task, peer); |
187 | (GNUNET_TIME_UNIT_SECONDS, 5), | ||
188 | &write_completion, | ||
189 | cls); | ||
190 | GNUNET_assert (NULL != peer->io_handle); | ||
191 | } | 539 | } |
192 | 540 | ||
193 | 541 | ||
@@ -211,34 +559,54 @@ input_processor (void *cls, | |||
211 | 559 | ||
212 | peer = (struct PeerData *) cls; | 560 | peer = (struct PeerData *) cls; |
213 | 561 | ||
214 | /* Peer1 is expected to read when it first finishes writing */ | 562 | switch (current_test) |
215 | if (peer == &peer1) | ||
216 | { | 563 | { |
217 | /* since p2 closed write */ | 564 | case PEER1_WRITE: |
218 | GNUNET_assert (GNUNET_STREAM_SHUTDOWN == status); | 565 | case PEER1_HALFCLOSE_READ: |
219 | /* Test passed; shutdown now */ | 566 | if (GNUNET_STREAM_TIMEOUT == status) |
220 | GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); | 567 | { |
221 | return 0; | 568 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
222 | } | 569 | "Read operation timedout - reading again!\n"); |
570 | GNUNET_assert (0 == size); | ||
571 | GNUNET_SCHEDULER_add_now (&stream_read_task, peer); | ||
572 | return 0; | ||
573 | } | ||
223 | 574 | ||
224 | GNUNET_assert (GNUNET_STERAM_OK == status); | 575 | GNUNET_assert (GNUNET_STREAM_OK == status); |
225 | GNUNET_assert (size < strlen (data)); | 576 | GNUNET_assert (size <= strlen (data)); |
226 | GNUNET_assert (strncmp ((const char *) data + peer->bytes_read, | 577 | GNUNET_assert (0 == strncmp ((const char *) data + peer->bytes_read, |
227 | (const char *) input_data, | 578 | (const char *) input_data, |
228 | size)); | 579 | size)); |
229 | peer->bytes_read += size; | 580 | peer->bytes_read += size; |
230 | 581 | ||
231 | if (peer->bytes_read < strlen (data)) | 582 | if (peer->bytes_read < strlen (data)) |
232 | { | 583 | { |
233 | peer->io_handle = GNUNET_STREAM_read ((struct GNUNET_STREAM_Socket *) | 584 | GNUNET_SCHEDULER_add_now (&stream_read_task, peer); |
234 | peer->socket, | 585 | } |
235 | GNUNET_TIME_relative_multiply | 586 | else |
236 | (GNUNET_TIME_UNIT_SECONDS, 5), | 587 | { |
237 | &input_processor, | 588 | if (&peer2 == peer) /* Peer2 has completed reading; should write */ |
238 | cls); | 589 | { |
239 | GNUNET_assert (NULL != peer->io_handle); | 590 | peer2.test_ok = GNUNET_YES; |
591 | transition (); /* Transition to PEER1_WRITE_SHUTDOWN */ | ||
592 | } | ||
593 | else /* Peer1 has completed reading. End of tests */ | ||
594 | { | ||
595 | peer1.test_ok = GNUNET_YES; | ||
596 | transition (); /* to PEER1_HALFCLOSE_WRITE_FAIL */ | ||
597 | } | ||
598 | } | ||
599 | break; | ||
600 | case PEER1_WRITE_SHUTDOWN: | ||
601 | GNUNET_assert (GNUNET_STREAM_SHUTDOWN == status); | ||
602 | peer2.test_ok = GNUNET_YES; | ||
603 | break; | ||
604 | case PEER1_HALFCLOSE_WRITE_FAIL: | ||
605 | case PEER1_READ_SHUTDOWN: | ||
606 | case SUCCESS: | ||
607 | GNUNET_assert (0); /* We shouldn't reach here */ | ||
240 | } | 608 | } |
241 | 609 | ||
242 | return size; | 610 | return size; |
243 | } | 611 | } |
244 | 612 | ||
@@ -253,16 +621,7 @@ stream_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
253 | read_task = GNUNET_SCHEDULER_NO_TASK; | 621 | read_task = GNUNET_SCHEDULER_NO_TASK; |
254 | GNUNET_assert (NULL != cls); | 622 | GNUNET_assert (NULL != cls); |
255 | peer2.bytes_read = 0; | 623 | peer2.bytes_read = 0; |
256 | GNUNET_STREAM_listen_close (peer2_listen_socket); /* Close listen socket */ | 624 | GNUNET_SCHEDULER_add_now (&stream_read_task, &peer2); |
257 | /* Close the stream for writing */ | ||
258 | GNUNET_STREAM_shutdown ((struct GNUNET_STREAM_Socket *) cls, | ||
259 | SHUT_WR); | ||
260 | peer2.io_handle = GNUNET_STREAM_read ((struct GNUNET_STREAM_Socket *) cls, | ||
261 | GNUNET_TIME_relative_multiply | ||
262 | (GNUNET_TIME_UNIT_SECONDS, 5), | ||
263 | &input_processor, | ||
264 | (void *) &peer2); | ||
265 | GNUNET_assert (NULL != peer2.io_handle); | ||
266 | } | 625 | } |
267 | 626 | ||
268 | 627 | ||
@@ -278,40 +637,80 @@ stream_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
278 | */ | 637 | */ |
279 | static int | 638 | static int |
280 | stream_listen_cb (void *cls, | 639 | stream_listen_cb (void *cls, |
281 | struct GNUNET_STREAM_Socket *socket, | 640 | struct GNUNET_STREAM_Socket *socket, |
282 | const struct GNUNET_PeerIdentity *initiator) | 641 | const struct GNUNET_PeerIdentity *initiator) |
283 | { | 642 | { |
284 | GNUNET_assert (NULL != socket); | 643 | GNUNET_assert (NULL != socket); |
285 | GNUNET_assert (NULL == initiator); /* Local peer=NULL? */ | 644 | GNUNET_assert (NULL != initiator); |
286 | GNUNET_assert (socket != peer1.socket); | 645 | GNUNET_assert (socket != peer1.socket); |
287 | 646 | ||
647 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
648 | "%s: Peer connected: %s\n", | ||
649 | GNUNET_i2s (&peer2.our_id), | ||
650 | GNUNET_i2s(initiator)); | ||
651 | |||
288 | peer2.socket = socket; | 652 | peer2.socket = socket; |
653 | /* FIXME: reading should be done right now instead of a scheduled call */ | ||
289 | read_task = GNUNET_SCHEDULER_add_now (&stream_read, (void *) socket); | 654 | read_task = GNUNET_SCHEDULER_add_now (&stream_read, (void *) socket); |
290 | return GNUNET_OK; | 655 | return GNUNET_OK; |
291 | } | 656 | } |
292 | 657 | ||
293 | 658 | ||
294 | /** | 659 | /** |
295 | * Testing function | 660 | * Callback to be called when testing peer group is ready |
661 | * | ||
662 | * @param cls NULL | ||
663 | * @param emsg NULL on success | ||
296 | */ | 664 | */ |
297 | static void | 665 | void |
298 | test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 666 | peergroup_ready (void *cls, const char *emsg) |
299 | { | 667 | { |
300 | test_task = GNUNET_SCHEDULER_NO_TASK; | 668 | if (NULL != emsg) |
669 | { | ||
670 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
671 | "Starting peer group failed: %s\n", emsg); | ||
672 | return; | ||
673 | } | ||
674 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
675 | "Peer group is now ready\n"); | ||
676 | |||
677 | GNUNET_assert (2 == GNUNET_TESTING_daemons_running (pg)); | ||
678 | |||
679 | d1 = GNUNET_TESTING_daemon_get (pg, 0); | ||
680 | GNUNET_assert (NULL != d1); | ||
681 | |||
682 | d2 = GNUNET_TESTING_daemon_get (pg, 1); | ||
683 | GNUNET_assert (NULL != d2); | ||
684 | |||
685 | GNUNET_TESTING_get_peer_identity (d1->cfg, | ||
686 | &peer1.our_id); | ||
687 | GNUNET_TESTING_get_peer_identity (d2->cfg, | ||
688 | &peer2.our_id); | ||
689 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
690 | "%s : %s\n", | ||
691 | GNUNET_i2s (&peer1.our_id), | ||
692 | GNUNET_i2s (&d1->id)); | ||
693 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
694 | "%s : %s\n", | ||
695 | GNUNET_i2s (&peer2.our_id), | ||
696 | GNUNET_i2s (&d2->id)); | ||
697 | |||
698 | peer2_listen_socket = GNUNET_STREAM_listen (d2->cfg, | ||
699 | 10, /* App port */ | ||
700 | &stream_listen_cb, | ||
701 | NULL); | ||
702 | GNUNET_assert (NULL != peer2_listen_socket); | ||
301 | 703 | ||
302 | /* Connect to stream library */ | 704 | /* Connect to stream library */ |
303 | peer1.socket = GNUNET_STREAM_open (NULL, /* Null for local peer? */ | 705 | peer1.socket = GNUNET_STREAM_open (d1->cfg, |
706 | &d2->id, /* Null for local peer? */ | ||
304 | 10, /* App port */ | 707 | 10, /* App port */ |
305 | &stream_open_cb, | 708 | &stream_open_cb, |
306 | (void *) &peer1); | 709 | &peer1); |
307 | GNUNET_assert (NULL != peer1.socket); | 710 | GNUNET_assert (NULL != peer1.socket); |
308 | peer2_listen_socket = GNUNET_STREAM_listen (10 /* App port */ | ||
309 | &stream_listen_cb, | ||
310 | NULL); | ||
311 | GNUNET_assert (NULL != peer2_listen_socket); | ||
312 | |||
313 | } | 711 | } |
314 | 712 | ||
713 | |||
315 | /** | 714 | /** |
316 | * Initialize framework and start test | 715 | * Initialize framework and start test |
317 | */ | 716 | */ |
@@ -319,28 +718,33 @@ static void | |||
319 | run (void *cls, char *const *args, const char *cfgfile, | 718 | run (void *cls, char *const *args, const char *cfgfile, |
320 | const struct GNUNET_CONFIGURATION_Handle *cfg) | 719 | const struct GNUNET_CONFIGURATION_Handle *cfg) |
321 | { | 720 | { |
322 | GNUNET_log_setup ("test_stream_local", | 721 | struct GNUNET_TESTING_Host *hosts; /* FIXME: free hosts (DLL) */ |
323 | #if VERBOSE | 722 | |
324 | "DEBUG", | 723 | /* GNUNET_log_setup ("test_stream_local", */ |
325 | #else | 724 | /* "DEBUG", */ |
326 | "WARNING", | 725 | /* NULL); */ |
327 | #endif | ||
328 | NULL); | ||
329 | arm_pid = | ||
330 | GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-service-arm", | ||
331 | "gnunet-service-arm", | ||
332 | #if VERBOSE_ARM | ||
333 | "-L", "DEBUG", | ||
334 | #endif | ||
335 | "-c", "test_stream_local.conf", NULL); | ||
336 | |||
337 | abort_task = | ||
338 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
339 | (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort, | ||
340 | NULL); | ||
341 | |||
342 | test_task = GNUNET_SCHEDULER_add_now (&test, (void *) cfg); | ||
343 | 726 | ||
727 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
728 | "Starting test\n"); | ||
729 | /* Duplicate the configuration */ | ||
730 | config = GNUNET_CONFIGURATION_dup (cfg); | ||
731 | |||
732 | hosts = GNUNET_TESTING_hosts_load (config); | ||
733 | |||
734 | pg = GNUNET_TESTING_peergroup_start (config, | ||
735 | 2, | ||
736 | GNUNET_TIME_relative_multiply | ||
737 | (GNUNET_TIME_UNIT_SECONDS, 3), | ||
738 | NULL, | ||
739 | &peergroup_ready, | ||
740 | NULL, | ||
741 | hosts); | ||
742 | GNUNET_assert (NULL != pg); | ||
743 | |||
744 | abort_task = | ||
745 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
746 | (GNUNET_TIME_UNIT_SECONDS, 40), &do_abort, | ||
747 | NULL); | ||
344 | } | 748 | } |
345 | 749 | ||
346 | /** | 750 | /** |
@@ -350,18 +754,15 @@ int main (int argc, char **argv) | |||
350 | { | 754 | { |
351 | int ret; | 755 | int ret; |
352 | 756 | ||
353 | char *const argv2[] = { "test-stream-local", | 757 | char *argv2[] = { "test-stream-local", |
354 | "-c", "test_stream.conf", | 758 | "-L", "DEBUG", |
355 | #if VERBOSE | 759 | "-c", "test_stream_local.conf", |
356 | "-L", "DEBUG", | 760 | NULL}; |
357 | #endif | ||
358 | NULL | ||
359 | }; | ||
360 | 761 | ||
361 | struct GNUNET_GETOPT_CommandLineOption options[] = { | 762 | struct GNUNET_GETOPT_CommandLineOption options[] = { |
362 | GNUNET_GETOPT_OPTION_END | 763 | GNUNET_GETOPT_OPTION_END |
363 | }; | 764 | }; |
364 | 765 | ||
365 | ret = | 766 | ret = |
366 | GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, | 767 | GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, |
367 | "test-stream-local", "nohelp", options, &run, NULL); | 768 | "test-stream-local", "nohelp", options, &run, NULL); |
@@ -377,6 +778,6 @@ int main (int argc, char **argv) | |||
377 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test failed\n"); | 778 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test failed\n"); |
378 | return 1; | 779 | return 1; |
379 | } | 780 | } |
380 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test ok\n"); | 781 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "test ok\n"); |
381 | return 0; | 782 | return 0; |
382 | } | 783 | } |