blob: c6a5c5f0289199428b41b58577fd425da23f0c06 [file] [log] [blame]
Benny Prijono4766ffe2005-11-01 17:56:59 +00001/* $Id$
Benny Prijonodd859a62005-11-01 16:42:51 +00002 */
3#include "test.h"
4
5
6/**
7 * \page page_pjlib_ioqueue_udp_test Test: I/O Queue (UDP)
8 *
9 * This file provides implementation to test the
10 * functionality of the I/O queue when UDP socket is used.
11 *
12 *
13 * This file is <b>pjlib-test/ioq_udp.c</b>
14 *
15 * \include pjlib-test/ioq_udp.c
16 */
17
18
19#if INCLUDE_UDP_IOQUEUE_TEST
20
21#include <pjlib.h>
22
23#include <pj/compat/socket.h>
24
25#define THIS_FILE "test_udp"
26#define PORT 51233
27#define LOOP 100
28#define BUF_MIN_SIZE 32
29#define BUF_MAX_SIZE 2048
30#define SOCK_INACTIVE_MIN (1)
31#define SOCK_INACTIVE_MAX (PJ_IOQUEUE_MAX_HANDLES - 2)
32#define POOL_SIZE (2*BUF_MAX_SIZE + SOCK_INACTIVE_MAX*128 + 2048)
33
34#undef TRACE_
35#define TRACE_(msg) PJ_LOG(3,(THIS_FILE,"....." msg))
36
Benny Prijonoa9946d52005-11-06 09:37:47 +000037static pj_ssize_t callback_read_size,
38 callback_write_size,
39 callback_accept_status,
40 callback_connect_status;
41static pj_ioqueue_key_t *callback_read_key,
42 *callback_write_key,
43 *callback_accept_key,
44 *callback_connect_key;
Benny Prijonoe91bf772005-11-08 11:31:55 +000045static pj_ioqueue_op_key_t *callback_read_op,
46 *callback_write_op,
47 *callback_accept_op;
Benny Prijonodd859a62005-11-01 16:42:51 +000048
Benny Prijonoe91bf772005-11-08 11:31:55 +000049static void on_ioqueue_read(pj_ioqueue_key_t *key,
50 pj_ioqueue_op_key_t *op_key,
Benny Prijonoa9946d52005-11-06 09:37:47 +000051 pj_ssize_t bytes_read)
Benny Prijonodd859a62005-11-01 16:42:51 +000052{
Benny Prijonoe91bf772005-11-08 11:31:55 +000053 callback_read_key = key;
Benny Prijonoa9946d52005-11-06 09:37:47 +000054 callback_read_op = op_key;
Benny Prijonodd859a62005-11-01 16:42:51 +000055 callback_read_size = bytes_read;
56}
57
Benny Prijonoe91bf772005-11-08 11:31:55 +000058static void on_ioqueue_write(pj_ioqueue_key_t *key,
59 pj_ioqueue_op_key_t *op_key,
Benny Prijonoa9946d52005-11-06 09:37:47 +000060 pj_ssize_t bytes_written)
Benny Prijonodd859a62005-11-01 16:42:51 +000061{
Benny Prijonoe91bf772005-11-08 11:31:55 +000062 callback_write_key = key;
Benny Prijonoa9946d52005-11-06 09:37:47 +000063 callback_write_op = op_key;
Benny Prijonodd859a62005-11-01 16:42:51 +000064 callback_write_size = bytes_written;
65}
66
Benny Prijonoe91bf772005-11-08 11:31:55 +000067static void on_ioqueue_accept(pj_ioqueue_key_t *key,
68 pj_ioqueue_op_key_t *op_key,
Benny Prijonoa9946d52005-11-06 09:37:47 +000069 pj_sock_t sock, int status)
Benny Prijonodd859a62005-11-01 16:42:51 +000070{
71 PJ_UNUSED_ARG(sock);
Benny Prijonoe91bf772005-11-08 11:31:55 +000072 callback_accept_key = key;
Benny Prijonoa9946d52005-11-06 09:37:47 +000073 callback_accept_op = op_key;
Benny Prijonodd859a62005-11-01 16:42:51 +000074 callback_accept_status = status;
75}
76
77static void on_ioqueue_connect(pj_ioqueue_key_t *key, int status)
78{
79 callback_connect_key = key;
80 callback_connect_status = status;
81}
82
83static pj_ioqueue_callback test_cb =
84{
85 &on_ioqueue_read,
86 &on_ioqueue_write,
87 &on_ioqueue_accept,
88 &on_ioqueue_connect,
89};
90
91#ifdef PJ_WIN32
92# define S_ADDR S_un.S_addr
93#else
94# define S_ADDR s_addr
95#endif
96
97/*
Benny Prijonodd859a62005-11-01 16:42:51 +000098 * compliance_test()
99 * To test that the basic IOQueue functionality works. It will just exchange
100 * data between two sockets.
101 */
102static int compliance_test(void)
103{
104 pj_sock_t ssock=-1, csock=-1;
105 pj_sockaddr_in addr;
106 int addrlen;
107 pj_pool_t *pool = NULL;
108 char *send_buf, *recv_buf;
109 pj_ioqueue_t *ioque = NULL;
Benny Prijonoe91bf772005-11-08 11:31:55 +0000110 pj_ioqueue_key_t *skey, *ckey;
Benny Prijonoa9946d52005-11-06 09:37:47 +0000111 pj_ioqueue_op_key_t read_op, write_op;
Benny Prijonodd859a62005-11-01 16:42:51 +0000112 int bufsize = BUF_MIN_SIZE;
113 pj_ssize_t bytes, status = -1;
114 pj_str_t temp;
115 pj_bool_t send_pending, recv_pending;
116 pj_status_t rc;
117
118 pj_set_os_error(PJ_SUCCESS);
119
120 // Create pool.
121 pool = pj_pool_create(mem, NULL, POOL_SIZE, 4000, NULL);
122
123 // Allocate buffers for send and receive.
124 send_buf = (char*)pj_pool_alloc(pool, bufsize);
125 recv_buf = (char*)pj_pool_alloc(pool, bufsize);
126
127 // Allocate sockets for sending and receiving.
128 TRACE_("creating sockets...");
129 rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &ssock);
130 if (rc==PJ_SUCCESS)
131 rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &csock);
132 else
133 csock = PJ_INVALID_SOCKET;
134 if (rc != PJ_SUCCESS) {
135 app_perror("...ERROR in pj_sock_socket()", rc);
136 status=-1; goto on_error;
137 }
138
139 // Bind server socket.
140 TRACE_("bind socket...");
141 memset(&addr, 0, sizeof(addr));
142 addr.sin_family = PJ_AF_INET;
143 addr.sin_port = pj_htons(PORT);
144 if (pj_sock_bind(ssock, &addr, sizeof(addr))) {
145 status=-10; goto on_error;
146 }
147
148 // Create I/O Queue.
149 TRACE_("create ioqueue...");
Benny Prijonoa9946d52005-11-06 09:37:47 +0000150 rc = pj_ioqueue_create(pool, PJ_IOQUEUE_MAX_HANDLES, &ioque);
Benny Prijonodd859a62005-11-01 16:42:51 +0000151 if (rc != PJ_SUCCESS) {
152 status=-20; goto on_error;
153 }
154
155 // Register server and client socket.
156 // We put this after inactivity socket, hopefully this can represent the
157 // worst waiting time.
158 TRACE_("registering first sockets...");
159 rc = pj_ioqueue_register_sock(pool, ioque, ssock, NULL,
160 &test_cb, &skey);
161 if (rc != PJ_SUCCESS) {
162 app_perror("...error(10): ioqueue_register error", rc);
163 status=-25; goto on_error;
164 }
165 TRACE_("registering second sockets...");
166 rc = pj_ioqueue_register_sock( pool, ioque, csock, NULL,
167 &test_cb, &ckey);
168 if (rc != PJ_SUCCESS) {
169 app_perror("...error(11): ioqueue_register error", rc);
170 status=-26; goto on_error;
171 }
172
173 // Set destination address to send the packet.
174 TRACE_("set destination address...");
175 temp = pj_str("127.0.0.1");
176 if ((rc=pj_sockaddr_in_init(&addr, &temp, PORT)) != 0) {
177 app_perror("...error: unable to resolve 127.0.0.1", rc);
178 status=-26; goto on_error;
179 }
180
181 // Randomize send_buf.
182 pj_create_random_string(send_buf, bufsize);
183
184 // Register reading from ioqueue.
185 TRACE_("start recvfrom...");
Benny Prijonoe91bf772005-11-08 11:31:55 +0000186 addrlen = sizeof(addr);
Benny Prijonoa9946d52005-11-06 09:37:47 +0000187 bytes = bufsize;
188 rc = pj_ioqueue_recvfrom(skey, &read_op, recv_buf, &bytes, 0,
189 &addr, &addrlen);
Benny Prijonoe91bf772005-11-08 11:31:55 +0000190 if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
Benny Prijonoa9946d52005-11-06 09:37:47 +0000191 app_perror("...error: pj_ioqueue_recvfrom", rc);
Benny Prijonodd859a62005-11-01 16:42:51 +0000192 status=-28; goto on_error;
Benny Prijonoa9946d52005-11-06 09:37:47 +0000193 } else if (rc == PJ_EPENDING) {
Benny Prijonodd859a62005-11-01 16:42:51 +0000194 recv_pending = 1;
195 PJ_LOG(3, (THIS_FILE,
196 "......ok: recvfrom returned pending"));
197 } else {
198 PJ_LOG(3, (THIS_FILE,
199 "......error: recvfrom returned immediate ok!"));
200 status=-29; goto on_error;
201 }
202
203 // Write must return the number of bytes.
Benny Prijonoe91bf772005-11-08 11:31:55 +0000204 TRACE_("start sendto...");
Benny Prijonoa9946d52005-11-06 09:37:47 +0000205 bytes = bufsize;
206 rc = pj_ioqueue_sendto(ckey, &write_op, send_buf, &bytes, 0, &addr,
207 sizeof(addr));
Benny Prijonoe91bf772005-11-08 11:31:55 +0000208 if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
Benny Prijonoa9946d52005-11-06 09:37:47 +0000209 app_perror("...error: pj_ioqueue_sendto", rc);
Benny Prijonodd859a62005-11-01 16:42:51 +0000210 status=-30; goto on_error;
Benny Prijonoa9946d52005-11-06 09:37:47 +0000211 } else if (rc == PJ_EPENDING) {
Benny Prijonodd859a62005-11-01 16:42:51 +0000212 send_pending = 1;
213 PJ_LOG(3, (THIS_FILE,
214 "......ok: sendto returned pending"));
215 } else {
216 send_pending = 0;
217 PJ_LOG(3, (THIS_FILE,
218 "......ok: sendto returned immediate success"));
219 }
220
221 // reset callback variables.
222 callback_read_size = callback_write_size = 0;
223 callback_accept_status = callback_connect_status = -2;
224 callback_read_key = callback_write_key =
225 callback_accept_key = callback_connect_key = NULL;
Benny Prijonoe91bf772005-11-08 11:31:55 +0000226 callback_read_op = callback_write_op = NULL;
Benny Prijonodd859a62005-11-01 16:42:51 +0000227
228 // Poll if pending.
Benny Prijonoa9946d52005-11-06 09:37:47 +0000229 while (send_pending || recv_pending) {
Benny Prijonodd859a62005-11-01 16:42:51 +0000230 int rc;
231 pj_time_val timeout = { 5, 0 };
232
233 TRACE_("poll...");
234 rc = pj_ioqueue_poll(ioque, &timeout);
235
236 if (rc == 0) {
237 PJ_LOG(1,(THIS_FILE, "...ERROR: timed out..."));
238 status=-45; goto on_error;
239 } else if (rc < 0) {
240 app_perror("...ERROR in ioqueue_poll()", rc);
241 status=-50; goto on_error;
242 }
243
244 if (callback_read_key != NULL) {
245 if (callback_read_size != bufsize) {
246 status=-61; goto on_error;
247 }
Benny Prijonodd859a62005-11-01 16:42:51 +0000248 if (callback_read_key != skey) {
249 status=-65; goto on_error;
Benny Prijonoe91bf772005-11-08 11:31:55 +0000250 }
251 if (callback_read_op != &read_op) {
252 status=-66; goto on_error;
Benny Prijonodd859a62005-11-01 16:42:51 +0000253 }
254
255 if (memcmp(send_buf, recv_buf, bufsize) != 0) {
256 status=-70; goto on_error;
257 }
258
259
260 recv_pending = 0;
261 }
262
263 if (callback_write_key != NULL) {
264 if (callback_write_size != bufsize) {
265 status=-73; goto on_error;
266 }
Benny Prijonodd859a62005-11-01 16:42:51 +0000267 if (callback_write_key != ckey) {
268 status=-75; goto on_error;
Benny Prijonoe91bf772005-11-08 11:31:55 +0000269 }
270 if (callback_write_op != &write_op) {
271 status=-76; goto on_error;
Benny Prijonodd859a62005-11-01 16:42:51 +0000272 }
273
274 send_pending = 0;
275 }
276 }
277
278 // Success
279 status = 0;
280
281on_error:
282 if (status != 0) {
283 char errbuf[128];
284 PJ_LOG(1, (THIS_FILE,
285 "...compliance test error: status=%d, os_err=%d (%s)",
286 status, pj_get_netos_error(),
287 pj_strerror(pj_get_netos_error(), errbuf, sizeof(errbuf))));
288 }
289 if (ssock)
290 pj_sock_close(ssock);
291 if (csock)
292 pj_sock_close(csock);
293 if (ioque != NULL)
294 pj_ioqueue_destroy(ioque);
295 pj_pool_release(pool);
296 return status;
297
298}
299
300/*
301 * Testing with many handles.
302 * This will just test registering PJ_IOQUEUE_MAX_HANDLES count
303 * of sockets to the ioqueue.
304 */
305static int many_handles_test(void)
306{
307 enum { MAX = PJ_IOQUEUE_MAX_HANDLES };
308 pj_pool_t *pool;
309 pj_ioqueue_t *ioqueue;
310 pj_sock_t *sock;
311 pj_ioqueue_key_t **key;
312 pj_status_t rc;
313 int count, i;
314
315 PJ_LOG(3,(THIS_FILE,"...testing with so many handles"));
316
317 pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);
318 if (!pool)
319 return PJ_ENOMEM;
320
321 key = pj_pool_alloc(pool, MAX*sizeof(pj_ioqueue_key_t*));
322 sock = pj_pool_alloc(pool, MAX*sizeof(pj_sock_t));
323
324 /* Create IOQueue */
Benny Prijonoa9946d52005-11-06 09:37:47 +0000325 rc = pj_ioqueue_create(pool, MAX, &ioqueue);
Benny Prijonodd859a62005-11-01 16:42:51 +0000326 if (rc != PJ_SUCCESS || ioqueue == NULL) {
327 app_perror("...error in pj_ioqueue_create", rc);
328 return -10;
329 }
330
331 /* Register as many sockets. */
332 for (count=0; count<MAX; ++count) {
333 sock[count] = PJ_INVALID_SOCKET;
334 rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[count]);
335 if (rc != PJ_SUCCESS || sock[count] == PJ_INVALID_SOCKET) {
336 PJ_LOG(3,(THIS_FILE, "....unable to create %d-th socket, rc=%d",
337 count, rc));
338 break;
339 }
340 key[count] = NULL;
341 rc = pj_ioqueue_register_sock(pool, ioqueue, sock[count],
342 NULL, &test_cb, &key[count]);
343 if (rc != PJ_SUCCESS || key[count] == NULL) {
344 PJ_LOG(3,(THIS_FILE, "....unable to register %d-th socket, rc=%d",
345 count, rc));
346 return -30;
347 }
348 }
349
350 /* Test complete. */
351
352 /* Now deregister and close all handles. */
353
354 for (i=0; i<count; ++i) {
Benny Prijonoa9946d52005-11-06 09:37:47 +0000355 rc = pj_ioqueue_unregister(key[i]);
Benny Prijonodd859a62005-11-01 16:42:51 +0000356 if (rc != PJ_SUCCESS) {
357 app_perror("...error in pj_ioqueue_unregister", rc);
358 }
359 rc = pj_sock_close(sock[i]);
360 if (rc != PJ_SUCCESS) {
361 app_perror("...error in pj_sock_close", rc);
362 }
363 }
364
365 rc = pj_ioqueue_destroy(ioqueue);
366 if (rc != PJ_SUCCESS) {
367 app_perror("...error in pj_ioqueue_destroy", rc);
368 }
369
370 pj_pool_release(pool);
371
372 PJ_LOG(3,(THIS_FILE,"....many_handles_test() ok"));
373
374 return 0;
375}
376
377/*
378 * Multi-operation test.
379 */
380
381/*
382 * Benchmarking IOQueue
383 */
384static int bench_test(int bufsize, int inactive_sock_count)
385{
386 pj_sock_t ssock=-1, csock=-1;
387 pj_sockaddr_in addr;
388 pj_pool_t *pool = NULL;
Benny Prijonoe91bf772005-11-08 11:31:55 +0000389 pj_sock_t *inactive_sock=NULL;
Benny Prijonoa9946d52005-11-06 09:37:47 +0000390 pj_ioqueue_op_key_t *inactive_read_op;
Benny Prijonodd859a62005-11-01 16:42:51 +0000391 char *send_buf, *recv_buf;
392 pj_ioqueue_t *ioque = NULL;
393 pj_ioqueue_key_t *skey, *ckey, *key;
394 pj_timestamp t1, t2, t_elapsed;
395 int rc=0, i;
396 pj_str_t temp;
397 char errbuf[128];
398
399 // Create pool.
400 pool = pj_pool_create(mem, NULL, POOL_SIZE, 4000, NULL);
401
402 // Allocate buffers for send and receive.
403 send_buf = (char*)pj_pool_alloc(pool, bufsize);
404 recv_buf = (char*)pj_pool_alloc(pool, bufsize);
405
406 // Allocate sockets for sending and receiving.
407 rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &ssock);
408 if (rc == PJ_SUCCESS) {
409 rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &csock);
410 } else
411 csock = PJ_INVALID_SOCKET;
412 if (rc != PJ_SUCCESS) {
413 app_perror("...error: pj_sock_socket()", rc);
414 goto on_error;
415 }
416
417 // Bind server socket.
418 memset(&addr, 0, sizeof(addr));
419 addr.sin_family = PJ_AF_INET;
420 addr.sin_port = pj_htons(PORT);
421 if (pj_sock_bind(ssock, &addr, sizeof(addr)))
422 goto on_error;
423
424 pj_assert(inactive_sock_count+2 <= PJ_IOQUEUE_MAX_HANDLES);
425
426 // Create I/O Queue.
Benny Prijonoa9946d52005-11-06 09:37:47 +0000427 rc = pj_ioqueue_create(pool, PJ_IOQUEUE_MAX_HANDLES, &ioque);
Benny Prijonodd859a62005-11-01 16:42:51 +0000428 if (rc != PJ_SUCCESS) {
429 app_perror("...error: pj_ioqueue_create()", rc);
430 goto on_error;
431 }
432
433 // Allocate inactive sockets, and bind them to some arbitrary address.
434 // Then register them to the I/O queue, and start a read operation.
435 inactive_sock = (pj_sock_t*)pj_pool_alloc(pool,
Benny Prijonoe91bf772005-11-08 11:31:55 +0000436 inactive_sock_count*sizeof(pj_sock_t));
437 inactive_read_op = (pj_ioqueue_op_key_t*)pj_pool_alloc(pool,
Benny Prijonoa9946d52005-11-06 09:37:47 +0000438 inactive_sock_count*sizeof(pj_ioqueue_op_key_t));
Benny Prijonodd859a62005-11-01 16:42:51 +0000439 memset(&addr, 0, sizeof(addr));
440 addr.sin_family = PJ_AF_INET;
Benny Prijonoe91bf772005-11-08 11:31:55 +0000441 for (i=0; i<inactive_sock_count; ++i) {
442 pj_ssize_t bytes;
Benny Prijonoa9946d52005-11-06 09:37:47 +0000443
Benny Prijonodd859a62005-11-01 16:42:51 +0000444 rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &inactive_sock[i]);
445 if (rc != PJ_SUCCESS || inactive_sock[i] < 0) {
446 app_perror("...error: pj_sock_socket()", rc);
447 goto on_error;
448 }
449 if ((rc=pj_sock_bind(inactive_sock[i], &addr, sizeof(addr))) != 0) {
450 pj_sock_close(inactive_sock[i]);
451 inactive_sock[i] = PJ_INVALID_SOCKET;
452 app_perror("...error: pj_sock_bind()", rc);
453 goto on_error;
454 }
455 rc = pj_ioqueue_register_sock(pool, ioque, inactive_sock[i],
456 NULL, &test_cb, &key);
457 if (rc != PJ_SUCCESS) {
458 pj_sock_close(inactive_sock[i]);
459 inactive_sock[i] = PJ_INVALID_SOCKET;
460 app_perror("...error(1): pj_ioqueue_register_sock()", rc);
461 PJ_LOG(3,(THIS_FILE, "....i=%d", i));
462 goto on_error;
Benny Prijonoe91bf772005-11-08 11:31:55 +0000463 }
Benny Prijonoa9946d52005-11-06 09:37:47 +0000464 bytes = bufsize;
465 rc = pj_ioqueue_recv(key, &inactive_read_op[i], recv_buf, &bytes, 0);
Benny Prijonodd859a62005-11-01 16:42:51 +0000466 if ( rc < 0 && rc != PJ_EPENDING) {
467 pj_sock_close(inactive_sock[i]);
468 inactive_sock[i] = PJ_INVALID_SOCKET;
469 app_perror("...error: pj_ioqueue_read()", rc);
470 goto on_error;
471 }
472 }
473
474 // Register server and client socket.
475 // We put this after inactivity socket, hopefully this can represent the
476 // worst waiting time.
477 rc = pj_ioqueue_register_sock(pool, ioque, ssock, NULL,
478 &test_cb, &skey);
479 if (rc != PJ_SUCCESS) {
480 app_perror("...error(2): pj_ioqueue_register_sock()", rc);
481 goto on_error;
482 }
483
484 rc = pj_ioqueue_register_sock(pool, ioque, csock, NULL,
485 &test_cb, &ckey);
486 if (rc != PJ_SUCCESS) {
487 app_perror("...error(3): pj_ioqueue_register_sock()", rc);
488 goto on_error;
489 }
490
491 // Set destination address to send the packet.
492 pj_sockaddr_in_init(&addr, pj_cstr(&temp, "127.0.0.1"), PORT);
493
494 // Test loop.
495 t_elapsed.u64 = 0;
496 for (i=0; i<LOOP; ++i) {
Benny Prijonoe91bf772005-11-08 11:31:55 +0000497 pj_ssize_t bytes;
Benny Prijonoa9946d52005-11-06 09:37:47 +0000498 pj_ioqueue_op_key_t read_op, write_op;
Benny Prijonodd859a62005-11-01 16:42:51 +0000499
500 // Randomize send buffer.
501 pj_create_random_string(send_buf, bufsize);
502
Benny Prijonoe91bf772005-11-08 11:31:55 +0000503 // Start reading on the server side.
Benny Prijonoa9946d52005-11-06 09:37:47 +0000504 bytes = bufsize;
505 rc = pj_ioqueue_recv(skey, &read_op, recv_buf, &bytes, 0);
Benny Prijonodd859a62005-11-01 16:42:51 +0000506 if (rc < 0 && rc != PJ_EPENDING) {
507 app_perror("...error: pj_ioqueue_read()", rc);
508 break;
509 }
510
Benny Prijonoe91bf772005-11-08 11:31:55 +0000511 // Starts send on the client side.
Benny Prijonoa9946d52005-11-06 09:37:47 +0000512 bytes = bufsize;
513 rc = pj_ioqueue_sendto(ckey, &write_op, send_buf, &bytes, 0,
514 &addr, sizeof(addr));
515 if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
Benny Prijonodd859a62005-11-01 16:42:51 +0000516 app_perror("...error: pj_ioqueue_write()", bytes);
517 rc = -1;
518 break;
519 }
520
521 // Begin time.
522 pj_get_timestamp(&t1);
523
524 // Poll the queue until we've got completion event in the server side.
525 callback_read_key = NULL;
526 callback_read_size = 0;
527 do {
528 rc = pj_ioqueue_poll(ioque, NULL);
529 } while (rc >= 0 && callback_read_key != skey);
530
531 // End time.
532 pj_get_timestamp(&t2);
533 t_elapsed.u64 += (t2.u64 - t1.u64);
534
535 if (rc < 0)
536 break;
537
538 // Compare recv buffer with send buffer.
539 if (callback_read_size != bufsize ||
540 memcmp(send_buf, recv_buf, bufsize))
541 {
542 rc = -1;
543 break;
544 }
545
546 // Poll until all events are exhausted, before we start the next loop.
547 do {
548 pj_time_val timeout = { 0, 10 };
549 rc = pj_ioqueue_poll(ioque, &timeout);
550 } while (rc>0);
551
552 rc = 0;
553 }
554
555 // Print results
556 if (rc == 0) {
557 pj_timestamp tzero;
558 pj_uint32_t usec_delay;
559
560 tzero.u32.hi = tzero.u32.lo = 0;
561 usec_delay = pj_elapsed_usec( &tzero, &t_elapsed);
562
563 PJ_LOG(3, (THIS_FILE, "...%10d %15d % 9d",
564 bufsize, inactive_sock_count, usec_delay));
565
566 } else {
567 PJ_LOG(2, (THIS_FILE, "...ERROR (buf:%d, fds:%d)",
568 bufsize, inactive_sock_count+2));
569 }
570
571 // Cleaning up.
572 for (i=0; i<inactive_sock_count; ++i)
573 pj_sock_close(inactive_sock[i]);
574 pj_sock_close(ssock);
575 pj_sock_close(csock);
576
577 pj_ioqueue_destroy(ioque);
578 pj_pool_release( pool);
579 return 0;
580
581on_error:
582 PJ_LOG(1,(THIS_FILE, "...ERROR: %s",
583 pj_strerror(pj_get_netos_error(), errbuf, sizeof(errbuf))));
584 if (ssock)
585 pj_sock_close(ssock);
586 if (csock)
587 pj_sock_close(csock);
588 for (i=0; i<inactive_sock_count && inactive_sock &&
589 inactive_sock[i]!=PJ_INVALID_SOCKET; ++i)
Benny Prijonoe91bf772005-11-08 11:31:55 +0000590 {
Benny Prijonodd859a62005-11-01 16:42:51 +0000591 pj_sock_close(inactive_sock[i]);
592 }
593 if (ioque != NULL)
594 pj_ioqueue_destroy(ioque);
595 pj_pool_release( pool);
596 return -1;
597}
598
599int udp_ioqueue_test()
600{
601 int status;
602 int bufsize, sock_count;
603
Benny Prijonoe91bf772005-11-08 11:31:55 +0000604 PJ_LOG(3, (THIS_FILE, "...compliance test (%s)", pj_ioqueue_name()));
Benny Prijonodd859a62005-11-01 16:42:51 +0000605 if ((status=compliance_test()) != 0) {
606 return status;
607 }
608 PJ_LOG(3, (THIS_FILE, "....compliance test ok"));
609
610 if ((status=many_handles_test()) != 0) {
611 return status;
612 }
613
614 PJ_LOG(4, (THIS_FILE, "...benchmarking different buffer size:"));
615 PJ_LOG(4, (THIS_FILE, "... note: buf=bytes sent, fds=# of fds, "
616 "elapsed=in timer ticks"));
617
Benny Prijonoe91bf772005-11-08 11:31:55 +0000618 PJ_LOG(3, (THIS_FILE, "...Benchmarking poll times for %s:", pj_ioqueue_name()));
Benny Prijonodd859a62005-11-01 16:42:51 +0000619 PJ_LOG(3, (THIS_FILE, "...====================================="));
620 PJ_LOG(3, (THIS_FILE, "...Buf.size #inactive-socks Time/poll"));
621 PJ_LOG(3, (THIS_FILE, "... (bytes) (nanosec)"));
622 PJ_LOG(3, (THIS_FILE, "...====================================="));
623
624 for (bufsize=BUF_MIN_SIZE; bufsize <= BUF_MAX_SIZE; bufsize *= 2) {
625 if (bench_test(bufsize, SOCK_INACTIVE_MIN))
626 return -1;
627 }
628 bufsize = 512;
629 for (sock_count=SOCK_INACTIVE_MIN+2;
630 sock_count<=SOCK_INACTIVE_MAX+2;
631 sock_count *= 2)
632 {
633 //PJ_LOG(3,(THIS_FILE, "...testing with %d fds", sock_count));
634 if (bench_test(bufsize, sock_count-2))
635 return -1;
636 }
637 return 0;
638}
639
640#else
641/* To prevent warning about "translation unit is empty"
642 * when this test is disabled.
643 */
644int dummy_uiq_udp;
645#endif /* INCLUDE_UDP_IOQUEUE_TEST */
646
647