*** empty log message ***
[bpt/guile.git] / libguile / socket.c
CommitLineData
09270afd 1/* Copyright (C) 1996,1997,1998,2000,2001, 2002, 2003, 2004 Free Software Foundation, Inc.
86667910 2 *
73be1d9e
MV
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
86667910 7 *
73be1d9e
MV
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
86667910 12 *
73be1d9e
MV
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
1bbd0b84 17
1bbd0b84 18
0f2d19dd
JB
19\f
20
eccde741
RB
21#if HAVE_CONFIG_H
22# include <config.h>
23#endif
24
e6e2e95a 25#include <errno.h>
69d49ac8 26#include <gmp.h>
e6e2e95a 27
a0599745
MD
28#include "libguile/_scm.h"
29#include "libguile/unif.h"
30#include "libguile/feature.h"
31#include "libguile/fports.h"
32#include "libguile/strings.h"
33#include "libguile/vectors.h"
20e6290e 34
a0599745
MD
35#include "libguile/validate.h"
36#include "libguile/socket.h"
95b88819 37
b4e15479
SJ
38#ifdef __MINGW32__
39#include "win32-socket.h"
40#endif
41
af68e5e5
SJ
42#ifdef HAVE_STDINT_H
43#include <stdint.h>
44#endif
95b88819
GH
45#ifdef HAVE_STRING_H
46#include <string.h>
47#endif
370312ae
GH
48#ifdef HAVE_UNISTD_H
49#include <unistd.h>
50#endif
0f2d19dd 51#include <sys/types.h>
f87c105a 52#ifdef HAVE_WINSOCK2_H
82893676
MG
53#include <winsock2.h>
54#else
0f2d19dd 55#include <sys/socket.h>
1ba8c23a 56#ifdef HAVE_UNIX_DOMAIN_SOCKETS
0f2d19dd 57#include <sys/un.h>
0e958795 58#endif
0f2d19dd
JB
59#include <netinet/in.h>
60#include <netdb.h>
61#include <arpa/inet.h>
82893676 62#endif
0f2d19dd 63
97d0e20b
GH
64#if defined (HAVE_UNIX_DOMAIN_SOCKETS) && !defined (SUN_LEN)
65#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
66 + strlen ((ptr)->sun_path))
67#endif
68
439006bf
GH
69/* we are not currently using socklen_t. it's not defined on all systems,
70 so would need to be checked by configure. in the meantime, plain
71 int is the best alternative. */
72
0f2d19dd
JB
73\f
74
a1ec6916 75SCM_DEFINE (scm_htons, "htons", 1, 0, 0,
eefae538
GH
76 (SCM value),
77 "Convert a 16 bit quantity from host to network byte ordering.\n"
78 "@var{value} is packed into 2 bytes, which are then converted\n"
79 "and returned as a new integer.")
1bbd0b84 80#define FUNC_NAME s_scm_htons
5c11cc9d 81{
7cee5b31 82 return scm_from_ushort (htons (scm_to_ushort (value)));
5c11cc9d 83}
1bbd0b84 84#undef FUNC_NAME
5c11cc9d 85
a1ec6916 86SCM_DEFINE (scm_ntohs, "ntohs", 1, 0, 0,
eefae538
GH
87 (SCM value),
88 "Convert a 16 bit quantity from network to host byte ordering.\n"
89 "@var{value} is packed into 2 bytes, which are then converted\n"
90 "and returned as a new integer.")
1bbd0b84 91#define FUNC_NAME s_scm_ntohs
5c11cc9d 92{
7cee5b31 93 return scm_from_ushort (ntohs (scm_to_ushort (value)));
5c11cc9d 94}
1bbd0b84 95#undef FUNC_NAME
5c11cc9d 96
a1ec6916 97SCM_DEFINE (scm_htonl, "htonl", 1, 0, 0,
eefae538
GH
98 (SCM value),
99 "Convert a 32 bit quantity from host to network byte ordering.\n"
100 "@var{value} is packed into 4 bytes, which are then converted\n"
101 "and returned as a new integer.")
1bbd0b84 102#define FUNC_NAME s_scm_htonl
5c11cc9d 103{
eccde741 104 scm_t_uint32 c_in = SCM_NUM2ULONG (1, value);
66c73b76 105
b9bd8526 106 return scm_from_ulong (htonl (c_in));
5c11cc9d 107}
1bbd0b84 108#undef FUNC_NAME
5c11cc9d 109
a1ec6916 110SCM_DEFINE (scm_ntohl, "ntohl", 1, 0, 0,
eefae538
GH
111 (SCM value),
112 "Convert a 32 bit quantity from network to host byte ordering.\n"
113 "@var{value} is packed into 4 bytes, which are then converted\n"
114 "and returned as a new integer.")
1bbd0b84 115#define FUNC_NAME s_scm_ntohl
5c11cc9d 116{
eccde741 117 scm_t_uint32 c_in = SCM_NUM2ULONG (1, value);
66c73b76 118
b9bd8526 119 return scm_from_ulong (ntohl (c_in));
5c11cc9d 120}
1bbd0b84 121#undef FUNC_NAME
5c11cc9d 122
66c73b76
GH
123#ifndef HAVE_INET_ATON
124/* for our definition in inet_aton.c, not usually needed. */
125extern int inet_aton ();
126#endif
127
128SCM_DEFINE (scm_inet_aton, "inet-aton", 1, 0, 0,
129 (SCM address),
eefae538
GH
130 "Convert an IPv4 Internet address from printable string\n"
131 "(dotted decimal notation) to an integer. E.g.,\n\n"
66c73b76
GH
132 "@lisp\n"
133 "(inet-aton \"127.0.0.1\") @result{} 2130706433\n"
134 "@end lisp")
135#define FUNC_NAME s_scm_inet_aton
136{
137 struct in_addr soka;
138
139 SCM_VALIDATE_STRING (1, address);
66c73b76
GH
140 if (inet_aton (SCM_STRING_CHARS (address), &soka) == 0)
141 SCM_MISC_ERROR ("bad address", SCM_EOL);
b9bd8526 142 return scm_from_ulong (ntohl (soka.s_addr));
66c73b76
GH
143}
144#undef FUNC_NAME
145
146
147SCM_DEFINE (scm_inet_ntoa, "inet-ntoa", 1, 0, 0,
148 (SCM inetid),
eefae538
GH
149 "Convert an IPv4 Internet address to a printable\n"
150 "(dotted decimal notation) string. E.g.,\n\n"
66c73b76
GH
151 "@lisp\n"
152 "(inet-ntoa 2130706433) @result{} \"127.0.0.1\"\n"
153 "@end lisp")
154#define FUNC_NAME s_scm_inet_ntoa
155{
156 struct in_addr addr;
157 char *s;
158 SCM answer;
159 addr.s_addr = htonl (SCM_NUM2ULONG (1, inetid));
160 s = inet_ntoa (addr);
36284627 161 answer = scm_mem2string (s, strlen (s));
66c73b76
GH
162 return answer;
163}
164#undef FUNC_NAME
165
166#ifdef HAVE_INET_NETOF
167SCM_DEFINE (scm_inet_netof, "inet-netof", 1, 0, 0,
168 (SCM address),
eefae538
GH
169 "Return the network number part of the given IPv4\n"
170 "Internet address. E.g.,\n\n"
66c73b76
GH
171 "@lisp\n"
172 "(inet-netof 2130706433) @result{} 127\n"
173 "@end lisp")
174#define FUNC_NAME s_scm_inet_netof
175{
176 struct in_addr addr;
177 addr.s_addr = htonl (SCM_NUM2ULONG (1, address));
b9bd8526 178 return scm_from_ulong (inet_netof (addr));
66c73b76
GH
179}
180#undef FUNC_NAME
181#endif
182
183#ifdef HAVE_INET_LNAOF
184SCM_DEFINE (scm_lnaof, "inet-lnaof", 1, 0, 0,
185 (SCM address),
186 "Return the local-address-with-network part of the given\n"
eefae538
GH
187 "IPv4 Internet address, using the obsolete class A/B/C system.\n"
188 "E.g.,\n\n"
66c73b76
GH
189 "@lisp\n"
190 "(inet-lnaof 2130706433) @result{} 1\n"
191 "@end lisp")
192#define FUNC_NAME s_scm_lnaof
193{
194 struct in_addr addr;
195 addr.s_addr = htonl (SCM_NUM2ULONG (1, address));
b9bd8526 196 return scm_from_ulong (inet_lnaof (addr));
66c73b76
GH
197}
198#undef FUNC_NAME
199#endif
200
201#ifdef HAVE_INET_MAKEADDR
202SCM_DEFINE (scm_inet_makeaddr, "inet-makeaddr", 2, 0, 0,
203 (SCM net, SCM lna),
eefae538 204 "Make an IPv4 Internet address by combining the network number\n"
66c73b76 205 "@var{net} with the local-address-within-network number\n"
eefae538 206 "@var{lna}. E.g.,\n\n"
66c73b76
GH
207 "@lisp\n"
208 "(inet-makeaddr 127 1) @result{} 2130706433\n"
209 "@end lisp")
210#define FUNC_NAME s_scm_inet_makeaddr
211{
212 struct in_addr addr;
213 unsigned long netnum;
214 unsigned long lnanum;
215
216 netnum = SCM_NUM2ULONG (1, net);
217 lnanum = SCM_NUM2ULONG (2, lna);
218 addr = inet_makeaddr (netnum, lnanum);
b9bd8526 219 return scm_from_ulong (ntohl (addr.s_addr));
66c73b76
GH
220}
221#undef FUNC_NAME
222#endif
223
a57a0b1e 224#ifdef HAVE_IPV6
eefae538 225
66c73b76
GH
226/* flip a 128 bit IPv6 address between host and network order. */
227#ifdef WORDS_BIGENDIAN
228#define FLIP_NET_HOST_128(addr)
229#else
230#define FLIP_NET_HOST_128(addr)\
231{\
232 int i;\
233 \
234 for (i = 0; i < 8; i++)\
235 {\
2de4f939 236 scm_t_uint8 c = (addr)[i];\
66c73b76
GH
237 \
238 (addr)[i] = (addr)[15 - i];\
239 (addr)[15 - i] = c;\
240 }\
241}
242#endif
243
2de4f939
RB
244#ifdef WORDS_BIGENDIAN
245#define FLIPCPY_NET_HOST_128(dest, src) memcpy (dest, src, 16)
246#else
247#define FLIPCPY_NET_HOST_128(dest, src) \
248{ \
249 const scm_t_uint8 *tmp_srcp = (src) + 15; \
250 scm_t_uint8 *tmp_destp = (dest); \
251 \
252 do { \
253 *tmp_destp++ = *tmp_srcp--; \
254 } while (tmp_srcp != (src)); \
255}
256#endif
257
258
7310ad0c 259#if (SIZEOF_SCM_T_BITS * SCM_CHAR_BIT) > 128
2de4f939
RB
260#error "Assumption that scm_t_bits <= 128 bits has been violated."
261#endif
262
7310ad0c 263#if (SIZEOF_UNSIGNED_LONG * SCM_CHAR_BIT) > 128
2de4f939
RB
264#error "Assumption that unsigned long <= 128 bits has been violated."
265#endif
266
7310ad0c 267#if (SIZEOF_UNSIGNED_LONG_LONG * SCM_CHAR_BIT) > 128
2de4f939
RB
268#error "Assumption that unsigned long long <= 128 bits has been violated."
269#endif
270
66c73b76
GH
271/* convert a 128 bit IPv6 address in network order to a host ordered
272 SCM integer. */
7cee5b31
MV
273static SCM
274scm_from_ipv6 (const scm_t_uint8 *src)
66c73b76 275{
2de4f939
RB
276 int i = 0;
277 const scm_t_uint8 *ptr = src;
278 int num_zero_bytes = 0;
279 scm_t_uint8 addr[16];
66c73b76 280
2de4f939
RB
281 /* count leading zeros (since we know it's bigendian, they'll be first) */
282 while (i < 16)
66c73b76 283 {
2de4f939
RB
284 if (*ptr) break;
285 num_zero_bytes++;
286 i++;
287 }
66c73b76 288
2de4f939
RB
289 if (SCM_SIZEOF_UNSIGNED_LONG_LONG != 0) /* compiler should optimize this */
290 {
291 if ((16 - num_zero_bytes) <= sizeof (unsigned long long))
292 {
293 /* it fits */
294 unsigned long long x;
295
296 FLIPCPY_NET_HOST_128(addr, src);
297#ifdef WORDS_BIGENDIAN
298 memcpy (&x, addr + (16 - sizeof (x)), sizeof (x));
299#else
300 memcpy (&x, addr, sizeof (x));
301#endif
b9bd8526 302 return scm_from_ulong_long (x);
2de4f939 303 }
66c73b76
GH
304 }
305 else
306 {
2de4f939
RB
307 if ((16 - num_zero_bytes) <= sizeof (unsigned long))
308 {
309 /* this is just so that we use INUM where possible. */
310 unsigned long x;
311
312 FLIPCPY_NET_HOST_128(addr, src);
313#ifdef WORDS_BIGENDIAN
314 memcpy (&x, addr + (16 - sizeof (x)), sizeof (x));
315#else
316 memcpy (&x, addr, sizeof (x));
317#endif
b9bd8526 318 return scm_from_ulong (x);
2de4f939 319 }
66c73b76 320 }
2de4f939
RB
321 /* otherwise get the big hammer */
322 {
323 SCM result = scm_i_mkbig ();
324
325 mpz_import (SCM_I_BIG_MPZ (result),
326 1, /* chunk */
327 1, /* big-endian chunk ordering */
328 16, /* chunks are 16 bytes long */
329 1, /* big-endian byte ordering */
330 0, /* "nails" -- leading unused bits per chunk */
331 src);
332 return scm_i_normbig (result);
333 }
66c73b76
GH
334}
335
336/* convert a host ordered SCM integer to a 128 bit IPv6 address in
337 network order. */
7cee5b31
MV
338static void
339scm_to_ipv6 (scm_t_uint8 dst[16], SCM src)
66c73b76 340{
e11e83f3 341 if (SCM_I_INUMP (src))
66c73b76 342 {
e11e83f3 343 scm_t_signed_bits n = SCM_I_INUM (src);
7cee5b31
MV
344 if (n < 0)
345 scm_out_of_range (NULL, src);
2de4f939
RB
346#ifdef WORDS_BIGENDIAN
347 memset (dst, 0, 16 - sizeof (scm_t_signed_bits));
348 memcpy (dst + (16 - sizeof (scm_t_signed_bits)),
349 &n,
350 sizeof (scm_t_signed_bits));
351#else
352 memset (dst + sizeof (scm_t_signed_bits),
353 0,
354 16 - sizeof (scm_t_signed_bits));
355 /* FIXME: this pair of ops is kinda wasteful -- should rewrite as
356 a single loop perhaps, similar to the handling of bignums. */
357 memcpy (dst, &n, sizeof (scm_t_signed_bits));
358 FLIP_NET_HOST_128 (dst);
359#endif
66c73b76 360 }
7cee5b31 361 else if (SCM_BIGP (src))
66c73b76 362 {
2de4f939 363 size_t count;
7cee5b31
MV
364
365 if ((mpz_sgn (SCM_I_BIG_MPZ (src)) < 0)
366 || mpz_sizeinbase (SCM_I_BIG_MPZ (src), 2) > 128)
367 scm_out_of_range (NULL, src);
368
66c73b76 369 memset (dst, 0, 16);
2de4f939
RB
370 mpz_export (dst,
371 &count,
372 1, /* big-endian chunk ordering */
373 16, /* chunks are 16 bytes long */
374 1, /* big-endian byte ordering */
375 0, /* "nails" -- leading unused bits per chunk */
376 SCM_I_BIG_MPZ (src));
377 scm_remember_upto_here_1 (src);
66c73b76 378 }
2de4f939 379 else
7cee5b31 380 scm_wrong_type_arg (NULL, 0, src);
2de4f939
RB
381}
382
66c73b76
GH
383#ifdef HAVE_INET_PTON
384SCM_DEFINE (scm_inet_pton, "inet-pton", 2, 0, 0,
385 (SCM family, SCM address),
eefae538
GH
386 "Convert a string containing a printable network address to\n"
387 "an integer address. Note that unlike the C version of this\n"
388 "function,\n"
66c73b76 389 "the result is an integer with normal host byte ordering.\n"
eefae538 390 "@var{family} can be @code{AF_INET} or @code{AF_INET6}. E.g.,\n\n"
66c73b76 391 "@lisp\n"
dd85ce47
ML
392 "(inet-pton AF_INET \"127.0.0.1\") @result{} 2130706433\n"
393 "(inet-pton AF_INET6 \"::1\") @result{} 1\n"
66c73b76
GH
394 "@end lisp")
395#define FUNC_NAME s_scm_inet_pton
396{
397 int af;
398 char *src;
399 char dst[16];
400 int rv;
401
7cee5b31 402 af = scm_to_int (family);
66c73b76
GH
403 SCM_ASSERT_RANGE (1, family, af == AF_INET || af == AF_INET6);
404 SCM_VALIDATE_STRING_COPY (2, address, src);
405 rv = inet_pton (af, src, dst);
406 if (rv == -1)
407 SCM_SYSERROR;
408 else if (rv == 0)
409 SCM_MISC_ERROR ("Bad address", SCM_EOL);
410 if (af == AF_INET)
b9bd8526 411 return scm_from_ulong (ntohl (*(scm_t_uint32 *) dst));
66c73b76 412 else
7cee5b31 413 return scm_from_ipv6 ((char *) dst);
66c73b76
GH
414}
415#undef FUNC_NAME
416#endif
417
418#ifdef HAVE_INET_NTOP
419SCM_DEFINE (scm_inet_ntop, "inet-ntop", 2, 0, 0,
420 (SCM family, SCM address),
eefae538 421 "Convert a network address into a printable string.\n"
66c73b76
GH
422 "Note that unlike the C version of this function,\n"
423 "the input is an integer with normal host byte ordering.\n"
eefae538 424 "@var{family} can be @code{AF_INET} or @code{AF_INET6}. E.g.,\n\n"
66c73b76 425 "@lisp\n"
dd85ce47 426 "(inet-ntop AF_INET 2130706433) @result{} \"127.0.0.1\"\n"
66c73b76
GH
427 "(inet-ntop AF_INET6 (- (expt 2 128) 1)) @result{}\n"
428 "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff\n"
429 "@end lisp")
430#define FUNC_NAME s_scm_inet_ntop
431{
432 int af;
433#ifdef INET6_ADDRSTRLEN
434 char dst[INET6_ADDRSTRLEN];
435#else
436 char dst[46];
437#endif
438 char addr6[16];
439
7cee5b31 440 af = scm_to_int (family);
66c73b76
GH
441 SCM_ASSERT_RANGE (1, family, af == AF_INET || af == AF_INET6);
442 if (af == AF_INET)
eccde741 443 *(scm_t_uint32 *) addr6 = htonl (SCM_NUM2ULONG (2, address));
66c73b76 444 else
7cee5b31 445 scm_to_ipv6 (addr6, address);
66c73b76
GH
446 if (inet_ntop (af, &addr6, dst, sizeof dst) == NULL)
447 SCM_SYSERROR;
448 return scm_makfrom0str (dst);
449}
450#undef FUNC_NAME
451#endif
452
a57a0b1e 453#endif /* HAVE_IPV6 */
eefae538 454
bc45012d 455SCM_SYMBOL (sym_socket, "socket");
82ddea4e 456
439006bf 457#define SCM_SOCK_FD_TO_PORT(fd) scm_fdes_to_port (fd, "r+0", sym_socket)
1bbd0b84 458
a1ec6916 459SCM_DEFINE (scm_socket, "socket", 3, 0, 0,
1bbd0b84 460 (SCM family, SCM style, SCM proto),
1e6808ea 461 "Return a new socket port of the type specified by @var{family},\n"
eefae538 462 "@var{style} and @var{proto}. All three parameters are\n"
3453619b
GH
463 "integers. Supported values for @var{family} are\n"
464 "@code{AF_UNIX}, @code{AF_INET} and @code{AF_INET6}.\n"
465 "Typical values for @var{style} are @code{SOCK_STREAM},\n"
eefae538
GH
466 "@code{SOCK_DGRAM} and @code{SOCK_RAW}.\n\n"
467 "@var{proto} can be obtained from a protocol name using\n"
1e6808ea 468 "@code{getprotobyname}. A value of zero specifies the default\n"
eefae538 469 "protocol, which is usually right.\n\n"
1e6808ea
MG
470 "A single socket port cannot by used for communication until it\n"
471 "has been connected to another socket.")
1bbd0b84 472#define FUNC_NAME s_scm_socket
0f2d19dd 473{
370312ae 474 int fd;
370312ae 475
7cee5b31
MV
476 fd = socket (scm_to_int (family),
477 scm_to_int (style),
478 scm_to_int (proto));
439006bf
GH
479 if (fd == -1)
480 SCM_SYSERROR;
481 return SCM_SOCK_FD_TO_PORT (fd);
0f2d19dd 482}
1bbd0b84 483#undef FUNC_NAME
0f2d19dd 484
0e958795 485#ifdef HAVE_SOCKETPAIR
a1ec6916 486SCM_DEFINE (scm_socketpair, "socketpair", 3, 0, 0,
1bbd0b84 487 (SCM family, SCM style, SCM proto),
1e6808ea 488 "Return a pair of connected (but unnamed) socket ports of the\n"
eefae538 489 "type specified by @var{family}, @var{style} and @var{proto}.\n"
1e6808ea
MG
490 "Many systems support only socket pairs of the @code{AF_UNIX}\n"
491 "family. Zero is likely to be the only meaningful value for\n"
eefae538 492 "@var{proto}.")
1bbd0b84 493#define FUNC_NAME s_scm_socketpair
0f2d19dd 494{
370312ae
GH
495 int fam;
496 int fd[2];
370312ae 497
7cee5b31 498 fam = scm_to_int (family);
370312ae 499
7cee5b31 500 if (socketpair (fam, scm_to_int (style), scm_to_int (proto), fd) == -1)
1bbd0b84 501 SCM_SYSERROR;
370312ae 502
439006bf 503 return scm_cons (SCM_SOCK_FD_TO_PORT (fd[0]), SCM_SOCK_FD_TO_PORT (fd[1]));
0f2d19dd 504}
1bbd0b84 505#undef FUNC_NAME
0e958795 506#endif
0f2d19dd 507
a1ec6916 508SCM_DEFINE (scm_getsockopt, "getsockopt", 3, 0, 0,
1bbd0b84 509 (SCM sock, SCM level, SCM optname),
1e6808ea 510 "Return the value of a particular socket option for the socket\n"
eefae538 511 "port @var{sock}. @var{level} is an integer code for type of\n"
1e6808ea
MG
512 "option being requested, e.g., @code{SOL_SOCKET} for\n"
513 "socket-level options. @var{optname} is an integer code for the\n"
514 "option required and should be specified using one of the\n"
eefae538 515 "symbols @code{SO_DEBUG}, @code{SO_REUSEADDR} etc.\n\n"
1e6808ea
MG
516 "The returned value is typically an integer but @code{SO_LINGER}\n"
517 "returns a pair of integers.")
1bbd0b84 518#define FUNC_NAME s_scm_getsockopt
0f2d19dd 519{
370312ae 520 int fd;
439006bf 521 /* size of optval is the largest supported option. */
370312ae
GH
522#ifdef HAVE_STRUCT_LINGER
523 char optval[sizeof (struct linger)];
439006bf 524 int optlen = sizeof (struct linger);
370312ae 525#else
1be6b49c
ML
526 char optval[sizeof (size_t)];
527 int optlen = sizeof (size_t);
370312ae
GH
528#endif
529 int ilevel;
530 int ioptname;
0f2d19dd 531
78446828 532 sock = SCM_COERCE_OUTPORT (sock);
2cf6d014 533 SCM_VALIDATE_OPFPORT (1, sock);
7cee5b31
MV
534 ilevel = scm_to_int (level);
535 ioptname = scm_to_int (optname);
0f2d19dd 536
ee149d03 537 fd = SCM_FPORT_FDES (sock);
370312ae 538 if (getsockopt (fd, ilevel, ioptname, (void *) optval, &optlen) == -1)
1bbd0b84 539 SCM_SYSERROR;
1cc91f1b 540
439006bf 541 if (ilevel == SOL_SOCKET)
0f2d19dd 542 {
439006bf
GH
543#ifdef SO_LINGER
544 if (ioptname == SO_LINGER)
545 {
370312ae 546#ifdef HAVE_STRUCT_LINGER
439006bf
GH
547 struct linger *ling = (struct linger *) optval;
548
b9bd8526
MV
549 return scm_cons (scm_from_long (ling->l_onoff),
550 scm_from_long (ling->l_linger));
370312ae 551#else
b9bd8526 552 return scm_cons (scm_from_long (*(int *) optval),
7cee5b31 553 scm_from_int (0));
0f2d19dd 554#endif
439006bf
GH
555 }
556 else
370312ae 557#endif
439006bf 558 if (0
370312ae 559#ifdef SO_SNDBUF
439006bf 560 || ioptname == SO_SNDBUF
370312ae
GH
561#endif
562#ifdef SO_RCVBUF
439006bf 563 || ioptname == SO_RCVBUF
370312ae 564#endif
439006bf
GH
565 )
566 {
b9bd8526 567 return scm_from_size_t (*(size_t *) optval);
439006bf
GH
568 }
569 }
b9bd8526 570 return scm_from_int (*(int *) optval);
0f2d19dd 571}
1bbd0b84 572#undef FUNC_NAME
0f2d19dd 573
a1ec6916 574SCM_DEFINE (scm_setsockopt, "setsockopt", 4, 0, 0,
1bbd0b84 575 (SCM sock, SCM level, SCM optname, SCM value),
eefae538
GH
576 "Set the value of a particular socket option for the socket\n"
577 "port @var{sock}. @var{level} is an integer code for type of option\n"
b380b885
MD
578 "being set, e.g., @code{SOL_SOCKET} for socket-level options.\n"
579 "@var{optname} is an\n"
580 "integer code for the option to set and should be specified using one of\n"
581 "the symbols @code{SO_DEBUG}, @code{SO_REUSEADDR} etc.\n"
582 "@var{value} is the value to which the option should be set. For\n"
583 "most options this must be an integer, but for @code{SO_LINGER} it must\n"
584 "be a pair.\n\n"
585 "The return value is unspecified.")
1bbd0b84 586#define FUNC_NAME s_scm_setsockopt
0f2d19dd 587{
370312ae 588 int fd;
439006bf
GH
589 int optlen = -1;
590 /* size of optval is the largest supported option. */
370312ae 591#ifdef HAVE_STRUCT_LINGER
439006bf 592 char optval[sizeof (struct linger)];
370312ae 593#else
1be6b49c 594 char optval[sizeof (size_t)];
370312ae
GH
595#endif
596 int ilevel, ioptname;
439006bf 597
78446828 598 sock = SCM_COERCE_OUTPORT (sock);
439006bf
GH
599
600 SCM_VALIDATE_OPFPORT (1, sock);
7cee5b31
MV
601 ilevel = scm_to_int (level);
602 ioptname = scm_to_int (optname);
439006bf 603
ee149d03 604 fd = SCM_FPORT_FDES (sock);
439006bf
GH
605
606 if (ilevel == SOL_SOCKET)
370312ae 607 {
439006bf
GH
608#ifdef SO_LINGER
609 if (ioptname == SO_LINGER)
610 {
370312ae 611#ifdef HAVE_STRUCT_LINGER
439006bf
GH
612 struct linger ling;
613 long lv;
614
615 SCM_ASSERT (SCM_CONSP (value), value, SCM_ARG4, FUNC_NAME);
616 lv = SCM_NUM2LONG (4, SCM_CAR (value));
617 ling.l_onoff = (int) lv;
618 SCM_ASSERT_RANGE (SCM_ARG4, value, ling.l_onoff == lv);
619 lv = SCM_NUM2LONG (4, SCM_CDR (value));
620 ling.l_linger = (int) lv;
621 SCM_ASSERT_RANGE (SCM_ARG4, value, ling.l_linger == lv);
622 optlen = (int) sizeof (struct linger);
623 memcpy (optval, (void *) &ling, optlen);
370312ae 624#else
439006bf
GH
625 int ling;
626 long lv;
627
628 SCM_ASSERT (SCM_CONSP (value), value, SCM_ARG4, FUNC_NAME);
629 /* timeout is ignored, but may as well validate it. */
630 lv = SCM_NUM2LONG (4, SCM_CDR (value));
631 ling = (int) lv;
632 SCM_ASSERT_RANGE (SCM_ARG4, value, ling == lv);
633 lv = SCM_NUM2LONG (4, SCM_CAR (value));
634 ling = (int) lv;
635 SCM_ASSERT_RANGE (SCM_ARG4, value, ling == lv);
636 optlen = (int) sizeof (int);
637 (*(int *) optval) = ling;
638#endif
639 }
640 else
641#endif
642 if (0
370312ae 643#ifdef SO_SNDBUF
439006bf 644 || ioptname == SO_SNDBUF
370312ae
GH
645#endif
646#ifdef SO_RCVBUF
439006bf 647 || ioptname == SO_RCVBUF
370312ae 648#endif
439006bf
GH
649 )
650 {
651 long lv = SCM_NUM2LONG (4, value);
652
1be6b49c
ML
653 optlen = (int) sizeof (size_t);
654 (*(size_t *) optval) = (size_t) lv;
439006bf
GH
655 }
656 }
657 if (optlen == -1)
0f2d19dd 658 {
439006bf
GH
659 /* Most options take an int. */
660 long lv = SCM_NUM2LONG (4, value);
661 int val = (int) lv;
662
663 SCM_ASSERT_RANGE (SCM_ARG4, value, val == lv);
370312ae 664 optlen = (int) sizeof (int);
439006bf 665 (*(int *) optval) = val;
0f2d19dd 666 }
370312ae 667 if (setsockopt (fd, ilevel, ioptname, (void *) optval, optlen) == -1)
1bbd0b84 668 SCM_SYSERROR;
370312ae 669 return SCM_UNSPECIFIED;
0f2d19dd 670}
1bbd0b84 671#undef FUNC_NAME
0f2d19dd 672
a1ec6916 673SCM_DEFINE (scm_shutdown, "shutdown", 2, 0, 0,
1bbd0b84 674 (SCM sock, SCM how),
b380b885 675 "Sockets can be closed simply by using @code{close-port}. The\n"
bb2c02f2 676 "@code{shutdown} procedure allows reception or transmission on a\n"
b380b885
MD
677 "connection to be shut down individually, according to the parameter\n"
678 "@var{how}:\n\n"
679 "@table @asis\n"
680 "@item 0\n"
681 "Stop receiving data for this socket. If further data arrives, reject it.\n"
682 "@item 1\n"
683 "Stop trying to transmit data from this socket. Discard any\n"
684 "data waiting to be sent. Stop looking for acknowledgement of\n"
685 "data already sent; don't retransmit it if it is lost.\n"
686 "@item 2\n"
687 "Stop both reception and transmission.\n"
688 "@end table\n\n"
689 "The return value is unspecified.")
1bbd0b84 690#define FUNC_NAME s_scm_shutdown
0f2d19dd 691{
370312ae 692 int fd;
78446828 693 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 694 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 695 fd = SCM_FPORT_FDES (sock);
7cee5b31 696 if (shutdown (fd, scm_to_signed_integer (how, 0, 2)) == -1)
1bbd0b84 697 SCM_SYSERROR;
370312ae
GH
698 return SCM_UNSPECIFIED;
699}
1bbd0b84 700#undef FUNC_NAME
0f2d19dd 701
370312ae
GH
702/* convert fam/address/args into a sockaddr of the appropriate type.
703 args is modified by removing the arguments actually used.
704 which_arg and proc are used when reporting errors:
705 which_arg is the position of address in the original argument list.
706 proc is the name of the original procedure.
707 size returns the size of the structure allocated. */
708
370312ae 709static struct sockaddr *
439006bf
GH
710scm_fill_sockaddr (int fam, SCM address, SCM *args, int which_arg,
711 const char *proc, int *size)
3453619b 712#define FUNC_NAME proc
370312ae
GH
713{
714 switch (fam)
0f2d19dd 715 {
370312ae
GH
716 case AF_INET:
717 {
370312ae 718 struct sockaddr_in *soka;
3453619b
GH
719 unsigned long addr;
720 int port;
370312ae 721
3453619b
GH
722 SCM_VALIDATE_ULONG_COPY (which_arg, address, addr);
723 SCM_VALIDATE_CONS (which_arg + 1, *args);
7cee5b31 724 port = scm_to_int (SCM_CAR (*args));
3453619b 725 *args = SCM_CDR (*args);
67329a9e 726 soka = (struct sockaddr_in *) scm_malloc (sizeof (struct sockaddr_in));
439006bf
GH
727 if (!soka)
728 scm_memory_error (proc);
3453619b
GH
729 /* 4.4BSD-style interface includes sin_len member and defines SIN_LEN,
730 4.3BSD does not. */
731#ifdef SIN_LEN
732 soka->sin_len = sizeof (struct sockaddr_in);
733#endif
370312ae 734 soka->sin_family = AF_INET;
3453619b
GH
735 soka->sin_addr.s_addr = htonl (addr);
736 soka->sin_port = htons (port);
370312ae
GH
737 *size = sizeof (struct sockaddr_in);
738 return (struct sockaddr *) soka;
739 }
a57a0b1e 740#ifdef HAVE_IPV6
3453619b
GH
741 case AF_INET6:
742 {
743 /* see RFC2553. */
744 int port;
745 struct sockaddr_in6 *soka;
746 unsigned long flowinfo = 0;
747 unsigned long scope_id = 0;
748
3453619b 749 SCM_VALIDATE_CONS (which_arg + 1, *args);
7cee5b31 750 port = scm_to_int (SCM_CAR (*args));
3453619b
GH
751 *args = SCM_CDR (*args);
752 if (SCM_CONSP (*args))
753 {
754 SCM_VALIDATE_ULONG_COPY (which_arg + 2, SCM_CAR (*args), flowinfo);
755 *args = SCM_CDR (*args);
756 if (SCM_CONSP (*args))
757 {
758 SCM_VALIDATE_ULONG_COPY (which_arg + 3, SCM_CAR (*args),
759 scope_id);
760 *args = SCM_CDR (*args);
761 }
762 }
67329a9e 763 soka = (struct sockaddr_in6 *) scm_malloc (sizeof (struct sockaddr_in6));
3453619b
GH
764 if (!soka)
765 scm_memory_error (proc);
766#ifdef SIN_LEN6
767 soka->sin6_len = sizeof (struct sockaddr_in6);
768#endif
769 soka->sin6_family = AF_INET6;
7cee5b31 770 scm_to_ipv6 (soka->sin6_addr.s6_addr, address);
5a525b84 771 soka->sin6_port = htons (port);
3453619b 772 soka->sin6_flowinfo = flowinfo;
5a525b84 773#ifdef HAVE_SIN6_SCOPE_ID
3453619b 774 soka->sin6_scope_id = scope_id;
5a525b84 775#endif
3453619b
GH
776 *size = sizeof (struct sockaddr_in6);
777 return (struct sockaddr *) soka;
778 }
779#endif
1ba8c23a 780#ifdef HAVE_UNIX_DOMAIN_SOCKETS
370312ae
GH
781 case AF_UNIX:
782 {
783 struct sockaddr_un *soka;
439006bf 784 int addr_size;
370312ae 785
a6d9e5ab 786 SCM_ASSERT (SCM_STRINGP (address), address, which_arg, proc);
439006bf
GH
787 /* the static buffer size in sockaddr_un seems to be arbitrary
788 and not necessarily a hard limit. e.g., the glibc manual
789 suggests it may be possible to declare it size 0. let's
790 ignore it. if the O/S doesn't like the size it will cause
791 connect/bind etc., to fail. sun_path is always the last
792 member of the structure. */
793 addr_size = sizeof (struct sockaddr_un)
794 + max (0, SCM_STRING_LENGTH (address) + 1 - (sizeof soka->sun_path));
67329a9e 795 soka = (struct sockaddr_un *) scm_malloc (addr_size);
439006bf
GH
796 if (!soka)
797 scm_memory_error (proc);
798 memset (soka, 0, addr_size); /* for sun_len: see sin_len above. */
799 soka->sun_family = AF_UNIX;
34f0f2b8 800 memcpy (soka->sun_path, SCM_STRING_CHARS (address),
439006bf
GH
801 SCM_STRING_LENGTH (address));
802 *size = SUN_LEN (soka);
370312ae
GH
803 return (struct sockaddr *) soka;
804 }
0e958795 805#endif
370312ae 806 default:
e11e83f3 807 scm_out_of_range (proc, scm_from_int (fam));
0f2d19dd 808 }
0f2d19dd 809}
3453619b 810#undef FUNC_NAME
370312ae 811
a1ec6916 812SCM_DEFINE (scm_connect, "connect", 3, 0, 1,
1bbd0b84 813 (SCM sock, SCM fam, SCM address, SCM args),
eefae538 814 "Initiate a connection from a socket using a specified address\n"
3453619b
GH
815 "family to the address\n"
816 "specified by @var{address} and possibly @var{args}.\n"
817 "The format required for @var{address}\n"
818 "and @var{args} depends on the family of the socket.\n\n"
b380b885 819 "For a socket of family @code{AF_UNIX},\n"
3453619b 820 "only @var{address} is specified and must be a string with the\n"
b380b885
MD
821 "filename where the socket is to be created.\n\n"
822 "For a socket of family @code{AF_INET},\n"
3453619b
GH
823 "@var{address} must be an integer IPv4 host address and\n"
824 "@var{args} must be a single integer port number.\n\n"
825 "For a socket of family @code{AF_INET6},\n"
826 "@var{address} must be an integer IPv6 host address and\n"
827 "@var{args} may be up to three integers:\n"
828 "port [flowinfo] [scope_id],\n"
829 "where flowinfo and scope_id default to zero.\n\n"
b380b885 830 "The return value is unspecified.")
1bbd0b84 831#define FUNC_NAME s_scm_connect
0f2d19dd 832{
370312ae
GH
833 int fd;
834 struct sockaddr *soka;
439006bf 835 int size;
0f2d19dd 836
78446828 837 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 838 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 839 fd = SCM_FPORT_FDES (sock);
7cee5b31 840 soka = scm_fill_sockaddr (scm_to_int (fam), address, &args, 3, FUNC_NAME,
439006bf 841 &size);
370312ae 842 if (connect (fd, soka, size) == -1)
439006bf
GH
843 {
844 int save_errno = errno;
845
846 free (soka);
847 errno = save_errno;
848 SCM_SYSERROR;
849 }
850 free (soka);
370312ae 851 return SCM_UNSPECIFIED;
0f2d19dd 852}
1bbd0b84 853#undef FUNC_NAME
0f2d19dd 854
a1ec6916 855SCM_DEFINE (scm_bind, "bind", 3, 0, 1,
1bbd0b84 856 (SCM sock, SCM fam, SCM address, SCM args),
eefae538 857 "Assign an address to the socket port @var{sock}.\n"
b380b885
MD
858 "Generally this only needs to be done for server sockets,\n"
859 "so they know where to look for incoming connections. A socket\n"
860 "without an address will be assigned one automatically when it\n"
861 "starts communicating.\n\n"
eefae538
GH
862 "The format of @var{address} and @var{args} depends\n"
863 "on the family of the socket.\n\n"
b380b885 864 "For a socket of family @code{AF_UNIX}, only @var{address}\n"
eefae538
GH
865 "is specified and must be a string with the filename where\n"
866 "the socket is to be created.\n\n"
867 "For a socket of family @code{AF_INET}, @var{address}\n"
868 "must be an integer IPv4 address and @var{args}\n"
869 "must be a single integer port number.\n\n"
870 "The values of the following variables can also be used for\n"
871 "@var{address}:\n\n"
b380b885
MD
872 "@defvar INADDR_ANY\n"
873 "Allow connections from any address.\n"
874 "@end defvar\n\n"
875 "@defvar INADDR_LOOPBACK\n"
876 "The address of the local host using the loopback device.\n"
877 "@end defvar\n\n"
878 "@defvar INADDR_BROADCAST\n"
879 "The broadcast address on the local network.\n"
880 "@end defvar\n\n"
881 "@defvar INADDR_NONE\n"
882 "No address.\n"
883 "@end defvar\n\n"
eefae538
GH
884 "For a socket of family @code{AF_INET6}, @var{address}\n"
885 "must be an integer IPv6 address and @var{args}\n"
886 "may be up to three integers:\n"
887 "port [flowinfo] [scope_id],\n"
888 "where flowinfo and scope_id default to zero.\n\n"
b380b885 889 "The return value is unspecified.")
1bbd0b84 890#define FUNC_NAME s_scm_bind
370312ae 891{
370312ae 892 struct sockaddr *soka;
439006bf 893 int size;
370312ae
GH
894 int fd;
895
78446828 896 sock = SCM_COERCE_OUTPORT (sock);
439006bf 897 SCM_VALIDATE_OPFPORT (1, sock);
7cee5b31 898 soka = scm_fill_sockaddr (scm_to_int (fam), address, &args, 3, FUNC_NAME,
439006bf 899 &size);
ee149d03 900 fd = SCM_FPORT_FDES (sock);
439006bf
GH
901 if (bind (fd, soka, size) == -1)
902 {
903 int save_errno = errno;
904
905 free (soka);
906 errno = save_errno;
1bbd0b84 907 SCM_SYSERROR;
439006bf
GH
908 }
909 free (soka);
370312ae
GH
910 return SCM_UNSPECIFIED;
911}
1bbd0b84 912#undef FUNC_NAME
370312ae 913
a1ec6916 914SCM_DEFINE (scm_listen, "listen", 2, 0, 0,
1bbd0b84 915 (SCM sock, SCM backlog),
eefae538 916 "Enable @var{sock} to accept connection\n"
b380b885
MD
917 "requests. @var{backlog} is an integer specifying\n"
918 "the maximum length of the queue for pending connections.\n"
eefae538
GH
919 "If the queue fills, new clients will fail to connect until\n"
920 "the server calls @code{accept} to accept a connection from\n"
921 "the queue.\n\n"
b380b885 922 "The return value is unspecified.")
1bbd0b84 923#define FUNC_NAME s_scm_listen
370312ae
GH
924{
925 int fd;
78446828 926 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 927 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 928 fd = SCM_FPORT_FDES (sock);
7cee5b31 929 if (listen (fd, scm_to_int (backlog)) == -1)
1bbd0b84 930 SCM_SYSERROR;
370312ae
GH
931 return SCM_UNSPECIFIED;
932}
1bbd0b84 933#undef FUNC_NAME
370312ae
GH
934
935/* Put the components of a sockaddr into a new SCM vector. */
370312ae 936static SCM
aca23b65
MV
937scm_addr_vector (const struct sockaddr *address, int addr_size,
938 const char *proc)
0f2d19dd 939{
370312ae 940 short int fam = address->sa_family;
1d1559ce 941 SCM result =SCM_EOL;
34d19ef6 942
439006bf 943
5a525b84 944 switch (fam)
0f2d19dd 945 {
5a525b84
GH
946 case AF_INET:
947 {
e1368a8d 948 const struct sockaddr_in *nad = (struct sockaddr_in *) address;
439006bf 949
1d1559ce 950 result = scm_c_make_vector (3, SCM_UNSPECIFIED);
34d19ef6 951
b9bd8526
MV
952 SCM_VECTOR_SET(result, 0,
953 scm_from_short (fam));
954 SCM_VECTOR_SET(result, 1,
955 scm_from_ulong (ntohl (nad->sin_addr.s_addr)));
956 SCM_VECTOR_SET(result, 2,
957 scm_from_ushort (ntohs (nad->sin_port)));
5a525b84
GH
958 }
959 break;
a57a0b1e 960#ifdef HAVE_IPV6
5a525b84
GH
961 case AF_INET6:
962 {
e1368a8d 963 const struct sockaddr_in6 *nad = (struct sockaddr_in6 *) address;
5a525b84 964
1d1559ce 965 result = scm_c_make_vector (5, SCM_UNSPECIFIED);
b9bd8526 966 SCM_VECTOR_SET(result, 0, scm_from_short (fam));
7cee5b31 967 SCM_VECTOR_SET(result, 1, scm_from_ipv6 (nad->sin6_addr.s6_addr));
b9bd8526
MV
968 SCM_VECTOR_SET(result, 2, scm_from_ushort (ntohs (nad->sin6_port)));
969 SCM_VECTOR_SET(result, 3, scm_from_uint32 (nad->sin6_flowinfo));
5a525b84 970#ifdef HAVE_SIN6_SCOPE_ID
b9bd8526 971 SCM_VECTOR_SET(result, 4, scm_from_ulong (nad->sin6_scope_id));
5a525b84 972#else
1d1559ce 973 SCM_VECTOR_SET(result, 4, SCM_INUM0);
0e958795 974#endif
5a525b84
GH
975 }
976 break;
977#endif
978#ifdef HAVE_UNIX_DOMAIN_SOCKETS
979 case AF_UNIX:
980 {
e1368a8d 981 const struct sockaddr_un *nad = (struct sockaddr_un *) address;
439006bf 982
1d1559ce 983 result = scm_c_make_vector (2, SCM_UNSPECIFIED);
34d19ef6 984
b9bd8526 985 SCM_VECTOR_SET(result, 0, scm_from_short (fam));
aca23b65
MV
986 /* When addr_size is not enough to cover sun_path, do not try
987 to access it. */
988 if (addr_size <= offsetof (struct sockaddr_un, sun_path))
989 SCM_VECTOR_SET(result, 1, SCM_BOOL_F);
990 else
991 SCM_VECTOR_SET(result, 1, scm_mem2string (nad->sun_path,
992 strlen (nad->sun_path)));
5a525b84
GH
993 }
994 break;
995#endif
996 default:
997 scm_misc_error (proc, "Unrecognised address family: ~A",
e11e83f3 998 scm_list_1 (scm_from_int (fam)));
0f2d19dd 999 }
1d1559ce 1000 return result;
370312ae
GH
1001}
1002
439006bf
GH
1003/* calculate the size of a buffer large enough to hold any supported
1004 sockaddr type. if the buffer isn't large enough, certain system
1005 calls will return a truncated address. */
370312ae 1006
439006bf
GH
1007#if defined (HAVE_UNIX_DOMAIN_SOCKETS)
1008#define MAX_SIZE_UN sizeof (struct sockaddr_un)
0e958795 1009#else
439006bf 1010#define MAX_SIZE_UN 0
0e958795 1011#endif
439006bf 1012
a57a0b1e 1013#if defined (HAVE_IPV6)
5a525b84
GH
1014#define MAX_SIZE_IN6 sizeof (struct sockaddr_in6)
1015#else
1016#define MAX_SIZE_IN6 0
1017#endif
1018
1019#define MAX_ADDR_SIZE max (max (sizeof (struct sockaddr_in), MAX_SIZE_IN6),\
1020 MAX_SIZE_UN)
0f2d19dd 1021
a1ec6916 1022SCM_DEFINE (scm_accept, "accept", 1, 0, 0,
1bbd0b84 1023 (SCM sock),
eefae538
GH
1024 "Accept a connection on a bound, listening socket.\n"
1025 "If there\n"
1026 "are no pending connections in the queue, wait until\n"
1027 "one is available unless the non-blocking option has been\n"
1028 "set on the socket.\n\n"
b380b885 1029 "The return value is a\n"
eefae538
GH
1030 "pair in which the @emph{car} is a new socket port for the\n"
1031 "connection and\n"
1032 "the @emph{cdr} is an object with address information about the\n"
1033 "client which initiated the connection.\n\n"
1034 "@var{sock} does not become part of the\n"
b380b885 1035 "connection and will continue to accept new requests.")
1bbd0b84 1036#define FUNC_NAME s_scm_accept
0f2d19dd 1037{
370312ae
GH
1038 int fd;
1039 int newfd;
1040 SCM address;
1041 SCM newsock;
439006bf
GH
1042 int addr_size = MAX_ADDR_SIZE;
1043 char max_addr[MAX_ADDR_SIZE];
1044 struct sockaddr *addr = (struct sockaddr *) max_addr;
370312ae 1045
78446828 1046 sock = SCM_COERCE_OUTPORT (sock);
439006bf 1047 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 1048 fd = SCM_FPORT_FDES (sock);
439006bf
GH
1049 newfd = accept (fd, addr, &addr_size);
1050 if (newfd == -1)
1051 SCM_SYSERROR;
1052 newsock = SCM_SOCK_FD_TO_PORT (newfd);
aca23b65 1053 address = scm_addr_vector (addr, addr_size, FUNC_NAME);
370312ae 1054 return scm_cons (newsock, address);
0f2d19dd 1055}
1bbd0b84 1056#undef FUNC_NAME
0f2d19dd 1057
a1ec6916 1058SCM_DEFINE (scm_getsockname, "getsockname", 1, 0, 0,
1bbd0b84 1059 (SCM sock),
eefae538 1060 "Return the address of @var{sock}, in the same form as the\n"
1e6808ea
MG
1061 "object returned by @code{accept}. On many systems the address\n"
1062 "of a socket in the @code{AF_FILE} namespace cannot be read.")
1bbd0b84 1063#define FUNC_NAME s_scm_getsockname
0f2d19dd 1064{
370312ae 1065 int fd;
439006bf
GH
1066 int addr_size = MAX_ADDR_SIZE;
1067 char max_addr[MAX_ADDR_SIZE];
1068 struct sockaddr *addr = (struct sockaddr *) max_addr;
1069
78446828 1070 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 1071 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 1072 fd = SCM_FPORT_FDES (sock);
439006bf 1073 if (getsockname (fd, addr, &addr_size) == -1)
1bbd0b84 1074 SCM_SYSERROR;
aca23b65 1075 return scm_addr_vector (addr, addr_size, FUNC_NAME);
0f2d19dd 1076}
1bbd0b84 1077#undef FUNC_NAME
0f2d19dd 1078
a1ec6916 1079SCM_DEFINE (scm_getpeername, "getpeername", 1, 0, 0,
1bbd0b84 1080 (SCM sock),
eefae538 1081 "Return the address that @var{sock}\n"
1e6808ea
MG
1082 "is connected to, in the same form as the object returned by\n"
1083 "@code{accept}. On many systems the address of a socket in the\n"
1084 "@code{AF_FILE} namespace cannot be read.")
1bbd0b84 1085#define FUNC_NAME s_scm_getpeername
0f2d19dd 1086{
370312ae 1087 int fd;
439006bf
GH
1088 int addr_size = MAX_ADDR_SIZE;
1089 char max_addr[MAX_ADDR_SIZE];
1090 struct sockaddr *addr = (struct sockaddr *) max_addr;
1091
78446828 1092 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 1093 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 1094 fd = SCM_FPORT_FDES (sock);
439006bf 1095 if (getpeername (fd, addr, &addr_size) == -1)
1bbd0b84 1096 SCM_SYSERROR;
aca23b65 1097 return scm_addr_vector (addr, addr_size, FUNC_NAME);
0f2d19dd 1098}
1bbd0b84 1099#undef FUNC_NAME
0f2d19dd 1100
a1ec6916 1101SCM_DEFINE (scm_recv, "recv!", 2, 1, 0,
1bbd0b84 1102 (SCM sock, SCM buf, SCM flags),
eefae538
GH
1103 "Receive data from a socket port.\n"
1104 "@var{sock} must already\n"
b380b885
MD
1105 "be bound to the address from which data is to be received.\n"
1106 "@var{buf} is a string into which\n"
eefae538
GH
1107 "the data will be written. The size of @var{buf} limits\n"
1108 "the amount of\n"
b380b885 1109 "data which can be received: in the case of packet\n"
eefae538
GH
1110 "protocols, if a packet larger than this limit is encountered\n"
1111 "then some data\n"
b380b885
MD
1112 "will be irrevocably lost.\n\n"
1113 "The optional @var{flags} argument is a value or\n"
1114 "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
eefae538
GH
1115 "The value returned is the number of bytes read from the\n"
1116 "socket.\n\n"
1117 "Note that the data is read directly from the socket file\n"
1118 "descriptor:\n"
09831f94 1119 "any unread buffered port data is ignored.")
1bbd0b84 1120#define FUNC_NAME s_scm_recv
0f2d19dd 1121{
370312ae
GH
1122 int rv;
1123 int fd;
1124 int flg;
370312ae 1125
34d19ef6
HWN
1126 SCM_VALIDATE_OPFPORT (1, sock);
1127 SCM_VALIDATE_STRING (2, buf);
7cee5b31
MV
1128 if (SCM_UNBNDP (flags))
1129 flg = 0;
1130 else
1131 flg = scm_to_int (flags);
ee149d03 1132 fd = SCM_FPORT_FDES (sock);
370312ae 1133
bfa974f0 1134 SCM_SYSCALL (rv = recv (fd, SCM_STRING_CHARS (buf), SCM_STRING_LENGTH (buf), flg));
370312ae 1135 if (rv == -1)
1bbd0b84 1136 SCM_SYSERROR;
370312ae 1137
7cee5b31 1138 return scm_from_int (rv);
370312ae 1139}
1bbd0b84 1140#undef FUNC_NAME
370312ae 1141
a1ec6916 1142SCM_DEFINE (scm_send, "send", 2, 1, 0,
1bbd0b84 1143 (SCM sock, SCM message, SCM flags),
eefae538
GH
1144 "Transmit the string @var{message} on a socket port @var{sock}.\n"
1145 "@var{sock} must already be bound to a destination address. The\n"
1146 "value returned is the number of bytes transmitted --\n"
1147 "it's possible for\n"
1148 "this to be less than the length of @var{message}\n"
1149 "if the socket is\n"
1150 "set to be non-blocking. The optional @var{flags} argument\n"
1151 "is a value or\n"
b380b885 1152 "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
eefae538
GH
1153 "Note that the data is written directly to the socket\n"
1154 "file descriptor:\n"
b380b885 1155 "any unflushed buffered port data is ignored.")
1bbd0b84 1156#define FUNC_NAME s_scm_send
370312ae
GH
1157{
1158 int rv;
1159 int fd;
1160 int flg;
1161
78446828 1162 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 1163 SCM_VALIDATE_OPFPORT (1, sock);
a6d9e5ab 1164 SCM_VALIDATE_STRING (2, message);
7cee5b31
MV
1165 if (SCM_UNBNDP (flags))
1166 flg = 0;
1167 else
1168 flg = scm_to_int (flags);
ee149d03 1169 fd = SCM_FPORT_FDES (sock);
370312ae 1170
34f0f2b8 1171 SCM_SYSCALL (rv = send (fd, SCM_STRING_CHARS (message), SCM_STRING_LENGTH (message), flg));
370312ae 1172 if (rv == -1)
1bbd0b84 1173 SCM_SYSERROR;
7cee5b31 1174 return scm_from_int (rv);
370312ae 1175}
1bbd0b84 1176#undef FUNC_NAME
370312ae 1177
a1ec6916 1178SCM_DEFINE (scm_recvfrom, "recvfrom!", 2, 3, 0,
60d02d09 1179 (SCM sock, SCM str, SCM flags, SCM start, SCM end),
eefae538 1180 "Return data from the socket port @var{sock} and also\n"
1e6808ea 1181 "information about where the data was received from.\n"
eefae538 1182 "@var{sock} must already be bound to the address from which\n"
1e6808ea
MG
1183 "data is to be received. @code{str}, is a string into which the\n"
1184 "data will be written. The size of @var{str} limits the amount\n"
1185 "of data which can be received: in the case of packet protocols,\n"
1186 "if a packet larger than this limit is encountered then some\n"
eefae538 1187 "data will be irrevocably lost.\n\n"
1e6808ea 1188 "The optional @var{flags} argument is a value or bitwise OR of\n"
eefae538 1189 "@code{MSG_OOB}, @code{MSG_PEEK}, @code{MSG_DONTROUTE} etc.\n\n"
1e6808ea
MG
1190 "The value returned is a pair: the @emph{car} is the number of\n"
1191 "bytes read from the socket and the @emph{cdr} an address object\n"
eefae538
GH
1192 "in the same form as returned by @code{accept}. The address\n"
1193 "will given as @code{#f} if not available, as is usually the\n"
1194 "case for stream sockets.\n\n"
1e6808ea 1195 "The @var{start} and @var{end} arguments specify a substring of\n"
eefae538 1196 "@var{str} to which the data should be written.\n\n"
1e6808ea
MG
1197 "Note that the data is read directly from the socket file\n"
1198 "descriptor: any unread buffered port data is ignored.")
1bbd0b84 1199#define FUNC_NAME s_scm_recvfrom
370312ae
GH
1200{
1201 int rv;
1202 int fd;
1203 int flg;
60d02d09
GH
1204 char *buf;
1205 int offset;
1146b6cd 1206 int cend;
370312ae 1207 SCM address;
439006bf
GH
1208 int addr_size = MAX_ADDR_SIZE;
1209 char max_addr[MAX_ADDR_SIZE];
1210 struct sockaddr *addr = (struct sockaddr *) max_addr;
370312ae 1211
34d19ef6 1212 SCM_VALIDATE_OPFPORT (1, sock);
60d02d09
GH
1213 fd = SCM_FPORT_FDES (sock);
1214 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, str, buf, 4, start, offset,
1215 5, end, cend);
1146b6cd
GH
1216 if (SCM_UNBNDP (flags))
1217 flg = 0;
370312ae 1218 else
60d02d09 1219 SCM_VALIDATE_ULONG_COPY (3, flags, flg);
370312ae 1220
97d0e20b
GH
1221 /* recvfrom will not necessarily return an address. usually nothing
1222 is returned for stream sockets. */
439006bf 1223 addr->sa_family = AF_UNSPEC;
60d02d09 1224 SCM_SYSCALL (rv = recvfrom (fd, buf + offset,
1146b6cd 1225 cend - offset, flg,
439006bf 1226 addr, &addr_size));
370312ae 1227 if (rv == -1)
1bbd0b84 1228 SCM_SYSERROR;
eefae538 1229 if (addr->sa_family != AF_UNSPEC)
aca23b65 1230 address = scm_addr_vector (addr, addr_size, FUNC_NAME);
370312ae
GH
1231 else
1232 address = SCM_BOOL_F;
1233
e11e83f3 1234 return scm_cons (scm_from_int (rv), address);
0f2d19dd 1235}
1bbd0b84 1236#undef FUNC_NAME
0f2d19dd 1237
a1ec6916 1238SCM_DEFINE (scm_sendto, "sendto", 4, 0, 1,
1bbd0b84 1239 (SCM sock, SCM message, SCM fam, SCM address, SCM args_and_flags),
eefae538
GH
1240 "Transmit the string @var{message} on the socket port\n"
1241 "@var{sock}. The\n"
1242 "destination address is specified using the @var{fam},\n"
1243 "@var{address} and\n"
1244 "@var{args_and_flags} arguments, in a similar way to the\n"
1245 "@code{connect} procedure. @var{args_and_flags} contains\n"
1246 "the usual connection arguments optionally followed by\n"
1247 "a flags argument, which is a value or\n"
b380b885 1248 "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
eefae538
GH
1249 "The value returned is the number of bytes transmitted --\n"
1250 "it's possible for\n"
1251 "this to be less than the length of @var{message} if the\n"
1252 "socket is\n"
1253 "set to be non-blocking.\n"
1254 "Note that the data is written directly to the socket\n"
1255 "file descriptor:\n"
b380b885 1256 "any unflushed buffered port data is ignored.")
1bbd0b84 1257#define FUNC_NAME s_scm_sendto
370312ae
GH
1258{
1259 int rv;
1260 int fd;
1261 int flg;
1262 struct sockaddr *soka;
439006bf 1263 int size;
370312ae 1264
78446828 1265 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 1266 SCM_VALIDATE_FPORT (1, sock);
a6d9e5ab 1267 SCM_VALIDATE_STRING (2, message);
ee149d03 1268 fd = SCM_FPORT_FDES (sock);
7cee5b31 1269 soka = scm_fill_sockaddr (scm_to_int (fam), address, &args_and_flags, 4,
1bbd0b84 1270 FUNC_NAME, &size);
370312ae
GH
1271 if (SCM_NULLP (args_and_flags))
1272 flg = 0;
1273 else
1274 {
34d19ef6 1275 SCM_VALIDATE_CONS (5, args_and_flags);
e4b265d8 1276 flg = SCM_NUM2ULONG (5, SCM_CAR (args_and_flags));
370312ae 1277 }
439006bf
GH
1278 SCM_SYSCALL (rv = sendto (fd, SCM_STRING_CHARS (message),
1279 SCM_STRING_LENGTH (message),
ae2fa5bc 1280 flg, soka, size));
370312ae 1281 if (rv == -1)
439006bf
GH
1282 {
1283 int save_errno = errno;
1284 free (soka);
1285 errno = save_errno;
1286 SCM_SYSERROR;
1287 }
1288 free (soka);
e11e83f3 1289 return scm_from_int (rv);
370312ae 1290}
1bbd0b84 1291#undef FUNC_NAME
370312ae
GH
1292\f
1293
1294
1295void
0f2d19dd 1296scm_init_socket ()
0f2d19dd 1297{
370312ae
GH
1298 /* protocol families. */
1299#ifdef AF_UNSPEC
e11e83f3 1300 scm_c_define ("AF_UNSPEC", scm_from_int (AF_UNSPEC));
370312ae
GH
1301#endif
1302#ifdef AF_UNIX
e11e83f3 1303 scm_c_define ("AF_UNIX", scm_from_int (AF_UNIX));
370312ae
GH
1304#endif
1305#ifdef AF_INET
e11e83f3 1306 scm_c_define ("AF_INET", scm_from_int (AF_INET));
370312ae 1307#endif
3453619b 1308#ifdef AF_INET6
e11e83f3 1309 scm_c_define ("AF_INET6", scm_from_int (AF_INET6));
3453619b 1310#endif
370312ae
GH
1311
1312#ifdef PF_UNSPEC
e11e83f3 1313 scm_c_define ("PF_UNSPEC", scm_from_int (PF_UNSPEC));
370312ae
GH
1314#endif
1315#ifdef PF_UNIX
e11e83f3 1316 scm_c_define ("PF_UNIX", scm_from_int (PF_UNIX));
370312ae
GH
1317#endif
1318#ifdef PF_INET
e11e83f3 1319 scm_c_define ("PF_INET", scm_from_int (PF_INET));
370312ae 1320#endif
3453619b 1321#ifdef PF_INET6
e11e83f3 1322 scm_c_define ("PF_INET6", scm_from_int (PF_INET6));
3453619b 1323#endif
370312ae 1324
66c73b76
GH
1325 /* standard addresses. */
1326#ifdef INADDR_ANY
b9bd8526 1327 scm_c_define ("INADDR_ANY", scm_from_ulong (INADDR_ANY));
66c73b76
GH
1328#endif
1329#ifdef INADDR_BROADCAST
b9bd8526 1330 scm_c_define ("INADDR_BROADCAST", scm_from_ulong (INADDR_BROADCAST));
66c73b76
GH
1331#endif
1332#ifdef INADDR_NONE
b9bd8526 1333 scm_c_define ("INADDR_NONE", scm_from_ulong (INADDR_NONE));
66c73b76
GH
1334#endif
1335#ifdef INADDR_LOOPBACK
b9bd8526 1336 scm_c_define ("INADDR_LOOPBACK", scm_from_ulong (INADDR_LOOPBACK));
66c73b76
GH
1337#endif
1338
370312ae
GH
1339 /* socket types. */
1340#ifdef SOCK_STREAM
e11e83f3 1341 scm_c_define ("SOCK_STREAM", scm_from_int (SOCK_STREAM));
370312ae
GH
1342#endif
1343#ifdef SOCK_DGRAM
e11e83f3 1344 scm_c_define ("SOCK_DGRAM", scm_from_int (SOCK_DGRAM));
370312ae
GH
1345#endif
1346#ifdef SOCK_RAW
e11e83f3 1347 scm_c_define ("SOCK_RAW", scm_from_int (SOCK_RAW));
370312ae
GH
1348#endif
1349
1350 /* setsockopt level. */
1351#ifdef SOL_SOCKET
e11e83f3 1352 scm_c_define ("SOL_SOCKET", scm_from_int (SOL_SOCKET));
370312ae
GH
1353#endif
1354#ifdef SOL_IP
e11e83f3 1355 scm_c_define ("SOL_IP", scm_from_int (SOL_IP));
370312ae
GH
1356#endif
1357#ifdef SOL_TCP
e11e83f3 1358 scm_c_define ("SOL_TCP", scm_from_int (SOL_TCP));
370312ae
GH
1359#endif
1360#ifdef SOL_UDP
e11e83f3 1361 scm_c_define ("SOL_UDP", scm_from_int (SOL_UDP));
370312ae
GH
1362#endif
1363
1364 /* setsockopt names. */
1365#ifdef SO_DEBUG
e11e83f3 1366 scm_c_define ("SO_DEBUG", scm_from_int (SO_DEBUG));
370312ae
GH
1367#endif
1368#ifdef SO_REUSEADDR
e11e83f3 1369 scm_c_define ("SO_REUSEADDR", scm_from_int (SO_REUSEADDR));
370312ae
GH
1370#endif
1371#ifdef SO_STYLE
e11e83f3 1372 scm_c_define ("SO_STYLE", scm_from_int (SO_STYLE));
370312ae
GH
1373#endif
1374#ifdef SO_TYPE
e11e83f3 1375 scm_c_define ("SO_TYPE", scm_from_int (SO_TYPE));
370312ae
GH
1376#endif
1377#ifdef SO_ERROR
e11e83f3 1378 scm_c_define ("SO_ERROR", scm_from_int (SO_ERROR));
370312ae
GH
1379#endif
1380#ifdef SO_DONTROUTE
e11e83f3 1381 scm_c_define ("SO_DONTROUTE", scm_from_int (SO_DONTROUTE));
370312ae
GH
1382#endif
1383#ifdef SO_BROADCAST
e11e83f3 1384 scm_c_define ("SO_BROADCAST", scm_from_int (SO_BROADCAST));
370312ae
GH
1385#endif
1386#ifdef SO_SNDBUF
e11e83f3 1387 scm_c_define ("SO_SNDBUF", scm_from_int (SO_SNDBUF));
370312ae
GH
1388#endif
1389#ifdef SO_RCVBUF
e11e83f3 1390 scm_c_define ("SO_RCVBUF", scm_from_int (SO_RCVBUF));
370312ae
GH
1391#endif
1392#ifdef SO_KEEPALIVE
e11e83f3 1393 scm_c_define ("SO_KEEPALIVE", scm_from_int (SO_KEEPALIVE));
370312ae
GH
1394#endif
1395#ifdef SO_OOBINLINE
e11e83f3 1396 scm_c_define ("SO_OOBINLINE", scm_from_int (SO_OOBINLINE));
370312ae
GH
1397#endif
1398#ifdef SO_NO_CHECK
e11e83f3 1399 scm_c_define ("SO_NO_CHECK", scm_from_int (SO_NO_CHECK));
370312ae
GH
1400#endif
1401#ifdef SO_PRIORITY
e11e83f3 1402 scm_c_define ("SO_PRIORITY", scm_from_int (SO_PRIORITY));
370312ae
GH
1403#endif
1404#ifdef SO_LINGER
e11e83f3 1405 scm_c_define ("SO_LINGER", scm_from_int (SO_LINGER));
370312ae
GH
1406#endif
1407
1408 /* recv/send options. */
1409#ifdef MSG_OOB
e11e83f3 1410 scm_c_define ("MSG_OOB", scm_from_int (MSG_OOB));
370312ae
GH
1411#endif
1412#ifdef MSG_PEEK
e11e83f3 1413 scm_c_define ("MSG_PEEK", scm_from_int (MSG_PEEK));
370312ae
GH
1414#endif
1415#ifdef MSG_DONTROUTE
e11e83f3 1416 scm_c_define ("MSG_DONTROUTE", scm_from_int (MSG_DONTROUTE));
370312ae
GH
1417#endif
1418
b4e15479
SJ
1419#ifdef __MINGW32__
1420 scm_i_init_socket_Win32 ();
1421#endif
1422
0f2d19dd 1423 scm_add_feature ("socket");
370312ae 1424
a0599745 1425#include "libguile/socket.x"
0f2d19dd
JB
1426}
1427
89e00824
ML
1428
1429/*
1430 Local Variables:
1431 c-file-style: "gnu"
1432 End:
1433*/