blob: 3e393359cab8c87e2771085c55c8341c722416b0 [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
Benny Prijonoa771a512007-02-19 01:13:53 +00003 * Copyright (C)2003-2007 Benny Prijono <benny@prijono.org>
Benny Prijono9033e312005-11-21 02:08:39 +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 <pj/sock.h>
20#include <pj/os.h>
21#include <pj/assert.h>
22#include <pj/string.h>
23#include <pj/compat/socket.h>
24#include <pj/addr_resolv.h>
25#include <pj/errno.h>
26
27/*
28 * Address families conversion.
Benny Prijono42c5b9e2006-05-10 19:24:40 +000029 * The values here are indexed based on pj_addr_family.
Benny Prijono9033e312005-11-21 02:08:39 +000030 */
31const pj_uint16_t PJ_AF_UNIX = AF_UNIX;
32const pj_uint16_t PJ_AF_INET = AF_INET;
33const pj_uint16_t PJ_AF_INET6 = AF_INET6;
34#ifdef AF_PACKET
35const pj_uint16_t PJ_AF_PACKET = AF_PACKET;
36#else
37const pj_uint16_t PJ_AF_PACKET = 0xFFFF;
38#endif
39#ifdef AF_IRDA
40const pj_uint16_t PJ_AF_IRDA = AF_IRDA;
41#else
42const pj_uint16_t PJ_AF_IRDA = 0xFFFF;
43#endif
44
45/*
46 * Socket types conversion.
Benny Prijono42c5b9e2006-05-10 19:24:40 +000047 * The values here are indexed based on pj_sock_type
Benny Prijono9033e312005-11-21 02:08:39 +000048 */
Benny Prijono87a00892007-02-01 00:33:12 +000049const pj_uint16_t PJ_SOCK_STREAM= SOCK_STREAM;
Benny Prijono9033e312005-11-21 02:08:39 +000050const pj_uint16_t PJ_SOCK_DGRAM = SOCK_DGRAM;
51const pj_uint16_t PJ_SOCK_RAW = SOCK_RAW;
52const pj_uint16_t PJ_SOCK_RDM = SOCK_RDM;
53
54/*
55 * Socket level values.
56 */
57const pj_uint16_t PJ_SOL_SOCKET = SOL_SOCKET;
58#ifdef SOL_IP
59const pj_uint16_t PJ_SOL_IP = SOL_IP;
60#else
61const pj_uint16_t PJ_SOL_IP = 0xFFFF;
62#endif /* SOL_IP */
63#if defined(SOL_TCP)
64const pj_uint16_t PJ_SOL_TCP = SOL_TCP;
65#elif defined(IPPROTO_TCP)
66const pj_uint16_t PJ_SOL_TCP = IPPROTO_TCP;
67#endif /* SOL_TCP */
68#ifdef SOL_UDP
69const pj_uint16_t PJ_SOL_UDP = SOL_UDP;
70#else
71const pj_uint16_t PJ_SOL_UDP = 0xFFFF;
72#endif
73#ifdef SOL_IPV6
74const pj_uint16_t PJ_SOL_IPV6 = SOL_IPV6;
75#else
76const pj_uint16_t PJ_SOL_IPV6 = 0xFFFF;
77#endif
78
Benny Prijono87a00892007-02-01 00:33:12 +000079/* IP_TOS */
80#ifdef IP_TOS
81const pj_uint16_t PJ_IP_TOS = IP_TOS;
82#else
83const pj_uint16_t PJ_IP_TOS = 1;
84#endif
85
86
87/* TOS settings (declared in netinet/ip.h) */
88#ifdef IPTOS_LOWDELAY
89const pj_uint16_t PJ_IPTOS_LOWDELAY = IPTOS_LOWDELAY;
90#else
91const pj_uint16_t PJ_IPTOS_LOWDELAY = 0x10;
92#endif
93#ifdef IPTOS_THROUGHPUT
94const pj_uint16_t PJ_IPTOS_THROUGHPUT = IPTOS_THROUGHPUT;
95#else
96const pj_uint16_t PJ_IPTOS_THROUGHPUT = 0x08;
97#endif
98#ifdef IPTOS_RELIABILITY
99const pj_uint16_t PJ_IPTOS_RELIABILITY = IPTOS_RELIABILITY;
100#else
101const pj_uint16_t PJ_IPTOS_RELIABILITY = 0x04;
102#endif
103#ifdef IPTOS_MINCOST
104const pj_uint16_t PJ_IPTOS_MINCOST = IPTOS_MINCOST;
105#else
106const pj_uint16_t PJ_IPTOS_MINCOST = 0x02;
107#endif
108
109
Benny Prijono9033e312005-11-21 02:08:39 +0000110/* optname values. */
111const pj_uint16_t PJ_SO_TYPE = SO_TYPE;
112const pj_uint16_t PJ_SO_RCVBUF = SO_RCVBUF;
113const pj_uint16_t PJ_SO_SNDBUF = SO_SNDBUF;
114
115
Benny Prijono57dc48b2006-12-25 06:39:33 +0000116/* recv() and send() flags */
117const int PJ_MSG_OOB = MSG_OOB;
118const int PJ_MSG_PEEK = MSG_PEEK;
119const int PJ_MSG_DONTROUTE = MSG_DONTROUTE;
120
121
Benny Prijonoe67d99a2006-03-20 12:39:24 +0000122#if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0
123# define SET_LEN(addr,len) (((pj_sockaddr*)(addr))->sa_zero_len=(len))
124# define RESET_LEN(addr) (((pj_sockaddr*)(addr))->sa_zero_len=0)
125#else
126# define SET_LEN(addr,len)
127# define RESET_LEN(addr)
128#endif
129
130
Benny Prijono9033e312005-11-21 02:08:39 +0000131/*
132 * Convert 16-bit value from network byte order to host byte order.
133 */
134PJ_DEF(pj_uint16_t) pj_ntohs(pj_uint16_t netshort)
135{
136 return ntohs(netshort);
137}
138
139/*
140 * Convert 16-bit value from host byte order to network byte order.
141 */
142PJ_DEF(pj_uint16_t) pj_htons(pj_uint16_t hostshort)
143{
144 return htons(hostshort);
145}
146
147/*
148 * Convert 32-bit value from network byte order to host byte order.
149 */
150PJ_DEF(pj_uint32_t) pj_ntohl(pj_uint32_t netlong)
151{
152 return ntohl(netlong);
153}
154
155/*
156 * Convert 32-bit value from host byte order to network byte order.
157 */
158PJ_DEF(pj_uint32_t) pj_htonl(pj_uint32_t hostlong)
159{
160 return htonl(hostlong);
161}
162
163/*
164 * Convert an Internet host address given in network byte order
165 * to string in standard numbers and dots notation.
166 */
167PJ_DEF(char*) pj_inet_ntoa(pj_in_addr inaddr)
168{
169#if !defined(PJ_LINUX) && !defined(PJ_LINUX_KERNEL)
170 return inet_ntoa(*(struct in_addr*)&inaddr);
171#else
172 struct in_addr addr;
173 addr.s_addr = inaddr.s_addr;
174 return inet_ntoa(addr);
175#endif
176}
177
178/*
179 * This function converts the Internet host address cp from the standard
180 * numbers-and-dots notation into binary data and stores it in the structure
181 * that inp points to.
182 */
183PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, struct pj_in_addr *inp)
184{
185 char tempaddr[16];
186
187 /* Initialize output with PJ_INADDR_NONE.
188 * Some apps relies on this instead of the return value
189 * (and anyway the return value is quite confusing!)
190 */
191 inp->s_addr = PJ_INADDR_NONE;
192
193 /* Caution:
194 * this function might be called with cp->slen >= 16
195 * (i.e. when called with hostname to check if it's an IP addr).
196 */
197 PJ_ASSERT_RETURN(cp && cp->slen && inp, 0);
198 if (cp->slen >= 16) {
199 return 0;
200 }
201
202 pj_memcpy(tempaddr, cp->ptr, cp->slen);
203 tempaddr[cp->slen] = '\0';
204
205#if defined(PJ_SOCK_HAS_INET_ATON) && PJ_SOCK_HAS_INET_ATON != 0
206 return inet_aton(tempaddr, (struct in_addr*)inp);
207#else
208 inp->s_addr = inet_addr(tempaddr);
209 return inp->s_addr == PJ_INADDR_NONE ? 0 : 1;
210#endif
211}
212
213/*
214 * Convert address string with numbers and dots to binary IP address.
215 */
216PJ_DEF(pj_in_addr) pj_inet_addr(const pj_str_t *cp)
217{
218 pj_in_addr addr;
219
220 pj_inet_aton(cp, &addr);
221 return addr;
222}
223
224/*
Benny Prijono7a4cf152006-03-22 11:48:33 +0000225 * Convert address string with numbers and dots to binary IP address.
226 */
227PJ_DEF(pj_in_addr) pj_inet_addr2(const char *cp)
228{
229 pj_str_t str = pj_str((char*)cp);
230 return pj_inet_addr(&str);
231}
232
233/*
Benny Prijono9033e312005-11-21 02:08:39 +0000234 * Set the IP address of an IP socket address from string address,
235 * with resolving the host if necessary. The string address may be in a
236 * standard numbers and dots notation or may be a hostname. If hostname
237 * is specified, then the function will resolve the host into the IP
238 * address.
239 */
240PJ_DEF(pj_status_t) pj_sockaddr_in_set_str_addr( pj_sockaddr_in *addr,
241 const pj_str_t *str_addr)
242{
243 PJ_CHECK_STACK();
244
Benny Prijono0ca04b62005-12-30 23:50:15 +0000245 PJ_ASSERT_RETURN(!str_addr || str_addr->slen < PJ_MAX_HOSTNAME,
Benny Prijono9033e312005-11-21 02:08:39 +0000246 (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL));
247
Benny Prijonoe67d99a2006-03-20 12:39:24 +0000248 RESET_LEN(addr);
Benny Prijono9033e312005-11-21 02:08:39 +0000249 addr->sin_family = AF_INET;
Benny Prijonoac623b32006-07-03 15:19:31 +0000250 pj_bzero(addr->sin_zero, sizeof(addr->sin_zero));
Benny Prijono9033e312005-11-21 02:08:39 +0000251
252 if (str_addr && str_addr->slen) {
253 addr->sin_addr = pj_inet_addr(str_addr);
254 if (addr->sin_addr.s_addr == PJ_INADDR_NONE) {
255 pj_hostent he;
256 pj_status_t rc;
257
258 rc = pj_gethostbyname(str_addr, &he);
259 if (rc == 0) {
260 addr->sin_addr.s_addr = *(pj_uint32_t*)he.h_addr;
261 } else {
262 addr->sin_addr.s_addr = PJ_INADDR_NONE;
263 return rc;
264 }
265 }
266
267 } else {
268 addr->sin_addr.s_addr = 0;
269 }
270
271 return PJ_SUCCESS;
272}
273
274/*
275 * Set the IP address and port of an IP socket address.
276 * The string address may be in a standard numbers and dots notation or
277 * may be a hostname. If hostname is specified, then the function will
278 * resolve the host into the IP address.
279 */
280PJ_DEF(pj_status_t) pj_sockaddr_in_init( pj_sockaddr_in *addr,
281 const pj_str_t *str_addr,
282 pj_uint16_t port)
283{
Benny Prijono0ca04b62005-12-30 23:50:15 +0000284 PJ_ASSERT_RETURN(addr, (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL));
Benny Prijono9033e312005-11-21 02:08:39 +0000285
Benny Prijonoe67d99a2006-03-20 12:39:24 +0000286 RESET_LEN(addr);
Benny Prijono9033e312005-11-21 02:08:39 +0000287 addr->sin_family = PJ_AF_INET;
Benny Prijonoac623b32006-07-03 15:19:31 +0000288 pj_bzero(addr->sin_zero, sizeof(addr->sin_zero));
Benny Prijono9033e312005-11-21 02:08:39 +0000289 pj_sockaddr_in_set_port(addr, port);
290 return pj_sockaddr_in_set_str_addr(addr, str_addr);
291}
292
293
294/*
295 * Get hostname.
296 */
297PJ_DEF(const pj_str_t*) pj_gethostname(void)
298{
299 static char buf[PJ_MAX_HOSTNAME];
300 static pj_str_t hostname;
301
302 PJ_CHECK_STACK();
303
304 if (hostname.ptr == NULL) {
305 hostname.ptr = buf;
306 if (gethostname(buf, sizeof(buf)) != 0) {
307 hostname.ptr[0] = '\0';
308 hostname.slen = 0;
309 } else {
310 hostname.slen = strlen(buf);
311 }
312 }
313 return &hostname;
314}
315
316/*
317 * Get first IP address associated with the hostname.
318 */
319PJ_DEF(pj_in_addr) pj_gethostaddr(void)
320{
321 pj_sockaddr_in addr;
322 const pj_str_t *hostname = pj_gethostname();
323
324 pj_sockaddr_in_set_str_addr(&addr, hostname);
325 return addr.sin_addr;
326}
327
328
329#if defined(PJ_WIN32)
330/*
331 * Create new socket/endpoint for communication and returns a descriptor.
332 */
333PJ_DEF(pj_status_t) pj_sock_socket(int af,
334 int type,
335 int proto,
336 pj_sock_t *sock)
337{
338 PJ_CHECK_STACK();
339
340 /* Sanity checks. */
341 PJ_ASSERT_RETURN(sock!=NULL, PJ_EINVAL);
342 PJ_ASSERT_RETURN((unsigned)PJ_INVALID_SOCKET==INVALID_SOCKET,
343 (*sock=PJ_INVALID_SOCKET, PJ_EINVAL));
344
345 *sock = WSASocket(af, type, proto, NULL, 0, WSA_FLAG_OVERLAPPED);
346
347 if (*sock == PJ_INVALID_SOCKET)
348 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
349 else
350 return PJ_SUCCESS;
351}
352
353#else
354/*
355 * Create new socket/endpoint for communication and returns a descriptor.
356 */
357PJ_DEF(pj_status_t) pj_sock_socket(int af,
358 int type,
359 int proto,
360 pj_sock_t *sock)
361{
362
363 PJ_CHECK_STACK();
364
365 /* Sanity checks. */
366 PJ_ASSERT_RETURN(sock!=NULL, PJ_EINVAL);
367 PJ_ASSERT_RETURN(PJ_INVALID_SOCKET==-1,
368 (*sock=PJ_INVALID_SOCKET, PJ_EINVAL));
369
370 *sock = socket(af, type, proto);
371 if (*sock == PJ_INVALID_SOCKET)
372 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
373 else
374 return PJ_SUCCESS;
375}
376#endif
377
378
379/*
380 * Bind socket.
381 */
382PJ_DEF(pj_status_t) pj_sock_bind( pj_sock_t sock,
383 const pj_sockaddr_t *addr,
384 int len)
385{
386 PJ_CHECK_STACK();
387
Benny Prijonoa1e69682007-05-11 15:14:34 +0000388 PJ_ASSERT_RETURN(addr && len >= (int)sizeof(struct sockaddr_in), PJ_EINVAL);
Benny Prijono9033e312005-11-21 02:08:39 +0000389
390 if (bind(sock, (struct sockaddr*)addr, len) != 0)
391 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
392 else
393 return PJ_SUCCESS;
394}
395
396
397/*
398 * Bind socket.
399 */
400PJ_DEF(pj_status_t) pj_sock_bind_in( pj_sock_t sock,
401 pj_uint32_t addr32,
402 pj_uint16_t port)
403{
404 pj_sockaddr_in addr;
405
406 PJ_CHECK_STACK();
407
Benny Prijonoe67d99a2006-03-20 12:39:24 +0000408 SET_LEN(&addr, sizeof(pj_sockaddr_in));
Benny Prijono9033e312005-11-21 02:08:39 +0000409 addr.sin_family = PJ_AF_INET;
Benny Prijonoac623b32006-07-03 15:19:31 +0000410 pj_bzero(addr.sin_zero, sizeof(addr.sin_zero));
Benny Prijono9033e312005-11-21 02:08:39 +0000411 addr.sin_addr.s_addr = pj_htonl(addr32);
412 addr.sin_port = pj_htons(port);
413
414 return pj_sock_bind(sock, &addr, sizeof(pj_sockaddr_in));
415}
416
417
418/*
419 * Close socket.
420 */
421PJ_DEF(pj_status_t) pj_sock_close(pj_sock_t sock)
422{
423 int rc;
424
425 PJ_CHECK_STACK();
Benny Prijono9cf138e2006-01-19 03:58:29 +0000426#if defined(PJ_WIN32) && PJ_WIN32!=0 || \
427 defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0
Benny Prijono9033e312005-11-21 02:08:39 +0000428 rc = closesocket(sock);
429#else
430 rc = close(sock);
431#endif
432
433 if (rc != 0)
434 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
435 else
436 return PJ_SUCCESS;
437}
438
439/*
440 * Get remote's name.
441 */
442PJ_DEF(pj_status_t) pj_sock_getpeername( pj_sock_t sock,
443 pj_sockaddr_t *addr,
444 int *namelen)
445{
446 PJ_CHECK_STACK();
447 if (getpeername(sock, (struct sockaddr*)addr, (socklen_t*)namelen) != 0)
448 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
Benny Prijonoe67d99a2006-03-20 12:39:24 +0000449 else {
450 RESET_LEN(addr);
Benny Prijono9033e312005-11-21 02:08:39 +0000451 return PJ_SUCCESS;
Benny Prijonoe67d99a2006-03-20 12:39:24 +0000452 }
Benny Prijono9033e312005-11-21 02:08:39 +0000453}
454
455/*
456 * Get socket name.
457 */
458PJ_DEF(pj_status_t) pj_sock_getsockname( pj_sock_t sock,
459 pj_sockaddr_t *addr,
460 int *namelen)
461{
462 PJ_CHECK_STACK();
463 if (getsockname(sock, (struct sockaddr*)addr, (socklen_t*)namelen) != 0)
464 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
Benny Prijonoe67d99a2006-03-20 12:39:24 +0000465 else {
466 RESET_LEN(addr);
Benny Prijono9033e312005-11-21 02:08:39 +0000467 return PJ_SUCCESS;
Benny Prijonoe67d99a2006-03-20 12:39:24 +0000468 }
Benny Prijono9033e312005-11-21 02:08:39 +0000469}
470
471/*
472 * Send data
473 */
474PJ_DEF(pj_status_t) pj_sock_send(pj_sock_t sock,
475 const void *buf,
476 pj_ssize_t *len,
477 unsigned flags)
478{
479 PJ_CHECK_STACK();
480 PJ_ASSERT_RETURN(len, PJ_EINVAL);
481
482 *len = send(sock, (const char*)buf, *len, flags);
483
484 if (*len < 0)
485 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
486 else
487 return PJ_SUCCESS;
488}
489
490
491/*
492 * Send data.
493 */
494PJ_DEF(pj_status_t) pj_sock_sendto(pj_sock_t sock,
495 const void *buf,
496 pj_ssize_t *len,
497 unsigned flags,
498 const pj_sockaddr_t *to,
499 int tolen)
500{
501 PJ_CHECK_STACK();
502 PJ_ASSERT_RETURN(len, PJ_EINVAL);
503
504 *len = sendto(sock, (const char*)buf, *len, flags,
505 (const struct sockaddr*)to, tolen);
506
507 if (*len < 0)
508 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
509 else
510 return PJ_SUCCESS;
511}
512
513/*
514 * Receive data.
515 */
516PJ_DEF(pj_status_t) pj_sock_recv(pj_sock_t sock,
517 void *buf,
518 pj_ssize_t *len,
519 unsigned flags)
520{
521 PJ_CHECK_STACK();
522 PJ_ASSERT_RETURN(buf && len, PJ_EINVAL);
523
524 *len = recv(sock, (char*)buf, *len, flags);
525
526 if (*len < 0)
527 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
528 else
529 return PJ_SUCCESS;
530}
531
532/*
533 * Receive data.
534 */
535PJ_DEF(pj_status_t) pj_sock_recvfrom(pj_sock_t sock,
536 void *buf,
537 pj_ssize_t *len,
538 unsigned flags,
539 pj_sockaddr_t *from,
540 int *fromlen)
541{
542 PJ_CHECK_STACK();
543 PJ_ASSERT_RETURN(buf && len, PJ_EINVAL);
544 PJ_ASSERT_RETURN(from && fromlen, (*len=-1, PJ_EINVAL));
545
546 *len = recvfrom(sock, (char*)buf, *len, flags,
547 (struct sockaddr*)from, (socklen_t*)fromlen);
548
549 if (*len < 0)
550 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
Benny Prijonoe67d99a2006-03-20 12:39:24 +0000551 else {
552 RESET_LEN(from);
Benny Prijono9033e312005-11-21 02:08:39 +0000553 return PJ_SUCCESS;
Benny Prijonoe67d99a2006-03-20 12:39:24 +0000554 }
Benny Prijono9033e312005-11-21 02:08:39 +0000555}
556
557/*
558 * Get socket option.
559 */
560PJ_DEF(pj_status_t) pj_sock_getsockopt( pj_sock_t sock,
561 pj_uint16_t level,
562 pj_uint16_t optname,
563 void *optval,
564 int *optlen)
565{
566 PJ_CHECK_STACK();
567 PJ_ASSERT_RETURN(optval && optlen, PJ_EINVAL);
568
569 if (getsockopt(sock, level, optname, (char*)optval, (socklen_t*)optlen)!=0)
570 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
571 else
572 return PJ_SUCCESS;
573}
574
575/*
576 * Set socket option.
577 */
578PJ_DEF(pj_status_t) pj_sock_setsockopt( pj_sock_t sock,
579 pj_uint16_t level,
580 pj_uint16_t optname,
581 const void *optval,
582 int optlen)
583{
584 PJ_CHECK_STACK();
585 if (setsockopt(sock, level, optname, (const char*)optval, optlen) != 0)
586 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
587 else
588 return PJ_SUCCESS;
589}
590
591/*
Benny Prijono3d327302006-02-08 11:14:03 +0000592 * Connect socket.
593 */
594PJ_DEF(pj_status_t) pj_sock_connect( pj_sock_t sock,
595 const pj_sockaddr_t *addr,
596 int namelen)
597{
598 PJ_CHECK_STACK();
599 if (connect(sock, (struct sockaddr*)addr, namelen) != 0)
600 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
601 else
602 return PJ_SUCCESS;
603}
604
605
606/*
Benny Prijono9033e312005-11-21 02:08:39 +0000607 * Shutdown socket.
608 */
609#if PJ_HAS_TCP
610PJ_DEF(pj_status_t) pj_sock_shutdown( pj_sock_t sock,
611 int how)
612{
613 PJ_CHECK_STACK();
614 if (shutdown(sock, how) != 0)
615 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
616 else
617 return PJ_SUCCESS;
618}
619
620/*
621 * Start listening to incoming connections.
622 */
623PJ_DEF(pj_status_t) pj_sock_listen( pj_sock_t sock,
624 int backlog)
625{
626 PJ_CHECK_STACK();
627 if (listen(sock, backlog) != 0)
628 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
629 else
630 return PJ_SUCCESS;
631}
632
633/*
Benny Prijono9033e312005-11-21 02:08:39 +0000634 * Accept incoming connections
635 */
636PJ_DEF(pj_status_t) pj_sock_accept( pj_sock_t serverfd,
637 pj_sock_t *newsock,
638 pj_sockaddr_t *addr,
639 int *addrlen)
640{
641 PJ_CHECK_STACK();
642 PJ_ASSERT_RETURN(newsock != NULL, PJ_EINVAL);
643
Benny Prijonoe67d99a2006-03-20 12:39:24 +0000644#if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0
645 if (addr) {
646 SET_LEN(addr, *addrlen);
647 }
648#endif
649
Benny Prijono9033e312005-11-21 02:08:39 +0000650 *newsock = accept(serverfd, (struct sockaddr*)addr, (socklen_t*)addrlen);
651 if (*newsock==PJ_INVALID_SOCKET)
652 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
Benny Prijonoe67d99a2006-03-20 12:39:24 +0000653 else {
654
655#if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0
656 if (addr) {
657 RESET_LEN(addr);
658 }
659#endif
660
Benny Prijono9033e312005-11-21 02:08:39 +0000661 return PJ_SUCCESS;
Benny Prijonoe67d99a2006-03-20 12:39:24 +0000662 }
Benny Prijono9033e312005-11-21 02:08:39 +0000663}
664#endif /* PJ_HAS_TCP */
665
666