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