blob: c69b7e25c29956729f85116c99e0929d84844713 [file] [log] [blame]
Benny Prijono0a749f12005-10-31 21:02:30 +00001/* $Header: /pjproject-0.3/pjlib/src/pj/sock_bsd.c 10 10/29/05 11:51a Bennylp $ */
2/* $Log: /pjproject-0.3/pjlib/src/pj/sock_bsd.c $
3 *
4 * 10 10/29/05 11:51a Bennylp
5 * Version 0.3-pre2.
6 *
7 * 9 10/14/05 12:26a Bennylp
8 * Finished error code framework, some fixes in ioqueue, etc. Pretty
9 * major.
10 *
11 * 8 9/21/05 1:39p Bennylp
12 * Periodic checkin for backup.
13 *
14 * 7 9/17/05 10:37a Bennylp
15 * Major reorganization towards version 0.3.
16 *
17 */
18#include <pj/sock.h>
19#include <pj/os.h>
20#include <pj/assert.h>
21#include <pj/string.h>
22#include <pj/compat/socket.h>
23#include <pj/addr_resolv.h>
24#include <pj/errno.h>
25
26/*
27 * Address families conversion.
28 * The values here are indexed based on pj_addr_family-0xFF00.
29 */
30const pj_uint16_t PJ_AF_UNIX = AF_UNIX;
31const pj_uint16_t PJ_AF_INET = AF_INET;
32const pj_uint16_t PJ_AF_INET6 = AF_INET6;
33#ifdef AF_PACKET
34const pj_uint16_t PJ_AF_PACKET = AF_PACKET;
35#else
36const pj_uint16_t PJ_AF_PACKET = 0xFFFF;
37#endif
38#ifdef AF_IRDA
39const pj_uint16_t PJ_AF_IRDA = AF_IRDA;
40#else
41const pj_uint16_t PJ_AF_IRDA = 0xFFFF;
42#endif
43
44/*
45 * Socket types conversion.
46 * The values here are indexed based on pj_sock_type-0xFF00
47 */
48const pj_uint16_t PJ_SOCK_STREAM = SOCK_STREAM;
49const pj_uint16_t PJ_SOCK_DGRAM = SOCK_DGRAM;
50const pj_uint16_t PJ_SOCK_RAW = SOCK_RAW;
51const pj_uint16_t PJ_SOCK_RDM = SOCK_RDM;
52
53/*
54 * Socket level values.
55 */
56const pj_uint16_t PJ_SOL_SOCKET = SOL_SOCKET;
57#ifdef SOL_IP
58const pj_uint16_t PJ_SOL_IP = SOL_IP;
59#else
60const pj_uint16_t PJ_SOL_IP = 0xFFFF;
61#endif /* SOL_IP */
62#if defined(SOL_TCP)
63const pj_uint16_t PJ_SOL_TCP = SOL_TCP;
64#elif defined(IPPROTO_TCP)
65const pj_uint16_t PJ_SOL_TCP = IPPROTO_TCP;
66#endif /* SOL_TCP */
67#ifdef SOL_UDP
68const pj_uint16_t PJ_SOL_UDP = SOL_UDP;
69#else
70const pj_uint16_t PJ_SOL_UDP = 0xFFFF;
71#endif
72#ifdef SOL_IPV6
73const pj_uint16_t PJ_SOL_IPV6 = SOL_IPV6;
74#else
75const pj_uint16_t PJ_SOL_IPV6 = 0xFFFF;
76#endif
77
78
79/*
80 * Convert 16-bit value from network byte order to host byte order.
81 */
82PJ_DEF(pj_uint16_t) pj_ntohs(pj_uint16_t netshort)
83{
84 return ntohs(netshort);
85}
86
87/*
88 * Convert 16-bit value from host byte order to network byte order.
89 */
90PJ_DEF(pj_uint16_t) pj_htons(pj_uint16_t hostshort)
91{
92 return htons(hostshort);
93}
94
95/*
96 * Convert 32-bit value from network byte order to host byte order.
97 */
98PJ_DEF(pj_uint32_t) pj_ntohl(pj_uint32_t netlong)
99{
100 return ntohl(netlong);
101}
102
103/*
104 * Convert 32-bit value from host byte order to network byte order.
105 */
106PJ_DEF(pj_uint32_t) pj_htonl(pj_uint32_t hostlong)
107{
108 return htonl(hostlong);
109}
110
111/*
112 * Convert an Internet host address given in network byte order
113 * to string in standard numbers and dots notation.
114 */
115PJ_DEF(char*) pj_inet_ntoa(pj_in_addr inaddr)
116{
117 return inet_ntoa(*(struct in_addr*)&inaddr);
118}
119
120/*
121 * This function converts the Internet host address cp from the standard
122 * numbers-and-dots notation into binary data and stores it in the structure
123 * that inp points to.
124 */
125PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, struct pj_in_addr *inp)
126{
127 char tempaddr[16];
128
129 /* Initialize output with PJ_INADDR_NONE.
130 * Some apps relies on this instead of the return value
131 * (and anyway the return value is quite confusing!)
132 */
133 inp->s_addr = PJ_INADDR_NONE;
134
135 /* Caution:
136 * this function might be called with cp->slen >= 16
137 * (i.e. when called with hostname to check if it's an IP addr).
138 */
139 PJ_ASSERT_RETURN(cp && cp->slen && inp, 0);
140 if (cp->slen >= 16) {
141 return 0;
142 }
143
144 pj_memcpy(tempaddr, cp->ptr, cp->slen);
145 tempaddr[cp->slen] = '\0';
146
147#if defined(PJ_SOCK_HAS_INET_ATON) && PJ_SOCK_HAS_INET_ATON != 0
148 return inet_aton(tempaddr, (struct in_addr*)inp);
149#else
150 inp->s_addr = inet_addr(tempaddr);
151 return inp->s_addr == PJ_INADDR_NONE ? 0 : 1;
152#endif
153}
154
155/*
156 * Convert address string with numbers and dots to binary IP address.
157 */
158PJ_DEF(pj_in_addr) pj_inet_addr(const pj_str_t *cp)
159{
160 pj_in_addr addr;
161
162 pj_inet_aton(cp, &addr);
163 return addr;
164}
165
166/*
167 * Set the IP address of an IP socket address from string address,
168 * with resolving the host if necessary. The string address may be in a
169 * standard numbers and dots notation or may be a hostname. If hostname
170 * is specified, then the function will resolve the host into the IP
171 * address.
172 */
173PJ_DEF(pj_status_t) pj_sockaddr_in_set_str_addr( pj_sockaddr_in *addr,
174 const pj_str_t *str_addr)
175{
176 PJ_CHECK_STACK();
177
178 PJ_ASSERT_RETURN(str_addr && str_addr->slen < PJ_MAX_HOSTNAME,
179 (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL));
180
181 addr->sin_family = AF_INET;
182
183 if (str_addr && str_addr->slen) {
184 addr->sin_addr = pj_inet_addr(str_addr);
185 if (addr->sin_addr.s_addr == PJ_INADDR_NONE) {
186 pj_hostent he;
187 pj_status_t rc;
188
189 rc = pj_gethostbyname(str_addr, &he);
190 if (rc == 0) {
191 addr->sin_addr.s_addr = *(pj_uint32_t*)he.h_addr;
192 } else {
193 addr->sin_addr.s_addr = PJ_INADDR_NONE;
194 return rc;
195 }
196 }
197
198 } else {
199 addr->sin_addr.s_addr = 0;
200 }
201
202 return PJ_SUCCESS;
203}
204
205/*
206 * Set the IP address and port of an IP socket address.
207 * The string address may be in a standard numbers and dots notation or
208 * may be a hostname. If hostname is specified, then the function will
209 * resolve the host into the IP address.
210 */
211PJ_DEF(pj_status_t) pj_sockaddr_in_init( pj_sockaddr_in *addr,
212 const pj_str_t *str_addr,
213 pj_uint16_t port)
214{
215 PJ_ASSERT_RETURN(addr && str_addr,
216 (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL));
217
218 addr->sin_family = PJ_AF_INET;
219 pj_sockaddr_in_set_port(addr, port);
220 return pj_sockaddr_in_set_str_addr(addr, str_addr);
221}
222
223
224/*
225 * Get hostname.
226 */
227PJ_DEF(const pj_str_t*) pj_gethostname(void)
228{
229 static char buf[PJ_MAX_HOSTNAME];
230 static pj_str_t hostname;
231
232 PJ_CHECK_STACK();
233
234 if (hostname.ptr == NULL) {
235 hostname.ptr = buf;
236 if (gethostname(buf, sizeof(buf)) != 0) {
237 hostname.ptr[0] = '\0';
238 hostname.slen = 0;
239 } else {
240 hostname.slen = strlen(buf);
241 }
242 }
243 return &hostname;
244}
245
246/*
247 * Get first IP address associated with the hostname.
248 */
249PJ_DEF(pj_in_addr) pj_gethostaddr(void)
250{
251 pj_sockaddr_in addr;
252 const pj_str_t *hostname = pj_gethostname();
253
254 pj_sockaddr_in_set_str_addr(&addr, hostname);
255 return addr.sin_addr;
256}
257
258
259#if defined(PJ_WIN32)
260/*
261 * Create new socket/endpoint for communication and returns a descriptor.
262 */
263PJ_DEF(pj_status_t) pj_sock_socket(int af,
264 int type,
265 int proto,
266 pj_sock_t *sock)
267{
268 PJ_CHECK_STACK();
269
270 /* Sanity checks. */
271 PJ_ASSERT_RETURN(sock!=NULL, PJ_EINVAL);
272 PJ_ASSERT_RETURN((unsigned)PJ_INVALID_SOCKET==INVALID_SOCKET,
273 (*sock=PJ_INVALID_SOCKET, PJ_EINVAL));
274
275 *sock = WSASocket(af, type, proto, NULL, 0, WSA_FLAG_OVERLAPPED);
276
277 if (*sock == PJ_INVALID_SOCKET)
278 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
279 else
280 return PJ_SUCCESS;
281}
282
283#else
284/*
285 * Create new socket/endpoint for communication and returns a descriptor.
286 */
287PJ_DEF(pj_status_t) pj_sock_socket(int af,
288 int type,
289 int proto,
290 pj_sock_t *sock)
291{
292
293 PJ_CHECK_STACK();
294
295 /* Sanity checks. */
296 PJ_ASSERT_RETURN(sock!=NULL, PJ_EINVAL);
297 PJ_ASSERT_RETURN(PJ_INVALID_SOCKET==-1,
298 (*sock=PJ_INVALID_SOCKET, PJ_EINVAL));
299
300 *sock = socket(af, type, proto);
301 if (*sock == PJ_INVALID_SOCKET)
302 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
303 else
304 return PJ_SUCCESS;
305}
306#endif
307
308
309/*
310 * Bind socket.
311 */
312PJ_DEF(pj_status_t) pj_sock_bind( pj_sock_t sock,
313 const pj_sockaddr_t *addr,
314 int len)
315{
316 PJ_CHECK_STACK();
317
318 PJ_ASSERT_RETURN(addr && len > 0, PJ_EINVAL);
319
320 if (bind(sock, (struct sockaddr*)addr, len) != 0)
321 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
322 else
323 return PJ_SUCCESS;
324}
325
326
327/*
328 * Bind socket.
329 */
330PJ_DEF(pj_status_t) pj_sock_bind_in( pj_sock_t sock,
331 pj_uint32_t addr32,
332 pj_uint16_t port)
333{
334 pj_sockaddr_in addr;
335
336 PJ_CHECK_STACK();
337
338 addr.sin_family = PJ_AF_INET;
339 addr.sin_addr.s_addr = pj_htonl(addr32);
340 addr.sin_port = pj_htons(port);
341
342 return pj_sock_bind(sock, &addr, sizeof(pj_sockaddr_in));
343}
344
345
346/*
347 * Close socket.
348 */
349PJ_DEF(pj_status_t) pj_sock_close(pj_sock_t sock)
350{
351 int rc;
352
353 PJ_CHECK_STACK();
354#if defined(PJ_WIN32) && PJ_WIN32==1
355 rc = closesocket(sock);
356#else
357 rc = close(sock);
358#endif
359
360 if (rc != 0)
361 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
362 else
363 return PJ_SUCCESS;
364}
365
366/*
367 * Get remote's name.
368 */
369PJ_DEF(pj_status_t) pj_sock_getpeername( pj_sock_t sock,
370 pj_sockaddr_t *addr,
371 int *namelen)
372{
373 PJ_CHECK_STACK();
374 if (getpeername(sock, (struct sockaddr*)addr, (socklen_t*)namelen) != 0)
375 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
376 else
377 return PJ_SUCCESS;
378}
379
380/*
381 * Get socket name.
382 */
383PJ_DEF(pj_status_t) pj_sock_getsockname( pj_sock_t sock,
384 pj_sockaddr_t *addr,
385 int *namelen)
386{
387 PJ_CHECK_STACK();
388 if (getsockname(sock, (struct sockaddr*)addr, (socklen_t*)namelen) != 0)
389 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
390 else
391 return PJ_SUCCESS;
392}
393
394/*
395 * Send data
396 */
397PJ_DEF(pj_status_t) pj_sock_send(pj_sock_t sock,
398 const void *buf,
399 pj_ssize_t *len,
400 unsigned flags)
401{
402 PJ_CHECK_STACK();
403 PJ_ASSERT_RETURN(len, PJ_EINVAL);
404
405 *len = send(sock, (const char*)buf, *len, flags);
406
407 if (*len < 0)
408 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
409 else
410 return PJ_SUCCESS;
411}
412
413
414/*
415 * Send data.
416 */
417PJ_DEF(pj_status_t) pj_sock_sendto(pj_sock_t sock,
418 const void *buf,
419 pj_ssize_t *len,
420 unsigned flags,
421 const pj_sockaddr_t *to,
422 int tolen)
423{
424 PJ_CHECK_STACK();
425 PJ_ASSERT_RETURN(len, PJ_EINVAL);
426
427 *len = sendto(sock, (const char*)buf, *len, flags,
428 (const struct sockaddr*)to, tolen);
429
430 if (*len < 0)
431 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
432 else
433 return PJ_SUCCESS;
434}
435
436/*
437 * Receive data.
438 */
439PJ_DEF(pj_status_t) pj_sock_recv(pj_sock_t sock,
440 void *buf,
441 pj_ssize_t *len,
442 unsigned flags)
443{
444 PJ_CHECK_STACK();
445 PJ_ASSERT_RETURN(buf && len, PJ_EINVAL);
446
447 *len = recv(sock, (char*)buf, *len, flags);
448
449 if (*len < 0)
450 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
451 else
452 return PJ_SUCCESS;
453}
454
455/*
456 * Receive data.
457 */
458PJ_DEF(pj_status_t) pj_sock_recvfrom(pj_sock_t sock,
459 void *buf,
460 pj_ssize_t *len,
461 unsigned flags,
462 pj_sockaddr_t *from,
463 int *fromlen)
464{
465 PJ_CHECK_STACK();
466 PJ_ASSERT_RETURN(buf && len, PJ_EINVAL);
467 PJ_ASSERT_RETURN(from && fromlen, (*len=-1, PJ_EINVAL));
468
469 *len = recvfrom(sock, (char*)buf, *len, flags,
470 (struct sockaddr*)from, (socklen_t*)fromlen);
471
472 if (*len < 0)
473 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
474 else
475 return PJ_SUCCESS;
476}
477
478/*
479 * Get socket option.
480 */
481PJ_DEF(pj_status_t) pj_sock_getsockopt( pj_sock_t sock,
482 int level,
483 int optname,
484 void *optval,
485 int *optlen)
486{
487 PJ_CHECK_STACK();
488 PJ_ASSERT_RETURN(optval && optlen, PJ_EINVAL);
489
490 if (getsockopt(sock, level, optname, (char*)optval, (socklen_t*)optlen)!=0)
491 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
492 else
493 return PJ_SUCCESS;
494}
495
496/*
497 * Set socket option.
498 */
499PJ_DEF(pj_status_t) pj_sock_setsockopt( pj_sock_t sock,
500 int level,
501 int optname,
502 const void *optval,
503 int optlen)
504{
505 PJ_CHECK_STACK();
506 if (setsockopt(sock, level, optname, (const char*)optval, optlen) != 0)
507 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
508 else
509 return PJ_SUCCESS;
510}
511
512/*
513 * Shutdown socket.
514 */
515#if PJ_HAS_TCP
516PJ_DEF(pj_status_t) pj_sock_shutdown( pj_sock_t sock,
517 int how)
518{
519 PJ_CHECK_STACK();
520 if (shutdown(sock, how) != 0)
521 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
522 else
523 return PJ_SUCCESS;
524}
525
526/*
527 * Start listening to incoming connections.
528 */
529PJ_DEF(pj_status_t) pj_sock_listen( pj_sock_t sock,
530 int backlog)
531{
532 PJ_CHECK_STACK();
533 if (listen(sock, backlog) != 0)
534 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
535 else
536 return PJ_SUCCESS;
537}
538
539/*
540 * Connect socket.
541 */
542PJ_DEF(pj_status_t) pj_sock_connect( pj_sock_t sock,
543 const pj_sockaddr_t *addr,
544 int namelen)
545{
546 PJ_CHECK_STACK();
547 if (connect(sock, (struct sockaddr*)addr, namelen) != 0)
548 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
549 else
550 return PJ_SUCCESS;
551}
552
553/*
554 * Accept incoming connections
555 */
556PJ_DEF(pj_status_t) pj_sock_accept( pj_sock_t serverfd,
557 pj_sock_t *newsock,
558 pj_sockaddr_t *addr,
559 int *addrlen)
560{
561 PJ_CHECK_STACK();
562 PJ_ASSERT_RETURN(newsock != NULL, PJ_EINVAL);
563
564 *newsock = accept(serverfd, (struct sockaddr*)addr, (socklen_t*)addrlen);
565 if (*newsock==PJ_INVALID_SOCKET)
566 return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
567 else
568 return PJ_SUCCESS;
569}
570#endif /* PJ_HAS_TCP */
571
572