blob: 35669dc0cf86ed4b1cd867d14ee1215b1dab439e [file] [log] [blame]
Alexandre Lision94f06ba2013-12-09 16:28:33 -05001/* $Id$ */
Tristan Matthews0a329cc2013-07-17 13:20:14 -04002/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
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.
10 *
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.
15 *
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
19 */
20#include <pjlib.h>
21#include "test.h"
22
23
24/**
25 * \page page_pjlib_sock_test Test: Socket
26 *
27 * This file provides implementation of \b sock_test(). It tests the
28 * various aspects of the socket API.
29 *
30 * \section sock_test_scope_sec Scope of the Test
31 *
32 * The scope of the test:
33 * - verify the validity of the address structs.
34 * - verify that address manipulation API works.
35 * - simple socket creation and destruction.
36 * - simple socket send/recv and sendto/recvfrom.
37 * - UDP connect()
38 * - send/recv big data.
39 * - all for both UDP and TCP.
40 *
41 * The APIs tested in this test:
42 * - pj_inet_aton()
43 * - pj_inet_ntoa()
44 * - pj_inet_pton() (only if IPv6 is enabled)
45 * - pj_inet_ntop() (only if IPv6 is enabled)
46 * - pj_gethostname()
47 * - pj_sock_socket()
48 * - pj_sock_close()
49 * - pj_sock_send()
50 * - pj_sock_sendto()
51 * - pj_sock_recv()
52 * - pj_sock_recvfrom()
53 * - pj_sock_bind()
54 * - pj_sock_connect()
55 * - pj_sock_listen()
56 * - pj_sock_accept()
57 * - pj_gethostbyname()
58 *
59 *
60 * This file is <b>pjlib-test/sock.c</b>
61 *
62 * \include pjlib-test/sock.c
63 */
64
65#if INCLUDE_SOCK_TEST
66
67#define UDP_PORT 51234
68#define TCP_PORT (UDP_PORT+10)
69#define BIG_DATA_LEN 8192
70#define ADDRESS "127.0.0.1"
71
72static char bigdata[BIG_DATA_LEN];
73static char bigbuffer[BIG_DATA_LEN];
74
75/* Macro for checking the value of "sin_len" member of sockaddr
76 * (it must always be zero).
77 */
78#if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0
79# define CHECK_SA_ZERO_LEN(addr, ret) \
80 if (((pj_addr_hdr*)(addr))->sa_zero_len != 0) \
81 return ret
82#else
83# define CHECK_SA_ZERO_LEN(addr, ret)
84#endif
85
86
87static int format_test(void)
88{
89 pj_str_t s = pj_str(ADDRESS);
90 unsigned char *p;
91 pj_in_addr addr;
92 char zero[64];
93 pj_sockaddr_in addr2;
94 const pj_str_t *hostname;
95 const unsigned char A[] = {127, 0, 0, 1};
96
97 PJ_LOG(3,("test", "...format_test()"));
98
99 /* pj_inet_aton() */
100 if (pj_inet_aton(&s, &addr) != 1)
101 return -10;
102
103 /* Check the result. */
104 p = (unsigned char*)&addr;
105 if (p[0]!=A[0] || p[1]!=A[1] || p[2]!=A[2] || p[3]!=A[3]) {
106 PJ_LOG(3,("test", " error: mismatched address. p0=%d, p1=%d, "
107 "p2=%d, p3=%d", p[0] & 0xFF, p[1] & 0xFF,
108 p[2] & 0xFF, p[3] & 0xFF));
109 return -15;
110 }
111
112 /* pj_inet_ntoa() */
113 p = (unsigned char*) pj_inet_ntoa(addr);
114 if (!p)
115 return -20;
116
117 if (pj_strcmp2(&s, (char*)p) != 0)
118 return -22;
119
120#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6!=0
121 /* pj_inet_pton() */
122 /* pj_inet_ntop() */
123 {
124 const pj_str_t s_ipv4 = pj_str("127.0.0.1");
125 const pj_str_t s_ipv6 = pj_str("fe80::2ff:83ff:fe7c:8b42");
126 char buf_ipv4[PJ_INET_ADDRSTRLEN];
127 char buf_ipv6[PJ_INET6_ADDRSTRLEN];
128 pj_in_addr ipv4;
129 pj_in6_addr ipv6;
130
131 if (pj_inet_pton(pj_AF_INET(), &s_ipv4, &ipv4) != PJ_SUCCESS)
132 return -24;
133
134 p = (unsigned char*)&ipv4;
135 if (p[0]!=A[0] || p[1]!=A[1] || p[2]!=A[2] || p[3]!=A[3]) {
136 return -25;
137 }
138
139 if (pj_inet_pton(pj_AF_INET6(), &s_ipv6, &ipv6) != PJ_SUCCESS)
140 return -26;
141
142 p = (unsigned char*)&ipv6;
143 if (p[0] != 0xfe || p[1] != 0x80 || p[2] != 0 || p[3] != 0 ||
144 p[4] != 0 || p[5] != 0 || p[6] != 0 || p[7] != 0 ||
145 p[8] != 0x02 || p[9] != 0xff || p[10] != 0x83 || p[11] != 0xff ||
146 p[12]!=0xfe || p[13]!=0x7c || p[14] != 0x8b || p[15]!=0x42)
147 {
148 return -27;
149 }
150
151 if (pj_inet_ntop(pj_AF_INET(), &ipv4, buf_ipv4, sizeof(buf_ipv4)) != PJ_SUCCESS)
152 return -28;
153 if (pj_stricmp2(&s_ipv4, buf_ipv4) != 0)
154 return -29;
155
156 if (pj_inet_ntop(pj_AF_INET6(), &ipv6, buf_ipv6, sizeof(buf_ipv6)) != PJ_SUCCESS)
157 return -30;
158 if (pj_stricmp2(&s_ipv6, buf_ipv6) != 0)
159 return -31;
160 }
161
162#endif /* PJ_HAS_IPV6 */
163
164 /* Test that pj_sockaddr_in_init() initialize the whole structure,
165 * including sin_zero.
166 */
167 pj_sockaddr_in_init(&addr2, 0, 1000);
168 pj_bzero(zero, sizeof(zero));
169 if (pj_memcmp(addr2.sin_zero, zero, sizeof(addr2.sin_zero)) != 0)
170 return -35;
171
172 /* pj_gethostname() */
173 hostname = pj_gethostname();
174 if (!hostname || !hostname->ptr || !hostname->slen)
175 return -40;
176
177 PJ_LOG(3,("test", "....hostname is %.*s",
178 (int)hostname->slen, hostname->ptr));
179
180 /* pj_gethostaddr() */
181
182 /* Various constants */
183#if !defined(PJ_SYMBIAN) || PJ_SYMBIAN==0
184 if (PJ_AF_INET==0xFFFF) return -5500;
185 if (PJ_AF_INET6==0xFFFF) return -5501;
186
187 /* 0xFFFF could be a valid SOL_SOCKET (e.g: on some Win or Mac) */
188 //if (PJ_SOL_SOCKET==0xFFFF) return -5503;
189
190 if (PJ_SOL_IP==0xFFFF) return -5502;
191 if (PJ_SOL_TCP==0xFFFF) return -5510;
192 if (PJ_SOL_UDP==0xFFFF) return -5520;
193 if (PJ_SOL_IPV6==0xFFFF) return -5530;
194
195 if (PJ_SO_TYPE==0xFFFF) return -5540;
196 if (PJ_SO_RCVBUF==0xFFFF) return -5550;
197 if (PJ_SO_SNDBUF==0xFFFF) return -5560;
198 if (PJ_TCP_NODELAY==0xFFFF) return -5570;
199 if (PJ_SO_REUSEADDR==0xFFFF) return -5580;
200
201 if (PJ_MSG_OOB==0xFFFF) return -5590;
202 if (PJ_MSG_PEEK==0xFFFF) return -5600;
203#endif
204
205 return 0;
206}
207
208static int parse_test(void)
209{
210#define IPv4 1
211#define IPv6 2
212
213 struct test_t {
214 const char *input;
215 int result_af;
216 const char *result_ip;
217 pj_uint16_t result_port;
218 };
219 struct test_t valid_tests[] =
220 {
221 /* IPv4 */
222 { "10.0.0.1:80", IPv4, "10.0.0.1", 80},
223 { "10.0.0.1", IPv4, "10.0.0.1", 0},
224 { "10.0.0.1:", IPv4, "10.0.0.1", 0},
225 { "10.0.0.1:0", IPv4, "10.0.0.1", 0},
226 { ":80", IPv4, "0.0.0.0", 80},
227 { ":", IPv4, "0.0.0.0", 0},
228#if !PJ_SYMBIAN
229 { "localhost", IPv4, "127.0.0.1", 0},
230 { "localhost:", IPv4, "127.0.0.1", 0},
231 { "localhost:80", IPv4, "127.0.0.1", 80},
232#endif
233
234#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6
235 { "fe::01:80", IPv6, "fe::01:80", 0},
236 { "[fe::01]:80", IPv6, "fe::01", 80},
237 { "fe::01", IPv6, "fe::01", 0},
238 { "[fe::01]", IPv6, "fe::01", 0},
239 { "fe::01:", IPv6, "fe::01", 0},
240 { "[fe::01]:", IPv6, "fe::01", 0},
241 { "::", IPv6, "::0", 0},
242 { "[::]", IPv6, "::", 0},
243 { ":::", IPv6, "::", 0},
244 { "[::]:", IPv6, "::", 0},
245 { ":::80", IPv6, "::", 80},
246 { "[::]:80", IPv6, "::", 80},
247#endif
248 };
249 struct test_t invalid_tests[] =
250 {
251 /* IPv4 */
252 { "10.0.0.1:abcd", IPv4}, /* port not numeric */
253 { "10.0.0.1:-1", IPv4}, /* port contains illegal character */
254 { "10.0.0.1:123456", IPv4}, /* port too big */
255 { "1.2.3.4.5:80", IPv4}, /* invalid IP */
256 { "10:0:80", IPv4}, /* hostname has colon */
257
258#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6
259 { "[fe::01]:abcd", IPv6}, /* port not numeric */
260 { "[fe::01]:-1", IPv6}, /* port contains illegal character */
261 { "[fe::01]:123456", IPv6}, /* port too big */
262 { "fe::01:02::03:04:80", IPv6}, /* invalid IP */
263 { "[fe::01:02::03:04]:80", IPv6}, /* invalid IP */
264 { "[fe:01", IPv6}, /* Unterminated bracket */
265#endif
266 };
267
268 unsigned i;
269
270 PJ_LOG(3,("test", "...IP address parsing"));
271
272 for (i=0; i<PJ_ARRAY_SIZE(valid_tests); ++i) {
273 pj_status_t status;
274 pj_str_t input;
275 pj_sockaddr addr, result;
276
277 switch (valid_tests[i].result_af) {
278 case IPv4:
279 valid_tests[i].result_af = PJ_AF_INET;
280 break;
281 case IPv6:
282 valid_tests[i].result_af = PJ_AF_INET6;
283 break;
284 default:
285 pj_assert(!"Invalid AF!");
286 continue;
287 }
288
289 /* Try parsing with PJ_AF_UNSPEC */
290 status = pj_sockaddr_parse(PJ_AF_UNSPEC, 0,
291 pj_cstr(&input, valid_tests[i].input),
292 &addr);
293 if (status != PJ_SUCCESS) {
294 PJ_LOG(1,("test", ".... failed when parsing %s (i=%d)",
295 valid_tests[i].input, i));
296 return -10;
297 }
298
299 /* Check "sin_len" member of parse result */
300 CHECK_SA_ZERO_LEN(&addr, -20);
301
302 /* Build the correct result */
303 status = pj_sockaddr_init(valid_tests[i].result_af,
304 &result,
305 pj_cstr(&input, valid_tests[i].result_ip),
306 valid_tests[i].result_port);
307 if (status != PJ_SUCCESS) {
308 PJ_LOG(1,("test", ".... error building IP address %s",
309 valid_tests[i].input));
310 return -30;
311 }
312
313 /* Compare the result */
314 if (pj_sockaddr_cmp(&addr, &result) != 0) {
315 PJ_LOG(1,("test", ".... parsed result mismatched for %s",
316 valid_tests[i].input));
317 return -40;
318 }
319
320 /* Parse again with the specified af */
321 status = pj_sockaddr_parse(valid_tests[i].result_af, 0,
322 pj_cstr(&input, valid_tests[i].input),
323 &addr);
324 if (status != PJ_SUCCESS) {
325 PJ_LOG(1,("test", ".... failed when parsing %s",
326 valid_tests[i].input));
327 return -50;
328 }
329
330 /* Check "sin_len" member of parse result */
331 CHECK_SA_ZERO_LEN(&addr, -55);
332
333 /* Compare the result again */
334 if (pj_sockaddr_cmp(&addr, &result) != 0) {
335 PJ_LOG(1,("test", ".... parsed result mismatched for %s",
336 valid_tests[i].input));
337 return -60;
338 }
339 }
340
341 for (i=0; i<PJ_ARRAY_SIZE(invalid_tests); ++i) {
342 pj_status_t status;
343 pj_str_t input;
344 pj_sockaddr addr;
345
346 switch (invalid_tests[i].result_af) {
347 case IPv4:
348 invalid_tests[i].result_af = PJ_AF_INET;
349 break;
350 case IPv6:
351 invalid_tests[i].result_af = PJ_AF_INET6;
352 break;
353 default:
354 pj_assert(!"Invalid AF!");
355 continue;
356 }
357
358 /* Try parsing with PJ_AF_UNSPEC */
359 status = pj_sockaddr_parse(PJ_AF_UNSPEC, 0,
360 pj_cstr(&input, invalid_tests[i].input),
361 &addr);
362 if (status == PJ_SUCCESS) {
363 PJ_LOG(1,("test", ".... expecting failure when parsing %s",
364 invalid_tests[i].input));
365 return -100;
366 }
367 }
368
369 return 0;
370}
371
372static int purity_test(void)
373{
374 PJ_LOG(3,("test", "...purity_test()"));
375
376#if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0
377 /* Check on "sin_len" member of sockaddr */
378 {
379 const pj_str_t str_ip = {"1.1.1.1", 7};
380 pj_sockaddr addr[16];
381 pj_addrinfo ai[16];
382 unsigned cnt;
383 pj_status_t rc;
384
385 /* pj_enum_ip_interface() */
386 cnt = PJ_ARRAY_SIZE(addr);
387 rc = pj_enum_ip_interface(pj_AF_UNSPEC(), &cnt, addr);
388 if (rc == PJ_SUCCESS) {
389 while (cnt--)
390 CHECK_SA_ZERO_LEN(&addr[cnt], -10);
391 }
392
393 /* pj_gethostip() on IPv4 */
394 rc = pj_gethostip(pj_AF_INET(), &addr[0]);
395 if (rc == PJ_SUCCESS)
396 CHECK_SA_ZERO_LEN(&addr[0], -20);
397
398 /* pj_gethostip() on IPv6 */
399 rc = pj_gethostip(pj_AF_INET6(), &addr[0]);
400 if (rc == PJ_SUCCESS)
401 CHECK_SA_ZERO_LEN(&addr[0], -30);
402
403 /* pj_getdefaultipinterface() on IPv4 */
404 rc = pj_getdefaultipinterface(pj_AF_INET(), &addr[0]);
405 if (rc == PJ_SUCCESS)
406 CHECK_SA_ZERO_LEN(&addr[0], -40);
407
408 /* pj_getdefaultipinterface() on IPv6 */
409 rc = pj_getdefaultipinterface(pj_AF_INET6(), &addr[0]);
410 if (rc == PJ_SUCCESS)
411 CHECK_SA_ZERO_LEN(&addr[0], -50);
412
413 /* pj_getaddrinfo() on a host name */
414 cnt = PJ_ARRAY_SIZE(ai);
415 rc = pj_getaddrinfo(pj_AF_UNSPEC(), pj_gethostname(), &cnt, ai);
416 if (rc == PJ_SUCCESS) {
417 while (cnt--)
418 CHECK_SA_ZERO_LEN(&ai[cnt].ai_addr, -60);
419 }
420
421 /* pj_getaddrinfo() on an IP address */
422 cnt = PJ_ARRAY_SIZE(ai);
423 rc = pj_getaddrinfo(pj_AF_UNSPEC(), &str_ip, &cnt, ai);
424 if (rc == PJ_SUCCESS) {
425 pj_assert(cnt == 1);
426 CHECK_SA_ZERO_LEN(&ai[0].ai_addr, -70);
427 }
428 }
429#endif
430
431 return 0;
432}
433
434static int simple_sock_test(void)
435{
436 int types[2];
437 pj_sock_t sock;
438 int i;
439 pj_status_t rc = PJ_SUCCESS;
440
441 types[0] = pj_SOCK_STREAM();
442 types[1] = pj_SOCK_DGRAM();
443
444 PJ_LOG(3,("test", "...simple_sock_test()"));
445
446 for (i=0; i<(int)(sizeof(types)/sizeof(types[0])); ++i) {
447
448 rc = pj_sock_socket(pj_AF_INET(), types[i], 0, &sock);
449 if (rc != PJ_SUCCESS) {
450 app_perror("...error: unable to create socket", rc);
451 break;
452 } else {
453 rc = pj_sock_close(sock);
454 if (rc != 0) {
455 app_perror("...error: close socket", rc);
456 break;
457 }
458 }
459 }
460 return rc;
461}
462
463
464static int send_recv_test(int sock_type,
465 pj_sock_t ss, pj_sock_t cs,
466 pj_sockaddr_in *dstaddr, pj_sockaddr_in *srcaddr,
467 int addrlen)
468{
469 enum { DATA_LEN = 16 };
470 char senddata[DATA_LEN+4], recvdata[DATA_LEN+4];
471 pj_ssize_t sent, received, total_received;
472 pj_status_t rc;
473
474 TRACE_(("test", "....create_random_string()"));
475 pj_create_random_string(senddata, DATA_LEN);
476 senddata[DATA_LEN-1] = '\0';
477
478 /*
479 * Test send/recv small data.
480 */
481 TRACE_(("test", "....sendto()"));
482 if (dstaddr) {
483 sent = DATA_LEN;
484 rc = pj_sock_sendto(cs, senddata, &sent, 0, dstaddr, addrlen);
485 if (rc != PJ_SUCCESS || sent != DATA_LEN) {
486 app_perror("...sendto error", rc);
487 rc = -140; goto on_error;
488 }
489 } else {
490 sent = DATA_LEN;
491 rc = pj_sock_send(cs, senddata, &sent, 0);
492 if (rc != PJ_SUCCESS || sent != DATA_LEN) {
493 app_perror("...send error", rc);
494 rc = -145; goto on_error;
495 }
496 }
497
498 TRACE_(("test", "....recv()"));
499 if (srcaddr) {
500 pj_sockaddr_in addr;
501 int srclen = sizeof(addr);
502
503 pj_bzero(&addr, sizeof(addr));
504
505 received = DATA_LEN;
506 rc = pj_sock_recvfrom(ss, recvdata, &received, 0, &addr, &srclen);
507 if (rc != PJ_SUCCESS || received != DATA_LEN) {
508 app_perror("...recvfrom error", rc);
509 rc = -150; goto on_error;
510 }
511 if (srclen != addrlen)
512 return -151;
513 if (pj_sockaddr_cmp(&addr, srcaddr) != 0) {
514 char srcaddr_str[32], addr_str[32];
515 strcpy(srcaddr_str, pj_inet_ntoa(srcaddr->sin_addr));
516 strcpy(addr_str, pj_inet_ntoa(addr.sin_addr));
517 PJ_LOG(3,("test", "...error: src address mismatch (original=%s, "
518 "recvfrom addr=%s)",
519 srcaddr_str, addr_str));
520 return -152;
521 }
522
523 } else {
524 /* Repeat recv() until all data is received.
525 * This applies only for non-UDP of course, since for UDP
526 * we would expect all data to be received in one packet.
527 */
528 total_received = 0;
529 do {
530 received = DATA_LEN-total_received;
531 rc = pj_sock_recv(ss, recvdata+total_received, &received, 0);
532 if (rc != PJ_SUCCESS) {
533 app_perror("...recv error", rc);
534 rc = -155; goto on_error;
535 }
536 if (received <= 0) {
537 PJ_LOG(3,("", "...error: socket has closed! (received=%d)",
538 received));
539 rc = -156; goto on_error;
540 }
541 if (received != DATA_LEN-total_received) {
542 if (sock_type != pj_SOCK_STREAM()) {
543 PJ_LOG(3,("", "...error: expecting %u bytes, got %u bytes",
544 DATA_LEN-total_received, received));
545 rc = -157; goto on_error;
546 }
547 }
548 total_received += received;
549 } while (total_received < DATA_LEN);
550 }
551
552 TRACE_(("test", "....memcmp()"));
553 if (pj_memcmp(senddata, recvdata, DATA_LEN) != 0) {
554 PJ_LOG(3,("","...error: received data mismatch "
555 "(got:'%s' expecting:'%s'",
556 recvdata, senddata));
557 rc = -160; goto on_error;
558 }
559
560 /*
561 * Test send/recv big data.
562 */
563 TRACE_(("test", "....sendto()"));
564 if (dstaddr) {
565 sent = BIG_DATA_LEN;
566 rc = pj_sock_sendto(cs, bigdata, &sent, 0, dstaddr, addrlen);
567 if (rc != PJ_SUCCESS || sent != BIG_DATA_LEN) {
568 app_perror("...sendto error", rc);
569 rc = -161; goto on_error;
570 }
571 } else {
572 sent = BIG_DATA_LEN;
573 rc = pj_sock_send(cs, bigdata, &sent, 0);
574 if (rc != PJ_SUCCESS || sent != BIG_DATA_LEN) {
575 app_perror("...send error", rc);
576 rc = -165; goto on_error;
577 }
578 }
579
580 TRACE_(("test", "....recv()"));
581
582 /* Repeat recv() until all data is received.
583 * This applies only for non-UDP of course, since for UDP
584 * we would expect all data to be received in one packet.
585 */
586 total_received = 0;
587 do {
588 received = BIG_DATA_LEN-total_received;
589 rc = pj_sock_recv(ss, bigbuffer+total_received, &received, 0);
590 if (rc != PJ_SUCCESS) {
591 app_perror("...recv error", rc);
592 rc = -170; goto on_error;
593 }
594 if (received <= 0) {
595 PJ_LOG(3,("", "...error: socket has closed! (received=%d)",
596 received));
597 rc = -173; goto on_error;
598 }
599 if (received != BIG_DATA_LEN-total_received) {
600 if (sock_type != pj_SOCK_STREAM()) {
601 PJ_LOG(3,("", "...error: expecting %u bytes, got %u bytes",
602 BIG_DATA_LEN-total_received, received));
603 rc = -176; goto on_error;
604 }
605 }
606 total_received += received;
607 } while (total_received < BIG_DATA_LEN);
608
609 TRACE_(("test", "....memcmp()"));
610 if (pj_memcmp(bigdata, bigbuffer, BIG_DATA_LEN) != 0) {
611 PJ_LOG(3,("", "...error: received data has been altered!"));
612 rc = -180; goto on_error;
613 }
614
615 rc = 0;
616
617on_error:
618 return rc;
619}
620
621static int udp_test(void)
622{
623 pj_sock_t cs = PJ_INVALID_SOCKET, ss = PJ_INVALID_SOCKET;
624 pj_sockaddr_in dstaddr, srcaddr;
625 pj_str_t s;
626 pj_status_t rc = 0, retval;
627
628 PJ_LOG(3,("test", "...udp_test()"));
629
630 rc = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &ss);
631 if (rc != 0) {
632 app_perror("...error: unable to create socket", rc);
633 return -100;
634 }
635
636 rc = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &cs);
637 if (rc != 0)
638 return -110;
639
640 /* Bind server socket. */
641 pj_bzero(&dstaddr, sizeof(dstaddr));
642 dstaddr.sin_family = pj_AF_INET();
643 dstaddr.sin_port = pj_htons(UDP_PORT);
644 dstaddr.sin_addr = pj_inet_addr(pj_cstr(&s, ADDRESS));
645
646 if ((rc=pj_sock_bind(ss, &dstaddr, sizeof(dstaddr))) != 0) {
647 app_perror("...bind error udp:"ADDRESS, rc);
648 rc = -120; goto on_error;
649 }
650
651 /* Bind client socket. */
652 pj_bzero(&srcaddr, sizeof(srcaddr));
653 srcaddr.sin_family = pj_AF_INET();
654 srcaddr.sin_port = pj_htons(UDP_PORT-1);
655 srcaddr.sin_addr = pj_inet_addr(pj_cstr(&s, ADDRESS));
656
657 if ((rc=pj_sock_bind(cs, &srcaddr, sizeof(srcaddr))) != 0) {
658 app_perror("...bind error", rc);
659 rc = -121; goto on_error;
660 }
661
662 /* Test send/recv, with sendto */
663 rc = send_recv_test(pj_SOCK_DGRAM(), ss, cs, &dstaddr, NULL,
664 sizeof(dstaddr));
665 if (rc != 0)
666 goto on_error;
667
668 /* Test send/recv, with sendto and recvfrom */
669 rc = send_recv_test(pj_SOCK_DGRAM(), ss, cs, &dstaddr,
670 &srcaddr, sizeof(dstaddr));
671 if (rc != 0)
672 goto on_error;
673
674 /* Disable this test on Symbian since UDP connect()/send() failed
675 * with S60 3rd edition (including MR2).
676 * See http://www.pjsip.org/trac/ticket/264
677 */
678#if !defined(PJ_SYMBIAN) || PJ_SYMBIAN==0
679 /* connect() the sockets. */
680 rc = pj_sock_connect(cs, &dstaddr, sizeof(dstaddr));
681 if (rc != 0) {
682 app_perror("...connect() error", rc);
683 rc = -122; goto on_error;
684 }
685
686 /* Test send/recv with send() */
687 rc = send_recv_test(pj_SOCK_DGRAM(), ss, cs, NULL, NULL, 0);
688 if (rc != 0)
689 goto on_error;
690
691 /* Test send/recv with send() and recvfrom */
692 rc = send_recv_test(pj_SOCK_DGRAM(), ss, cs, NULL, &srcaddr,
693 sizeof(srcaddr));
694 if (rc != 0)
695 goto on_error;
696#endif
697
698on_error:
699 retval = rc;
700 if (cs != PJ_INVALID_SOCKET) {
701 rc = pj_sock_close(cs);
702 if (rc != PJ_SUCCESS) {
703 app_perror("...error in closing socket", rc);
704 return -1000;
705 }
706 }
707 if (ss != PJ_INVALID_SOCKET) {
708 rc = pj_sock_close(ss);
709 if (rc != PJ_SUCCESS) {
710 app_perror("...error in closing socket", rc);
711 return -1010;
712 }
713 }
714
715 return retval;
716}
717
718static int tcp_test(void)
719{
720 pj_sock_t cs, ss;
721 pj_status_t rc = 0, retval;
722
723 PJ_LOG(3,("test", "...tcp_test()"));
724
725 rc = app_socketpair(pj_AF_INET(), pj_SOCK_STREAM(), 0, &ss, &cs);
726 if (rc != PJ_SUCCESS) {
727 app_perror("...error: app_socketpair():", rc);
728 return -2000;
729 }
730
731 /* Test send/recv with send() and recv() */
732 retval = send_recv_test(pj_SOCK_STREAM(), ss, cs, NULL, NULL, 0);
733
734 rc = pj_sock_close(cs);
735 if (rc != PJ_SUCCESS) {
736 app_perror("...error in closing socket", rc);
737 return -2000;
738 }
739
740 rc = pj_sock_close(ss);
741 if (rc != PJ_SUCCESS) {
742 app_perror("...error in closing socket", rc);
743 return -2010;
744 }
745
746 return retval;
747}
748
749static int ioctl_test(void)
750{
751 return 0;
752}
753
754static int gethostbyname_test(void)
755{
756 pj_str_t host;
757 pj_hostent he;
758 pj_status_t status;
759
760 /* Testing pj_gethostbyname() with invalid host */
761 host = pj_str("an-invalid-host-name");
762 status = pj_gethostbyname(&host, &he);
763
764 /* Must return failure! */
765 if (status == PJ_SUCCESS)
766 return -20100;
767 else
768 return 0;
769}
770
771#if 0
772#include "../pj/os_symbian.h"
773static int connect_test()
774{
775 RSocketServ rSockServ;
776 RSocket rSock;
777 TInetAddr inetAddr;
778 TRequestStatus reqStatus;
779 char buffer[16];
780 TPtrC8 data((const TUint8*)buffer, (TInt)sizeof(buffer));
781 int rc;
782
783 rc = rSockServ.Connect();
784 if (rc != KErrNone)
785 return rc;
786
787 rc = rSock.Open(rSockServ, KAfInet, KSockDatagram, KProtocolInetUdp);
788 if (rc != KErrNone)
789 {
790 rSockServ.Close();
791 return rc;
792 }
793
794 inetAddr.Init(KAfInet);
795 inetAddr.Input(_L("127.0.0.1"));
796 inetAddr.SetPort(80);
797
798 rSock.Connect(inetAddr, reqStatus);
799 User::WaitForRequest(reqStatus);
800
801 if (reqStatus != KErrNone) {
802 rSock.Close();
803 rSockServ.Close();
804 return rc;
805 }
806
807 rSock.Send(data, 0, reqStatus);
808 User::WaitForRequest(reqStatus);
809
810 if (reqStatus!=KErrNone) {
811 rSock.Close();
812 rSockServ.Close();
813 return rc;
814 }
815
816 rSock.Close();
817 rSockServ.Close();
818 return KErrNone;
819}
820#endif
821
822int sock_test()
823{
824 int rc;
825
826 pj_create_random_string(bigdata, BIG_DATA_LEN);
827
828// Enable this to demonstrate the error witn S60 3rd Edition MR2
829#if 0
830 rc = connect_test();
831 if (rc != 0)
832 return rc;
833#endif
834
835 rc = format_test();
836 if (rc != 0)
837 return rc;
838
839 rc = parse_test();
840 if (rc != 0)
841 return rc;
842
843 rc = purity_test();
844 if (rc != 0)
845 return rc;
846
847 rc = gethostbyname_test();
848 if (rc != 0)
849 return rc;
850
851 rc = simple_sock_test();
852 if (rc != 0)
853 return rc;
854
855 rc = ioctl_test();
856 if (rc != 0)
857 return rc;
858
859 rc = udp_test();
860 if (rc != 0)
861 return rc;
862
863 rc = tcp_test();
864 if (rc != 0)
865 return rc;
866
867 return 0;
868}
869
870
871#else
872/* To prevent warning about "translation unit is empty"
873 * when this test is disabled.
874 */
875int dummy_sock_test;
876#endif /* INCLUDE_SOCK_TEST */
877