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