blob: 4ccad789c04e91ea840f5095dc0f54839346937f [file] [log] [blame]
Benny Prijono5dcb38d2005-11-21 01:55:47 +00001/* $Id$ */
2/*
Benny Prijonoa771a512007-02-19 01:13:53 +00003 * Copyright (C)2003-2007 Benny Prijono <benny@prijono.org>
Benny Prijono5dcb38d2005-11-21 01:55:47 +00004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <pjlib.h>
20#include "test.h"
21
22
23/**
24 * \page page_pjlib_sock_test Test: Socket
25 *
26 * This file provides implementation of \b sock_test(). It tests the
27 * various aspects of the socket API.
28 *
29 * \section sock_test_scope_sec Scope of the Test
30 *
31 * The scope of the test:
32 * - verify the validity of the address structs.
33 * - verify that address manipulation API works.
34 * - simple socket creation and destruction.
35 * - simple socket send/recv and sendto/recvfrom.
36 * - UDP connect()
37 * - send/recv big data.
38 * - all for both UDP and TCP.
39 *
40 * The APIs tested in this test:
41 * - pj_inet_aton()
42 * - pj_inet_ntoa()
43 * - pj_gethostname()
44 * - pj_sock_socket()
45 * - pj_sock_close()
46 * - pj_sock_send()
47 * - pj_sock_sendto()
48 * - pj_sock_recv()
49 * - pj_sock_recvfrom()
50 * - pj_sock_bind()
51 * - pj_sock_connect()
52 * - pj_sock_listen()
53 * - pj_sock_accept()
Benny Prijono60cac482007-03-01 18:56:02 +000054 * - pj_gethostbyname()
Benny Prijono5dcb38d2005-11-21 01:55:47 +000055 *
56 *
57 * This file is <b>pjlib-test/sock.c</b>
58 *
59 * \include pjlib-test/sock.c
60 */
61
62#if INCLUDE_SOCK_TEST
63
64#define UDP_PORT 51234
65#define TCP_PORT (UDP_PORT+10)
Benny Prijonof260e462007-04-30 21:03:32 +000066#define BIG_DATA_LEN 8192
Benny Prijono42c5b9e2006-05-10 19:24:40 +000067#define ADDRESS "127.0.0.1"
Benny Prijono5dcb38d2005-11-21 01:55:47 +000068
69static char bigdata[BIG_DATA_LEN];
70static char bigbuffer[BIG_DATA_LEN];
71
72static int format_test(void)
73{
Benny Prijono42c5b9e2006-05-10 19:24:40 +000074 pj_str_t s = pj_str(ADDRESS);
75 unsigned char *p;
Benny Prijono5dcb38d2005-11-21 01:55:47 +000076 pj_in_addr addr;
Benny Prijono0e25e7c2006-06-28 11:10:02 +000077 char zero[64];
78 pj_sockaddr_in addr2;
Benny Prijono5dcb38d2005-11-21 01:55:47 +000079 const pj_str_t *hostname;
Benny Prijonof260e462007-04-30 21:03:32 +000080#if defined(PJ_SYMBIAN) && PJ_SYMBIAN!=0
81 /* Symbian IP address is saved in host order */
82 unsigned char A[] = {1, 0, 0, 127};
83#else
84 unsigned char A[] = {127, 0, 0, 1};
85#endif
Benny Prijono5dcb38d2005-11-21 01:55:47 +000086
87 PJ_LOG(3,("test", "...format_test()"));
88
89 /* pj_inet_aton() */
90 if (pj_inet_aton(&s, &addr) != 1)
91 return -10;
92
93 /* Check the result. */
Benny Prijono42c5b9e2006-05-10 19:24:40 +000094 p = (unsigned char*)&addr;
Benny Prijonof260e462007-04-30 21:03:32 +000095 if (p[0]!=A[0] || p[1]!=A[1] || p[2]!=A[2] || p[3]!=A[3]) {
Benny Prijono42c5b9e2006-05-10 19:24:40 +000096 PJ_LOG(3,("test", " error: mismatched address. p0=%d, p1=%d, "
97 "p2=%d, p3=%d", p[0] & 0xFF, p[1] & 0xFF,
98 p[2] & 0xFF, p[3] & 0xFF));
Benny Prijono5dcb38d2005-11-21 01:55:47 +000099 return -15;
Benny Prijono42c5b9e2006-05-10 19:24:40 +0000100 }
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000101
102 /* pj_inet_ntoa() */
Benny Prijonod8410532006-06-15 11:04:33 +0000103 p = (unsigned char*) pj_inet_ntoa(addr);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000104 if (!p)
105 return -20;
106
Benny Prijonod8410532006-06-15 11:04:33 +0000107 if (pj_strcmp2(&s, (char*)p) != 0)
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000108 return -30;
109
Benny Prijono0e25e7c2006-06-28 11:10:02 +0000110 /* Test that pj_sockaddr_in_init() initialize the whole structure,
111 * including sin_zero.
112 */
113 pj_sockaddr_in_init(&addr2, 0, 1000);
Benny Prijonoac623b32006-07-03 15:19:31 +0000114 pj_bzero(zero, sizeof(zero));
Benny Prijono0e25e7c2006-06-28 11:10:02 +0000115 if (pj_memcmp(addr2.sin_zero, zero, sizeof(addr2.sin_zero)) != 0)
116 return -35;
117
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000118 /* pj_gethostname() */
119 hostname = pj_gethostname();
120 if (!hostname || !hostname->ptr || !hostname->slen)
121 return -40;
122
Benny Prijono42c5b9e2006-05-10 19:24:40 +0000123 PJ_LOG(3,("test", "....hostname is %.*s",
124 (int)hostname->slen, hostname->ptr));
125
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000126 /* pj_gethostaddr() */
127
Benny Prijono0e25e7c2006-06-28 11:10:02 +0000128
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000129 return 0;
130}
131
132static int simple_sock_test(void)
133{
134 int types[2];
135 pj_sock_t sock;
136 int i;
137 pj_status_t rc = PJ_SUCCESS;
138
139 types[0] = PJ_SOCK_STREAM;
140 types[1] = PJ_SOCK_DGRAM;
141
142 PJ_LOG(3,("test", "...simple_sock_test()"));
143
144 for (i=0; i<sizeof(types)/sizeof(types[0]); ++i) {
145
146 rc = pj_sock_socket(PJ_AF_INET, types[i], 0, &sock);
147 if (rc != PJ_SUCCESS) {
148 app_perror("...error: unable to create socket type %d", rc);
149 break;
150 } else {
151 rc = pj_sock_close(sock);
152 if (rc != 0) {
153 app_perror("...error: close socket", rc);
154 break;
155 }
156 }
157 }
158 return rc;
159}
160
161
162static int send_recv_test(int sock_type,
163 pj_sock_t ss, pj_sock_t cs,
164 pj_sockaddr_in *dstaddr, pj_sockaddr_in *srcaddr,
165 int addrlen)
166{
167 enum { DATA_LEN = 16 };
168 char senddata[DATA_LEN+4], recvdata[DATA_LEN+4];
169 pj_ssize_t sent, received, total_received;
170 pj_status_t rc;
171
172 TRACE_(("test", "....create_random_string()"));
173 pj_create_random_string(senddata, DATA_LEN);
174 senddata[DATA_LEN-1] = '\0';
175
176 /*
177 * Test send/recv small data.
178 */
179 TRACE_(("test", "....sendto()"));
180 if (dstaddr) {
181 sent = DATA_LEN;
182 rc = pj_sock_sendto(cs, senddata, &sent, 0, dstaddr, addrlen);
183 if (rc != PJ_SUCCESS || sent != DATA_LEN) {
184 app_perror("...sendto error", rc);
185 rc = -140; goto on_error;
186 }
187 } else {
188 sent = DATA_LEN;
189 rc = pj_sock_send(cs, senddata, &sent, 0);
190 if (rc != PJ_SUCCESS || sent != DATA_LEN) {
191 app_perror("...send error", rc);
192 rc = -145; goto on_error;
193 }
194 }
195
196 TRACE_(("test", "....recv()"));
197 if (srcaddr) {
198 pj_sockaddr_in addr;
199 int srclen = sizeof(addr);
200
Benny Prijonoac623b32006-07-03 15:19:31 +0000201 pj_bzero(&addr, sizeof(addr));
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000202
203 received = DATA_LEN;
204 rc = pj_sock_recvfrom(ss, recvdata, &received, 0, &addr, &srclen);
205 if (rc != PJ_SUCCESS || received != DATA_LEN) {
206 app_perror("...recvfrom error", rc);
207 rc = -150; goto on_error;
208 }
209 if (srclen != addrlen)
210 return -151;
211 if (pj_memcmp(&addr, srcaddr, srclen) != 0) {
212 char srcaddr_str[32], addr_str[32];
213 strcpy(srcaddr_str, pj_inet_ntoa(srcaddr->sin_addr));
214 strcpy(addr_str, pj_inet_ntoa(addr.sin_addr));
215 PJ_LOG(3,("test", "...error: src address mismatch (original=%s, "
216 "recvfrom addr=%s)",
217 srcaddr_str, addr_str));
218 return -152;
219 }
220
221 } else {
222 /* Repeat recv() until all data is received.
223 * This applies only for non-UDP of course, since for UDP
224 * we would expect all data to be received in one packet.
225 */
226 total_received = 0;
227 do {
228 received = DATA_LEN-total_received;
229 rc = pj_sock_recv(ss, recvdata+total_received, &received, 0);
230 if (rc != PJ_SUCCESS) {
231 app_perror("...recv error", rc);
232 rc = -155; goto on_error;
233 }
234 if (received <= 0) {
235 PJ_LOG(3,("", "...error: socket has closed! (received=%d)",
236 received));
237 rc = -156; goto on_error;
238 }
239 if (received != DATA_LEN-total_received) {
240 if (sock_type != PJ_SOCK_STREAM) {
241 PJ_LOG(3,("", "...error: expecting %u bytes, got %u bytes",
242 DATA_LEN-total_received, received));
243 rc = -157; goto on_error;
244 }
245 }
246 total_received += received;
247 } while (total_received < DATA_LEN);
248 }
249
250 TRACE_(("test", "....memcmp()"));
251 if (pj_memcmp(senddata, recvdata, DATA_LEN) != 0) {
252 PJ_LOG(3,("","...error: received data mismatch "
253 "(got:'%s' expecting:'%s'",
254 recvdata, senddata));
255 rc = -160; goto on_error;
256 }
257
258 /*
259 * Test send/recv big data.
260 */
261 TRACE_(("test", "....sendto()"));
262 if (dstaddr) {
263 sent = BIG_DATA_LEN;
264 rc = pj_sock_sendto(cs, bigdata, &sent, 0, dstaddr, addrlen);
265 if (rc != PJ_SUCCESS || sent != BIG_DATA_LEN) {
266 app_perror("...sendto error", rc);
267 rc = -161; goto on_error;
268 }
269 } else {
270 sent = BIG_DATA_LEN;
271 rc = pj_sock_send(cs, bigdata, &sent, 0);
272 if (rc != PJ_SUCCESS || sent != BIG_DATA_LEN) {
273 app_perror("...send error", rc);
274 rc = -165; goto on_error;
275 }
276 }
277
278 TRACE_(("test", "....recv()"));
279
280 /* Repeat recv() until all data is received.
281 * This applies only for non-UDP of course, since for UDP
282 * we would expect all data to be received in one packet.
283 */
284 total_received = 0;
285 do {
286 received = BIG_DATA_LEN-total_received;
287 rc = pj_sock_recv(ss, bigbuffer+total_received, &received, 0);
288 if (rc != PJ_SUCCESS) {
289 app_perror("...recv error", rc);
290 rc = -170; goto on_error;
291 }
292 if (received <= 0) {
293 PJ_LOG(3,("", "...error: socket has closed! (received=%d)",
294 received));
295 rc = -173; goto on_error;
296 }
297 if (received != BIG_DATA_LEN-total_received) {
298 if (sock_type != PJ_SOCK_STREAM) {
299 PJ_LOG(3,("", "...error: expecting %u bytes, got %u bytes",
300 BIG_DATA_LEN-total_received, received));
301 rc = -176; goto on_error;
302 }
303 }
304 total_received += received;
305 } while (total_received < BIG_DATA_LEN);
306
307 TRACE_(("test", "....memcmp()"));
308 if (pj_memcmp(bigdata, bigbuffer, BIG_DATA_LEN) != 0) {
309 PJ_LOG(3,("", "...error: received data has been altered!"));
310 rc = -180; goto on_error;
311 }
312
313 rc = 0;
314
315on_error:
316 return rc;
317}
318
319static int udp_test(void)
320{
321 pj_sock_t cs = PJ_INVALID_SOCKET, ss = PJ_INVALID_SOCKET;
322 pj_sockaddr_in dstaddr, srcaddr;
323 pj_str_t s;
324 pj_status_t rc = 0, retval;
325
326 PJ_LOG(3,("test", "...udp_test()"));
327
328 rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &ss);
329 if (rc != 0) {
330 app_perror("...error: unable to create socket", rc);
331 return -100;
332 }
333
334 rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &cs);
335 if (rc != 0)
336 return -110;
337
338 /* Bind server socket. */
Benny Prijonoac623b32006-07-03 15:19:31 +0000339 pj_bzero(&dstaddr, sizeof(dstaddr));
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000340 dstaddr.sin_family = PJ_AF_INET;
341 dstaddr.sin_port = pj_htons(UDP_PORT);
Benny Prijono42c5b9e2006-05-10 19:24:40 +0000342 dstaddr.sin_addr = pj_inet_addr(pj_cstr(&s, ADDRESS));
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000343
344 if ((rc=pj_sock_bind(ss, &dstaddr, sizeof(dstaddr))) != 0) {
Benny Prijono42c5b9e2006-05-10 19:24:40 +0000345 app_perror("...bind error udp:"ADDRESS, rc);
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000346 rc = -120; goto on_error;
347 }
348
349 /* Bind client socket. */
Benny Prijonoac623b32006-07-03 15:19:31 +0000350 pj_bzero(&srcaddr, sizeof(srcaddr));
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000351 srcaddr.sin_family = PJ_AF_INET;
352 srcaddr.sin_port = pj_htons(UDP_PORT-1);
Benny Prijono42c5b9e2006-05-10 19:24:40 +0000353 srcaddr.sin_addr = pj_inet_addr(pj_cstr(&s, ADDRESS));
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000354
355 if ((rc=pj_sock_bind(cs, &srcaddr, sizeof(srcaddr))) != 0) {
356 app_perror("...bind error", rc);
357 rc = -121; goto on_error;
358 }
359
360 /* Test send/recv, with sendto */
361 rc = send_recv_test(PJ_SOCK_DGRAM, ss, cs, &dstaddr, NULL,
362 sizeof(dstaddr));
363 if (rc != 0)
364 goto on_error;
365
366 /* Test send/recv, with sendto and recvfrom */
367 rc = send_recv_test(PJ_SOCK_DGRAM, ss, cs, &dstaddr,
368 &srcaddr, sizeof(dstaddr));
369 if (rc != 0)
370 goto on_error;
371
Benny Prijonoaeeb1d12007-05-01 10:42:22 +0000372 /* Disable this test on Symbian since UDP connect()/send() failed
373 * with S60 3rd edition (including MR2).
374 * See http://www.pjsip.org/trac/ticket/264
375 */
376#if !defined(PJ_SYMBIAN) || PJ_SYMBIAN==0
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000377 /* connect() the sockets. */
378 rc = pj_sock_connect(cs, &dstaddr, sizeof(dstaddr));
379 if (rc != 0) {
380 app_perror("...connect() error", rc);
381 rc = -122; goto on_error;
382 }
383
384 /* Test send/recv with send() */
385 rc = send_recv_test(PJ_SOCK_DGRAM, ss, cs, NULL, NULL, 0);
386 if (rc != 0)
387 goto on_error;
388
389 /* Test send/recv with send() and recvfrom */
390 rc = send_recv_test(PJ_SOCK_DGRAM, ss, cs, NULL, &srcaddr,
391 sizeof(srcaddr));
392 if (rc != 0)
393 goto on_error;
Benny Prijonof260e462007-04-30 21:03:32 +0000394#endif
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000395
396on_error:
397 retval = rc;
398 if (cs != PJ_INVALID_SOCKET) {
399 rc = pj_sock_close(cs);
400 if (rc != PJ_SUCCESS) {
401 app_perror("...error in closing socket", rc);
402 return -1000;
403 }
404 }
405 if (ss != PJ_INVALID_SOCKET) {
406 rc = pj_sock_close(ss);
407 if (rc != PJ_SUCCESS) {
408 app_perror("...error in closing socket", rc);
409 return -1010;
410 }
411 }
412
413 return retval;
414}
415
416static int tcp_test(void)
417{
418 pj_sock_t cs, ss;
419 pj_status_t rc = 0, retval;
420
421 PJ_LOG(3,("test", "...tcp_test()"));
422
423 rc = app_socketpair(PJ_AF_INET, PJ_SOCK_STREAM, 0, &ss, &cs);
424 if (rc != PJ_SUCCESS) {
425 app_perror("...error: app_socketpair():", rc);
426 return -2000;
427 }
428
429 /* Test send/recv with send() and recv() */
430 retval = send_recv_test(PJ_SOCK_STREAM, ss, cs, NULL, NULL, 0);
431
432 rc = pj_sock_close(cs);
433 if (rc != PJ_SUCCESS) {
434 app_perror("...error in closing socket", rc);
435 return -2000;
436 }
437
438 rc = pj_sock_close(ss);
439 if (rc != PJ_SUCCESS) {
440 app_perror("...error in closing socket", rc);
441 return -2010;
442 }
443
444 return retval;
445}
446
447static int ioctl_test(void)
448{
449 return 0;
450}
451
Benny Prijono60cac482007-03-01 18:56:02 +0000452static int gethostbyname_test(void)
453{
454 pj_str_t host;
455 pj_hostent he;
456 pj_status_t status;
457
458 /* Testing pj_gethostbyname() with invalid host */
459 host = pj_str("an-invalid-host-name");
460 status = pj_gethostbyname(&host, &he);
461
462 /* Must return failure! */
463 if (status == PJ_SUCCESS)
464 return -20100;
465 else
466 return 0;
467}
468
Benny Prijonof260e462007-04-30 21:03:32 +0000469#if 0
470#include "../pj/os_symbian.h"
471static int connect_test()
472{
473 RSocketServ rSockServ;
474 RSocket rSock;
475 TInetAddr inetAddr;
476 TRequestStatus reqStatus;
477 char buffer[16];
478 TPtrC8 data((const TUint8*)buffer, (TInt)sizeof(buffer));
479 int rc;
480
481 rc = rSockServ.Connect();
482 if (rc != KErrNone)
483 return rc;
484
485 rc = rSock.Open(rSockServ, KAfInet, KSockDatagram, KProtocolInetUdp);
486 if (rc != KErrNone)
487 {
488 rSockServ.Close();
489 return rc;
490 }
491
492 inetAddr.Init(KAfInet);
493 inetAddr.Input(_L("127.0.0.1"));
494 inetAddr.SetPort(80);
495
496 rSock.Connect(inetAddr, reqStatus);
497 User::WaitForRequest(reqStatus);
498
499 if (reqStatus != KErrNone) {
500 rSock.Close();
501 rSockServ.Close();
502 return rc;
503 }
504
505 rSock.Send(data, 0, reqStatus);
506 User::WaitForRequest(reqStatus);
507
508 if (reqStatus!=KErrNone) {
509 rSock.Close();
510 rSockServ.Close();
511 return rc;
512 }
513
514 rSock.Close();
515 rSockServ.Close();
516 return KErrNone;
517}
518#endif
519
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000520int sock_test()
521{
522 int rc;
523
524 pj_create_random_string(bigdata, BIG_DATA_LEN);
525
Benny Prijonof260e462007-04-30 21:03:32 +0000526// Enable this to demonstrate the error witn S60 3rd Edition MR2
527#if 0
528 rc = connect_test();
529 if (rc != 0)
530 return rc;
531#endif
532
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000533 rc = format_test();
534 if (rc != 0)
535 return rc;
536
Benny Prijono60cac482007-03-01 18:56:02 +0000537 rc = gethostbyname_test();
538 if (rc != 0)
539 return rc;
540
Benny Prijono5dcb38d2005-11-21 01:55:47 +0000541 rc = simple_sock_test();
542 if (rc != 0)
543 return rc;
544
545 rc = ioctl_test();
546 if (rc != 0)
547 return rc;
548
549 rc = udp_test();
550 if (rc != 0)
551 return rc;
552
553 rc = tcp_test();
554 if (rc != 0)
555 return rc;
556
557 return 0;
558}
559
560
561#else
562/* To prevent warning about "translation unit is empty"
563 * when this test is disabled.
564 */
565int dummy_sock_test;
566#endif /* INCLUDE_SOCK_TEST */
567