1
/* $Id: ioq_udp.c 4238 2012-08-31 06:17:56Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
* \page page_pjlib_ioqueue_udp_test Test: I/O Queue (UDP)
26
* This file provides implementation to test the
27
* functionality of the I/O queue when UDP socket is used.
30
* This file is <b>pjlib-test/ioq_udp.c</b>
32
* \include pjlib-test/ioq_udp.c
36
#if INCLUDE_UDP_IOQUEUE_TEST
40
#include <pj/compat/socket.h>
42
#define THIS_FILE "test_udp"
46
#define BUF_MIN_SIZE 32
47
#define BUF_MAX_SIZE 2048
48
#define SOCK_INACTIVE_MIN (1)
49
#define SOCK_INACTIVE_MAX (PJ_IOQUEUE_MAX_HANDLES - 2)
50
#define POOL_SIZE (2*BUF_MAX_SIZE + SOCK_INACTIVE_MAX*128 + 2048)
53
#define TRACE_(msg) PJ_LOG(3,(THIS_FILE,"....." msg))
56
# define TRACE__(args) PJ_LOG(3,args)
58
# define TRACE__(args)
62
static pj_ssize_t callback_read_size,
64
callback_accept_status,
65
callback_connect_status;
66
static pj_ioqueue_key_t *callback_read_key,
69
*callback_connect_key;
70
static pj_ioqueue_op_key_t *callback_read_op,
74
static void on_ioqueue_read(pj_ioqueue_key_t *key,
75
pj_ioqueue_op_key_t *op_key,
76
pj_ssize_t bytes_read)
78
callback_read_key = key;
79
callback_read_op = op_key;
80
callback_read_size = bytes_read;
81
TRACE__((THIS_FILE, " callback_read_key = %p, bytes=%d",
85
static void on_ioqueue_write(pj_ioqueue_key_t *key,
86
pj_ioqueue_op_key_t *op_key,
87
pj_ssize_t bytes_written)
89
callback_write_key = key;
90
callback_write_op = op_key;
91
callback_write_size = bytes_written;
94
static void on_ioqueue_accept(pj_ioqueue_key_t *key,
95
pj_ioqueue_op_key_t *op_key,
96
pj_sock_t sock, int status)
99
callback_accept_key = key;
100
callback_accept_op = op_key;
101
callback_accept_status = status;
104
static void on_ioqueue_connect(pj_ioqueue_key_t *key, int status)
106
callback_connect_key = key;
107
callback_connect_status = status;
110
static pj_ioqueue_callback test_cb =
119
# define S_ADDR S_un.S_addr
121
# define S_ADDR s_addr
126
* To test that the basic IOQueue functionality works. It will just exchange
127
* data between two sockets.
129
static int compliance_test(pj_bool_t allow_concur)
131
pj_sock_t ssock=-1, csock=-1;
132
pj_sockaddr_in addr, dst_addr;
134
pj_pool_t *pool = NULL;
135
char *send_buf, *recv_buf;
136
pj_ioqueue_t *ioque = NULL;
137
pj_ioqueue_key_t *skey = NULL, *ckey = NULL;
138
pj_ioqueue_op_key_t read_op, write_op;
139
int bufsize = BUF_MIN_SIZE;
140
pj_ssize_t bytes, status = -1;
142
pj_bool_t send_pending, recv_pending;
145
pj_set_os_error(PJ_SUCCESS);
148
pool = pj_pool_create(mem, NULL, POOL_SIZE, 4000, NULL);
150
// Allocate buffers for send and receive.
151
send_buf = (char*)pj_pool_alloc(pool, bufsize);
152
recv_buf = (char*)pj_pool_alloc(pool, bufsize);
154
// Allocate sockets for sending and receiving.
155
TRACE_("creating sockets...");
156
rc = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &ssock);
158
rc = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &csock);
160
csock = PJ_INVALID_SOCKET;
161
if (rc != PJ_SUCCESS) {
162
app_perror("...ERROR in pj_sock_socket()", rc);
163
status=-1; goto on_error;
166
// Bind server socket.
167
TRACE_("bind socket...");
168
pj_bzero(&addr, sizeof(addr));
169
addr.sin_family = pj_AF_INET();
170
addr.sin_port = pj_htons(PORT);
171
if (pj_sock_bind(ssock, &addr, sizeof(addr))) {
172
status=-10; goto on_error;
176
TRACE_("create ioqueue...");
177
rc = pj_ioqueue_create(pool, PJ_IOQUEUE_MAX_HANDLES, &ioque);
178
if (rc != PJ_SUCCESS) {
179
status=-20; goto on_error;
183
TRACE_("set concurrency...");
184
rc = pj_ioqueue_set_default_concurrency(ioque, allow_concur);
185
if (rc != PJ_SUCCESS) {
186
status=-21; goto on_error;
189
// Register server and client socket.
190
// We put this after inactivity socket, hopefully this can represent the
191
// worst waiting time.
192
TRACE_("registering first sockets...");
193
rc = pj_ioqueue_register_sock(pool, ioque, ssock, NULL,
195
if (rc != PJ_SUCCESS) {
196
app_perror("...error(10): ioqueue_register error", rc);
197
status=-25; goto on_error;
199
TRACE_("registering second sockets...");
200
rc = pj_ioqueue_register_sock( pool, ioque, csock, NULL,
202
if (rc != PJ_SUCCESS) {
203
app_perror("...error(11): ioqueue_register error", rc);
204
status=-26; goto on_error;
207
// Randomize send_buf.
208
pj_create_random_string(send_buf, bufsize);
210
// Register reading from ioqueue.
211
TRACE_("start recvfrom...");
212
pj_bzero(&addr, sizeof(addr));
213
addrlen = sizeof(addr);
215
rc = pj_ioqueue_recvfrom(skey, &read_op, recv_buf, &bytes, 0,
217
if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
218
app_perror("...error: pj_ioqueue_recvfrom", rc);
219
status=-28; goto on_error;
220
} else if (rc == PJ_EPENDING) {
222
PJ_LOG(3, (THIS_FILE,
223
"......ok: recvfrom returned pending"));
225
PJ_LOG(3, (THIS_FILE,
226
"......error: recvfrom returned immediate ok!"));
227
status=-29; goto on_error;
230
// Set destination address to send the packet.
231
TRACE_("set destination address...");
232
temp = pj_str("127.0.0.1");
233
if ((rc=pj_sockaddr_in_init(&dst_addr, &temp, PORT)) != 0) {
234
app_perror("...error: unable to resolve 127.0.0.1", rc);
235
status=-290; goto on_error;
238
// Write must return the number of bytes.
239
TRACE_("start sendto...");
241
rc = pj_ioqueue_sendto(ckey, &write_op, send_buf, &bytes, 0, &dst_addr,
243
if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
244
app_perror("...error: pj_ioqueue_sendto", rc);
245
status=-30; goto on_error;
246
} else if (rc == PJ_EPENDING) {
248
PJ_LOG(3, (THIS_FILE,
249
"......ok: sendto returned pending"));
252
PJ_LOG(3, (THIS_FILE,
253
"......ok: sendto returned immediate success"));
256
// reset callback variables.
257
callback_read_size = callback_write_size = 0;
258
callback_accept_status = callback_connect_status = -2;
259
callback_read_key = callback_write_key =
260
callback_accept_key = callback_connect_key = NULL;
261
callback_read_op = callback_write_op = NULL;
264
while (send_pending || recv_pending) {
266
pj_time_val timeout = { 5, 0 };
270
rc = pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout));
272
rc = pj_ioqueue_poll(ioque, &timeout);
276
PJ_LOG(1,(THIS_FILE, "...ERROR: timed out..."));
277
status=-45; goto on_error;
279
app_perror("...ERROR in ioqueue_poll()", -rc);
280
status=-50; goto on_error;
283
if (callback_read_key != NULL) {
284
if (callback_read_size != bufsize) {
285
status=-61; goto on_error;
287
if (callback_read_key != skey) {
288
status=-65; goto on_error;
290
if (callback_read_op != &read_op) {
291
status=-66; goto on_error;
294
if (pj_memcmp(send_buf, recv_buf, bufsize) != 0) {
295
status=-67; goto on_error;
297
if (addrlen != sizeof(pj_sockaddr_in)) {
298
status=-68; goto on_error;
300
if (addr.sin_family != pj_AF_INET()) {
301
status=-69; goto on_error;
308
if (callback_write_key != NULL) {
309
if (callback_write_size != bufsize) {
310
status=-73; goto on_error;
312
if (callback_write_key != ckey) {
313
status=-75; goto on_error;
315
if (callback_write_op != &write_op) {
316
status=-76; goto on_error;
328
pj_ioqueue_unregister(skey);
329
else if (ssock != -1)
330
pj_sock_close(ssock);
333
pj_ioqueue_unregister(ckey);
334
else if (csock != -1)
335
pj_sock_close(csock);
338
pj_ioqueue_destroy(ioque);
339
pj_pool_release(pool);
345
static void on_read_complete(pj_ioqueue_key_t *key,
346
pj_ioqueue_op_key_t *op_key,
347
pj_ssize_t bytes_read)
349
unsigned *p_packet_cnt = (unsigned*) pj_ioqueue_get_user_data(key);
351
PJ_UNUSED_ARG(op_key);
352
PJ_UNUSED_ARG(bytes_read);
359
* Check if callback is still called after socket has been unregistered or
362
static int unregister_test(pj_bool_t allow_concur)
364
enum { RPORT = 50000, SPORT = 50001 };
366
pj_ioqueue_t *ioqueue;
371
pj_ioqueue_key_t *key;
372
pj_ioqueue_op_key_t opkey;
373
pj_ioqueue_callback cb;
375
char sendbuf[10], recvbuf[10];
380
pool = pj_pool_create(mem, "test", 4000, 4000, NULL);
382
app_perror("Unable to create pool", PJ_ENOMEM);
386
status = pj_ioqueue_create(pool, 16, &ioqueue);
387
if (status != PJ_SUCCESS) {
388
app_perror("Error creating ioqueue", status);
393
TRACE_("set concurrency...");
394
status = pj_ioqueue_set_default_concurrency(ioqueue, allow_concur);
395
if (status != PJ_SUCCESS) {
399
/* Create sender socket */
400
status = app_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, SPORT, &ssock);
401
if (status != PJ_SUCCESS) {
402
app_perror("Error initializing socket", status);
406
/* Create receiver socket. */
407
status = app_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, RPORT, &rsock);
408
if (status != PJ_SUCCESS) {
409
app_perror("Error initializing socket", status);
413
/* Register rsock to ioqueue. */
414
pj_bzero(&cb, sizeof(cb));
415
cb.on_read_complete = &on_read_complete;
417
status = pj_ioqueue_register_sock(pool, ioqueue, rsock, &packet_cnt,
419
if (status != PJ_SUCCESS) {
420
app_perror("Error registering to ioqueue", status);
424
/* Init operation key. */
425
pj_ioqueue_op_key_init(&opkey, sizeof(opkey));
428
bytes = sizeof(recvbuf);
429
status = pj_ioqueue_recv( key, &opkey, recvbuf, &bytes, 0);
430
if (status != PJ_EPENDING) {
431
app_perror("Expecting PJ_EPENDING, but got this", status);
435
/* Init destination address. */
436
addrlen = sizeof(addr);
437
status = pj_sock_getsockname(rsock, &addr, &addrlen);
438
if (status != PJ_SUCCESS) {
439
app_perror("getsockname error", status);
443
/* Override address with 127.0.0.1, since getsockname will return
444
* zero in the address field.
446
addr.sin_addr = pj_inet_addr2("127.0.0.1");
448
/* Init buffer to send */
449
pj_ansi_strcpy(sendbuf, "Hello0123");
451
/* Send one packet. */
452
bytes = sizeof(sendbuf);
453
status = pj_sock_sendto(ssock, sendbuf, &bytes, 0,
454
&addr, sizeof(addr));
456
if (status != PJ_SUCCESS) {
457
app_perror("sendto error", status);
461
/* Check if packet is received. */
462
timeout.sec = 1; timeout.msec = 0;
464
pj_symbianos_poll(-1, 1000);
466
pj_ioqueue_poll(ioqueue, &timeout);
469
if (packet_cnt != 1) {
473
/* Just to make sure things are settled.. */
474
pj_thread_sleep(100);
476
/* Start reading again. */
477
bytes = sizeof(recvbuf);
478
status = pj_ioqueue_recv( key, &opkey, recvbuf, &bytes, 0);
479
if (status != PJ_EPENDING) {
480
app_perror("Expecting PJ_EPENDING, but got this", status);
484
/* Reset packet counter */
487
/* Send one packet. */
488
bytes = sizeof(sendbuf);
489
status = pj_sock_sendto(ssock, sendbuf, &bytes, 0,
490
&addr, sizeof(addr));
492
if (status != PJ_SUCCESS) {
493
app_perror("sendto error", status);
497
/* Now unregister and close socket. */
498
pj_ioqueue_unregister(key);
502
pj_symbianos_poll(-1, 1000);
504
timeout.sec = 1; timeout.msec = 0;
505
pj_ioqueue_poll(ioqueue, &timeout);
508
/* Must NOT receive any packets after socket is closed! */
509
if (packet_cnt > 0) {
510
PJ_LOG(3,(THIS_FILE, "....errror: not expecting to receive packet "
511
"after socket has been closed"));
516
pj_sock_close(ssock);
517
pj_ioqueue_destroy(ioqueue);
519
pj_pool_release(pool);
526
* Testing with many handles.
527
* This will just test registering PJ_IOQUEUE_MAX_HANDLES count
528
* of sockets to the ioqueue.
530
static int many_handles_test(pj_bool_t allow_concur)
532
enum { MAX = PJ_IOQUEUE_MAX_HANDLES };
534
pj_ioqueue_t *ioqueue;
536
pj_ioqueue_key_t **key;
538
int count, i; /* must be signed */
540
PJ_LOG(3,(THIS_FILE,"...testing with so many handles"));
542
pool = pj_pool_create(mem, NULL, 4000, 4000, NULL);
546
key = (pj_ioqueue_key_t**)
547
pj_pool_alloc(pool, MAX*sizeof(pj_ioqueue_key_t*));
548
sock = (pj_sock_t*) pj_pool_alloc(pool, MAX*sizeof(pj_sock_t));
551
rc = pj_ioqueue_create(pool, MAX, &ioqueue);
552
if (rc != PJ_SUCCESS || ioqueue == NULL) {
553
app_perror("...error in pj_ioqueue_create", rc);
558
rc = pj_ioqueue_set_default_concurrency(ioqueue, allow_concur);
559
if (rc != PJ_SUCCESS) {
563
/* Register as many sockets. */
564
for (count=0; count<MAX; ++count) {
565
sock[count] = PJ_INVALID_SOCKET;
566
rc = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock[count]);
567
if (rc != PJ_SUCCESS || sock[count] == PJ_INVALID_SOCKET) {
568
PJ_LOG(3,(THIS_FILE, "....unable to create %d-th socket, rc=%d",
573
rc = pj_ioqueue_register_sock(pool, ioqueue, sock[count],
574
NULL, &test_cb, &key[count]);
575
if (rc != PJ_SUCCESS || key[count] == NULL) {
576
PJ_LOG(3,(THIS_FILE, "....unable to register %d-th socket, rc=%d",
584
/* Now deregister and close all handles. */
587
* It seems that the order of close(sock) is pretty important here.
588
* If we close the sockets with the same order as when they were created,
589
* RTEMS doesn't seem to reuse the sockets, thus next socket created
590
* will have descriptor higher than the last socket created.
591
* If we close the sockets in the reverse order, then the descriptor will
593
* This used to cause problem with select ioqueue, since the ioqueue
594
* always gives FD_SETSIZE for the first select() argument. This ioqueue
595
* behavior can be changed with setting PJ_SELECT_NEEDS_NFDS macro.
597
for (i=count-1; i>=0; --i) {
598
///for (i=0; i<count; ++i) {
599
rc = pj_ioqueue_unregister(key[i]);
600
if (rc != PJ_SUCCESS) {
601
app_perror("...error in pj_ioqueue_unregister", rc);
605
rc = pj_ioqueue_destroy(ioqueue);
606
if (rc != PJ_SUCCESS) {
607
app_perror("...error in pj_ioqueue_destroy", rc);
610
pj_pool_release(pool);
612
PJ_LOG(3,(THIS_FILE,"....many_handles_test() ok"));
618
* Multi-operation test.
622
* Benchmarking IOQueue
624
static int bench_test(pj_bool_t allow_concur, int bufsize,
625
int inactive_sock_count)
627
pj_sock_t ssock=-1, csock=-1;
629
pj_pool_t *pool = NULL;
630
pj_sock_t *inactive_sock=NULL;
631
pj_ioqueue_op_key_t *inactive_read_op;
632
char *send_buf, *recv_buf;
633
pj_ioqueue_t *ioque = NULL;
634
pj_ioqueue_key_t *skey, *ckey, *keys[SOCK_INACTIVE_MAX+2];
635
pj_timestamp t1, t2, t_elapsed;
636
int rc=0, i; /* i must be signed */
638
char errbuf[PJ_ERR_MSG_SIZE];
640
TRACE__((THIS_FILE, " bench test %d", inactive_sock_count));
643
pool = pj_pool_create(mem, NULL, POOL_SIZE, 4000, NULL);
645
// Allocate buffers for send and receive.
646
send_buf = (char*)pj_pool_alloc(pool, bufsize);
647
recv_buf = (char*)pj_pool_alloc(pool, bufsize);
649
// Allocate sockets for sending and receiving.
650
rc = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &ssock);
651
if (rc == PJ_SUCCESS) {
652
rc = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &csock);
654
csock = PJ_INVALID_SOCKET;
655
if (rc != PJ_SUCCESS) {
656
app_perror("...error: pj_sock_socket()", rc);
660
// Bind server socket.
661
pj_bzero(&addr, sizeof(addr));
662
addr.sin_family = pj_AF_INET();
663
addr.sin_port = pj_htons(PORT);
664
if (pj_sock_bind(ssock, &addr, sizeof(addr)))
667
pj_assert(inactive_sock_count+2 <= PJ_IOQUEUE_MAX_HANDLES);
670
rc = pj_ioqueue_create(pool, PJ_IOQUEUE_MAX_HANDLES, &ioque);
671
if (rc != PJ_SUCCESS) {
672
app_perror("...error: pj_ioqueue_create()", rc);
677
rc = pj_ioqueue_set_default_concurrency(ioque, allow_concur);
678
if (rc != PJ_SUCCESS) {
679
app_perror("...error: pj_ioqueue_set_default_concurrency()", rc);
683
// Allocate inactive sockets, and bind them to some arbitrary address.
684
// Then register them to the I/O queue, and start a read operation.
685
inactive_sock = (pj_sock_t*)pj_pool_alloc(pool,
686
inactive_sock_count*sizeof(pj_sock_t));
687
inactive_read_op = (pj_ioqueue_op_key_t*)pj_pool_alloc(pool,
688
inactive_sock_count*sizeof(pj_ioqueue_op_key_t));
689
pj_bzero(&addr, sizeof(addr));
690
addr.sin_family = pj_AF_INET();
691
for (i=0; i<inactive_sock_count; ++i) {
694
rc = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &inactive_sock[i]);
695
if (rc != PJ_SUCCESS || inactive_sock[i] < 0) {
696
app_perror("...error: pj_sock_socket()", rc);
699
if ((rc=pj_sock_bind(inactive_sock[i], &addr, sizeof(addr))) != 0) {
700
pj_sock_close(inactive_sock[i]);
701
inactive_sock[i] = PJ_INVALID_SOCKET;
702
app_perror("...error: pj_sock_bind()", rc);
705
rc = pj_ioqueue_register_sock(pool, ioque, inactive_sock[i],
706
NULL, &test_cb, &keys[i]);
707
if (rc != PJ_SUCCESS) {
708
pj_sock_close(inactive_sock[i]);
709
inactive_sock[i] = PJ_INVALID_SOCKET;
710
app_perror("...error(1): pj_ioqueue_register_sock()", rc);
711
PJ_LOG(3,(THIS_FILE, "....i=%d", i));
715
rc = pj_ioqueue_recv(keys[i], &inactive_read_op[i], recv_buf, &bytes, 0);
716
if (rc != PJ_EPENDING) {
717
pj_sock_close(inactive_sock[i]);
718
inactive_sock[i] = PJ_INVALID_SOCKET;
719
app_perror("...error: pj_ioqueue_read()", rc);
724
// Register server and client socket.
725
// We put this after inactivity socket, hopefully this can represent the
726
// worst waiting time.
727
rc = pj_ioqueue_register_sock(pool, ioque, ssock, NULL,
729
if (rc != PJ_SUCCESS) {
730
app_perror("...error(2): pj_ioqueue_register_sock()", rc);
734
rc = pj_ioqueue_register_sock(pool, ioque, csock, NULL,
736
if (rc != PJ_SUCCESS) {
737
app_perror("...error(3): pj_ioqueue_register_sock()", rc);
741
// Set destination address to send the packet.
742
pj_sockaddr_in_init(&addr, pj_cstr(&temp, "127.0.0.1"), PORT);
746
for (i=0; i<LOOP; ++i) {
748
pj_ioqueue_op_key_t read_op, write_op;
750
// Randomize send buffer.
751
pj_create_random_string(send_buf, bufsize);
753
// Start reading on the server side.
755
rc = pj_ioqueue_recv(skey, &read_op, recv_buf, &bytes, 0);
756
if (rc != PJ_EPENDING) {
757
app_perror("...error: pj_ioqueue_read()", rc);
761
// Starts send on the client side.
763
rc = pj_ioqueue_sendto(ckey, &write_op, send_buf, &bytes, 0,
764
&addr, sizeof(addr));
765
if (rc != PJ_SUCCESS && rc != PJ_EPENDING) {
766
app_perror("...error: pj_ioqueue_write()", rc);
769
if (rc == PJ_SUCCESS) {
771
app_perror("...error: pj_ioqueue_sendto()", -bytes);
777
pj_get_timestamp(&t1);
779
// Poll the queue until we've got completion event in the server side.
780
callback_read_key = NULL;
781
callback_read_size = 0;
782
TRACE__((THIS_FILE, " waiting for key = %p", skey));
784
pj_time_val timeout = { 1, 0 };
786
rc = pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout));
788
rc = pj_ioqueue_poll(ioque, &timeout);
790
TRACE__((THIS_FILE, " poll rc=%d", rc));
791
} while (rc >= 0 && callback_read_key != skey);
794
pj_get_timestamp(&t2);
795
t_elapsed.u64 += (t2.u64 - t1.u64);
798
app_perror(" error: pj_ioqueue_poll", -rc);
802
// Compare recv buffer with send buffer.
803
if (callback_read_size != bufsize ||
804
pj_memcmp(send_buf, recv_buf, bufsize))
807
PJ_LOG(3,(THIS_FILE, " error: size/buffer mismatch"));
811
// Poll until all events are exhausted, before we start the next loop.
813
pj_time_val timeout = { 0, 10 };
815
PJ_UNUSED_ARG(timeout);
816
rc = pj_symbianos_poll(-1, 100);
818
rc = pj_ioqueue_poll(ioque, &timeout);
828
pj_uint32_t usec_delay;
830
tzero.u32.hi = tzero.u32.lo = 0;
831
usec_delay = pj_elapsed_usec( &tzero, &t_elapsed);
833
PJ_LOG(3, (THIS_FILE, "...%10d %15d % 9d",
834
bufsize, inactive_sock_count, usec_delay));
837
PJ_LOG(2, (THIS_FILE, "...ERROR rc=%d (buf:%d, fds:%d)",
838
rc, bufsize, inactive_sock_count+2));
842
for (i=inactive_sock_count-1; i>=0; --i) {
843
pj_ioqueue_unregister(keys[i]);
846
pj_ioqueue_unregister(skey);
847
pj_ioqueue_unregister(ckey);
850
pj_ioqueue_destroy(ioque);
851
pj_pool_release( pool);
855
PJ_LOG(1,(THIS_FILE, "...ERROR: %s",
856
pj_strerror(pj_get_netos_error(), errbuf, sizeof(errbuf))));
858
pj_sock_close(ssock);
860
pj_sock_close(csock);
861
for (i=0; i<inactive_sock_count && inactive_sock &&
862
inactive_sock[i]!=PJ_INVALID_SOCKET; ++i)
864
pj_sock_close(inactive_sock[i]);
867
pj_ioqueue_destroy(ioque);
868
pj_pool_release( pool);
872
static int udp_ioqueue_test_imp(pj_bool_t allow_concur)
875
int bufsize, sock_count;
877
PJ_LOG(3,(THIS_FILE, "..testing with concurency=%d", allow_concur));
881
PJ_LOG(3, (THIS_FILE, "...compliance test (%s)", pj_ioqueue_name()));
882
if ((status=compliance_test(allow_concur)) != 0) {
885
PJ_LOG(3, (THIS_FILE, "....compliance test ok"));
888
PJ_LOG(3, (THIS_FILE, "...unregister test (%s)", pj_ioqueue_name()));
889
if ((status=unregister_test(allow_concur)) != 0) {
892
PJ_LOG(3, (THIS_FILE, "....unregister test ok"));
894
if ((status=many_handles_test(allow_concur)) != 0) {
900
PJ_LOG(4, (THIS_FILE, "...benchmarking different buffer size:"));
901
PJ_LOG(4, (THIS_FILE, "... note: buf=bytes sent, fds=# of fds, "
902
"elapsed=in timer ticks"));
905
PJ_LOG(3, (THIS_FILE, "...Benchmarking poll times for %s:", pj_ioqueue_name()));
906
PJ_LOG(3, (THIS_FILE, "...====================================="));
907
PJ_LOG(3, (THIS_FILE, "...Buf.size #inactive-socks Time/poll"));
908
PJ_LOG(3, (THIS_FILE, "... (bytes) (nanosec)"));
909
PJ_LOG(3, (THIS_FILE, "...====================================="));
913
for (bufsize=BUF_MIN_SIZE; bufsize <= BUF_MAX_SIZE; bufsize *= 2) {
914
if ((status=bench_test(allow_concur, bufsize, SOCK_INACTIVE_MIN)) != 0)
919
for (sock_count=SOCK_INACTIVE_MIN+2;
920
sock_count<=SOCK_INACTIVE_MAX+2;
923
//PJ_LOG(3,(THIS_FILE, "...testing with %d fds", sock_count));
924
if ((status=bench_test(allow_concur, bufsize, sock_count-2)) != 0)
930
int udp_ioqueue_test()
934
rc = udp_ioqueue_test_imp(PJ_TRUE);
938
rc = udp_ioqueue_test_imp(PJ_FALSE);
946
/* To prevent warning about "translation unit is empty"
947
* when this test is disabled.
950
#endif /* INCLUDE_UDP_IOQUEUE_TEST */