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