*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libguile/fports.h"
#include "libguile/strings.h"
#include "libguile/vectors.h"
+#include "libguile/dynwind.h"
#include "libguile/validate.h"
#include "libguile/socket.h"
+ strlen ((ptr)->sun_path))
#endif
-/* we are not currently using socklen_t. it's not defined on all systems,
- so would need to be checked by configure. in the meantime, plain
- int is the best alternative. */
-
\f
SCM_DEFINE (scm_htons, "htons", 1, 0, 0,
{
scm_t_uint32 c_in = SCM_NUM2ULONG (1, value);
- return scm_ulong2num (htonl (c_in));
+ return scm_from_ulong (htonl (c_in));
}
#undef FUNC_NAME
{
scm_t_uint32 c_in = SCM_NUM2ULONG (1, value);
- return scm_ulong2num (ntohl (c_in));
+ return scm_from_ulong (ntohl (c_in));
}
#undef FUNC_NAME
#define FUNC_NAME s_scm_inet_aton
{
struct in_addr soka;
+ char *c_address;
+ int rv;
- SCM_VALIDATE_STRING (1, address);
- if (inet_aton (SCM_STRING_CHARS (address), &soka) == 0)
+ c_address = scm_to_locale_string (address);
+ rv = inet_aton (c_address, &soka);
+ free (c_address);
+ if (rv == 0)
SCM_MISC_ERROR ("bad address", SCM_EOL);
- return scm_ulong2num (ntohl (soka.s_addr));
+ return scm_from_ulong (ntohl (soka.s_addr));
}
#undef FUNC_NAME
SCM answer;
addr.s_addr = htonl (SCM_NUM2ULONG (1, inetid));
s = inet_ntoa (addr);
- answer = scm_mem2string (s, strlen (s));
+ answer = scm_from_locale_string (s);
return answer;
}
#undef FUNC_NAME
{
struct in_addr addr;
addr.s_addr = htonl (SCM_NUM2ULONG (1, address));
- return scm_ulong2num ((unsigned long) inet_netof (addr));
+ return scm_from_ulong (inet_netof (addr));
}
#undef FUNC_NAME
#endif
{
struct in_addr addr;
addr.s_addr = htonl (SCM_NUM2ULONG (1, address));
- return scm_ulong2num ((unsigned long) inet_lnaof (addr));
+ return scm_from_ulong (inet_lnaof (addr));
}
#undef FUNC_NAME
#endif
netnum = SCM_NUM2ULONG (1, net);
lnanum = SCM_NUM2ULONG (2, lna);
addr = inet_makeaddr (netnum, lnanum);
- return scm_ulong2num (ntohl (addr.s_addr));
+ return scm_from_ulong (ntohl (addr.s_addr));
}
#undef FUNC_NAME
#endif
static SCM
scm_from_ipv6 (const scm_t_uint8 *src)
{
- int i = 0;
- const scm_t_uint8 *ptr = src;
- int num_zero_bytes = 0;
- scm_t_uint8 addr[16];
-
- /* count leading zeros (since we know it's bigendian, they'll be first) */
- while (i < 16)
- {
- if (*ptr) break;
- num_zero_bytes++;
- i++;
- }
-
- if (SCM_SIZEOF_UNSIGNED_LONG_LONG != 0) /* compiler should optimize this */
- {
- if ((16 - num_zero_bytes) <= sizeof (unsigned long long))
- {
- /* it fits */
- unsigned long long x;
-
- FLIPCPY_NET_HOST_128(addr, src);
-#ifdef WORDS_BIGENDIAN
- memcpy (&x, addr + (16 - sizeof (x)), sizeof (x));
-#else
- memcpy (&x, addr, sizeof (x));
-#endif
- return scm_ulong_long2num (x);
- }
- }
- else
- {
- if ((16 - num_zero_bytes) <= sizeof (unsigned long))
- {
- /* this is just so that we use INUM where possible. */
- unsigned long x;
-
- FLIPCPY_NET_HOST_128(addr, src);
-#ifdef WORDS_BIGENDIAN
- memcpy (&x, addr + (16 - sizeof (x)), sizeof (x));
-#else
- memcpy (&x, addr, sizeof (x));
-#endif
- return scm_ulong2num (x);
- }
- }
- /* otherwise get the big hammer */
- {
- SCM result = scm_i_mkbig ();
-
- mpz_import (SCM_I_BIG_MPZ (result),
- 1, /* chunk */
- 1, /* big-endian chunk ordering */
- 16, /* chunks are 16 bytes long */
- 1, /* big-endian byte ordering */
- 0, /* "nails" -- leading unused bits per chunk */
- src);
- return scm_i_normbig (result);
- }
-}
+ SCM result = scm_i_mkbig ();
+ mpz_import (SCM_I_BIG_MPZ (result),
+ 1, /* chunk */
+ 1, /* big-endian chunk ordering */
+ 16, /* chunks are 16 bytes long */
+ 1, /* big-endian byte ordering */
+ 0, /* "nails" -- leading unused bits per chunk */
+ src);
+ return scm_i_normbig (result);
+}
/* convert a host ordered SCM integer to a 128 bit IPv6 address in
network order. */
int af;
char *src;
char dst[16];
- int rv;
+ int rv, eno;
af = scm_to_int (family);
SCM_ASSERT_RANGE (1, family, af == AF_INET || af == AF_INET6);
- SCM_VALIDATE_STRING_COPY (2, address, src);
+ src = scm_to_locale_string (address);
rv = inet_pton (af, src, dst);
+ eno = errno;
+ free (src);
+ errno = eno;
if (rv == -1)
SCM_SYSERROR;
else if (rv == 0)
SCM_MISC_ERROR ("Bad address", SCM_EOL);
if (af == AF_INET)
- return scm_ulong2num (ntohl (*(scm_t_uint32 *) dst));
+ return scm_from_ulong (ntohl (*(scm_t_uint32 *) dst));
else
return scm_from_ipv6 ((char *) dst);
}
scm_to_ipv6 (addr6, address);
if (inet_ntop (af, &addr6, dst, sizeof dst) == NULL)
SCM_SYSERROR;
- return scm_makfrom0str (dst);
+ return scm_from_locale_string (dst);
}
#undef FUNC_NAME
#endif
#ifdef HAVE_STRUCT_LINGER
struct linger *ling = (struct linger *) optval;
- return scm_cons (scm_long2num (ling->l_onoff),
- scm_long2num (ling->l_linger));
+ return scm_cons (scm_from_long (ling->l_onoff),
+ scm_from_long (ling->l_linger));
#else
- return scm_cons (scm_long2num (*(int *) optval),
+ return scm_cons (scm_from_long (*(int *) optval),
scm_from_int (0));
#endif
}
#endif
)
{
- return scm_long2num (*(size_t *) optval);
+ return scm_from_size_t (*(size_t *) optval);
}
}
- return scm_long2num (*(int *) optval);
+ return scm_from_int (*(int *) optval);
}
#undef FUNC_NAME
#define FUNC_NAME s_scm_setsockopt
{
int fd;
- int optlen = -1;
- /* size of optval is the largest supported option. */
+
+ int opt_int;
#ifdef HAVE_STRUCT_LINGER
- char optval[sizeof (struct linger)];
-#else
- char optval[sizeof (size_t)];
+ struct linger opt_linger;
#endif
+
+#if HAVE_STRUCT_IP_MREQ
+ struct ip_mreq opt_mreq;
+#endif
+
+ const void *optval = NULL;
+ socklen_t optlen = 0;
+
int ilevel, ioptname;
sock = SCM_COERCE_OUTPORT (sock);
ioptname = scm_to_int (optname);
fd = SCM_FPORT_FDES (sock);
-
+
if (ilevel == SOL_SOCKET)
{
#ifdef SO_LINGER
if (ioptname == SO_LINGER)
{
#ifdef HAVE_STRUCT_LINGER
- struct linger ling;
- long lv;
-
- SCM_ASSERT (SCM_CONSP (value), value, SCM_ARG4, FUNC_NAME);
- lv = SCM_NUM2LONG (4, SCM_CAR (value));
- ling.l_onoff = (int) lv;
- SCM_ASSERT_RANGE (SCM_ARG4, value, ling.l_onoff == lv);
- lv = SCM_NUM2LONG (4, SCM_CDR (value));
- ling.l_linger = (int) lv;
- SCM_ASSERT_RANGE (SCM_ARG4, value, ling.l_linger == lv);
- optlen = (int) sizeof (struct linger);
- memcpy (optval, (void *) &ling, optlen);
+ SCM_ASSERT (scm_is_pair (value), value, SCM_ARG4, FUNC_NAME);
+ opt_linger.l_onoff = scm_to_int (SCM_CAR (value));
+ opt_linger.l_linger = scm_to_int (SCM_CDR (value));
+ optlen = sizeof (struct linger);
+ optval = &opt_linger;
#else
- int ling;
- long lv;
-
- SCM_ASSERT (SCM_CONSP (value), value, SCM_ARG4, FUNC_NAME);
+ SCM_ASSERT (scm_is_pair (value), value, SCM_ARG4, FUNC_NAME);
+ opt_int = scm_to_int (SCM_CAR (value));
/* timeout is ignored, but may as well validate it. */
- lv = SCM_NUM2LONG (4, SCM_CDR (value));
- ling = (int) lv;
- SCM_ASSERT_RANGE (SCM_ARG4, value, ling == lv);
- lv = SCM_NUM2LONG (4, SCM_CAR (value));
- ling = (int) lv;
- SCM_ASSERT_RANGE (SCM_ARG4, value, ling == lv);
- optlen = (int) sizeof (int);
- (*(int *) optval) = ling;
+ scm_to_int (SCM_CDR (value));
+ optlen = sizeof (int);
+ optval = &opt_int;
#endif
}
else
#endif
)
{
- long lv = SCM_NUM2LONG (4, value);
-
- optlen = (int) sizeof (size_t);
- (*(size_t *) optval) = (size_t) lv;
+ opt_int = scm_to_int (value);
+ optlen = sizeof (size_t);
+ optval = &opt_int;
}
}
- if (optlen == -1)
+
+#if HAVE_STRUCT_IP_MREQ
+ if (ilevel == IPPROTO_IP &&
+ (ioptname == IP_ADD_MEMBERSHIP || ioptname == IP_DROP_MEMBERSHIP))
{
- /* Most options take an int. */
- long lv = SCM_NUM2LONG (4, value);
- int val = (int) lv;
+ /* Fourth argument must be a pair of addresses. */
+ SCM_ASSERT (scm_is_pair (value), value, SCM_ARG4, FUNC_NAME);
+ opt_mreq.imr_multiaddr.s_addr = htonl (scm_to_ulong (SCM_CAR (value)));
+ opt_mreq.imr_interface.s_addr = htonl (scm_to_ulong (SCM_CDR (value)));
+ optlen = sizeof (opt_mreq);
+ optval = &opt_mreq;
+ }
+#endif
- SCM_ASSERT_RANGE (SCM_ARG4, value, val == lv);
- optlen = (int) sizeof (int);
- (*(int *) optval) = val;
+ if (optval == NULL)
+ {
+ /* Most options take an int. */
+ opt_int = scm_to_int (value);
+ optlen = sizeof (int);
+ optval = &opt_int;
}
- if (setsockopt (fd, ilevel, ioptname, (void *) optval, optlen) == -1)
+
+ if (setsockopt (fd, ilevel, ioptname, optval, optlen) == -1)
SCM_SYSERROR;
return SCM_UNSPECIFIED;
}
soka = (struct sockaddr_in *) scm_malloc (sizeof (struct sockaddr_in));
if (!soka)
scm_memory_error (proc);
- /* 4.4BSD-style interface includes sin_len member and defines SIN_LEN,
- 4.3BSD does not. */
-#ifdef SIN_LEN
+#if HAVE_STRUCT_SOCKADDR_SIN_LEN
soka->sin_len = sizeof (struct sockaddr_in);
#endif
soka->sin_family = AF_INET;
SCM_VALIDATE_CONS (which_arg + 1, *args);
port = scm_to_int (SCM_CAR (*args));
*args = SCM_CDR (*args);
- if (SCM_CONSP (*args))
+ if (scm_is_pair (*args))
{
SCM_VALIDATE_ULONG_COPY (which_arg + 2, SCM_CAR (*args), flowinfo);
*args = SCM_CDR (*args);
- if (SCM_CONSP (*args))
+ if (scm_is_pair (*args))
{
SCM_VALIDATE_ULONG_COPY (which_arg + 3, SCM_CAR (*args),
scope_id);
soka = (struct sockaddr_in6 *) scm_malloc (sizeof (struct sockaddr_in6));
if (!soka)
scm_memory_error (proc);
-#ifdef SIN_LEN6
+#if HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
soka->sin6_len = sizeof (struct sockaddr_in6);
#endif
soka->sin6_family = AF_INET6;
{
struct sockaddr_un *soka;
int addr_size;
+ char *c_address;
+
+ scm_frame_begin (0);
+
+ c_address = scm_to_locale_string (address);
+ scm_frame_free (c_address);
- SCM_ASSERT (SCM_STRINGP (address), address, which_arg, proc);
/* the static buffer size in sockaddr_un seems to be arbitrary
and not necessarily a hard limit. e.g., the glibc manual
suggests it may be possible to declare it size 0. let's
connect/bind etc., to fail. sun_path is always the last
member of the structure. */
addr_size = sizeof (struct sockaddr_un)
- + max (0, SCM_STRING_LENGTH (address) + 1 - (sizeof soka->sun_path));
+ + max (0, strlen (c_address) + 1 - (sizeof soka->sun_path));
soka = (struct sockaddr_un *) scm_malloc (addr_size);
- if (!soka)
- scm_memory_error (proc);
memset (soka, 0, addr_size); /* for sun_len: see sin_len above. */
soka->sun_family = AF_UNIX;
- memcpy (soka->sun_path, SCM_STRING_CHARS (address),
- SCM_STRING_LENGTH (address));
+ strcpy (soka->sun_path, c_address);
*size = SUN_LEN (soka);
+
+ scm_frame_end ();
return (struct sockaddr *) soka;
}
#endif
result = scm_c_make_vector (3, SCM_UNSPECIFIED);
- SCM_VECTOR_SET(result, 0, scm_ulong2num ((unsigned long) fam));
- SCM_VECTOR_SET(result, 1, scm_ulong2num (ntohl (nad->sin_addr.s_addr)));
- SCM_VECTOR_SET(result, 2, scm_ulong2num ((unsigned long) ntohs (nad->sin_port)));
+ SCM_SIMPLE_VECTOR_SET(result, 0,
+ scm_from_short (fam));
+ SCM_SIMPLE_VECTOR_SET(result, 1,
+ scm_from_ulong (ntohl (nad->sin_addr.s_addr)));
+ SCM_SIMPLE_VECTOR_SET(result, 2,
+ scm_from_ushort (ntohs (nad->sin_port)));
}
break;
#ifdef HAVE_IPV6
const struct sockaddr_in6 *nad = (struct sockaddr_in6 *) address;
result = scm_c_make_vector (5, SCM_UNSPECIFIED);
- SCM_VECTOR_SET(result, 0, scm_ulong2num ((unsigned long) fam));
- SCM_VECTOR_SET(result, 1, scm_from_ipv6 (nad->sin6_addr.s6_addr));
- SCM_VECTOR_SET(result, 2, scm_ulong2num ((unsigned long) ntohs (nad->sin6_port)));
- SCM_VECTOR_SET(result, 3, scm_ulong2num ((unsigned long) nad->sin6_flowinfo));
+ SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_short (fam));
+ SCM_SIMPLE_VECTOR_SET(result, 1, scm_from_ipv6 (nad->sin6_addr.s6_addr));
+ SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_ushort (ntohs (nad->sin6_port)));
+ SCM_SIMPLE_VECTOR_SET(result, 3, scm_from_uint32 (nad->sin6_flowinfo));
#ifdef HAVE_SIN6_SCOPE_ID
- SCM_VECTOR_SET(result, 4, scm_ulong2num ((unsigned long) nad->sin6_scope_id));
+ SCM_SIMPLE_VECTOR_SET(result, 4, scm_from_ulong (nad->sin6_scope_id));
#else
- SCM_VECTOR_SET(result, 4, SCM_INUM0);
+ SCM_SIMPLE_VECTOR_SET(result, 4, SCM_INUM0);
#endif
}
break;
result = scm_c_make_vector (2, SCM_UNSPECIFIED);
- SCM_VECTOR_SET(result, 0, scm_ulong2num ((unsigned long) fam));
+ SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_short (fam));
/* When addr_size is not enough to cover sun_path, do not try
to access it. */
if (addr_size <= offsetof (struct sockaddr_un, sun_path))
- SCM_VECTOR_SET(result, 1, SCM_BOOL_F);
+ SCM_SIMPLE_VECTOR_SET(result, 1, SCM_BOOL_F);
else
- SCM_VECTOR_SET(result, 1, scm_mem2string (nad->sun_path,
- strlen (nad->sun_path)));
+ SCM_SIMPLE_VECTOR_SET(result, 1, scm_from_locale_string (nad->sun_path));
}
break;
#endif
int rv;
int fd;
int flg;
+ char *dest;
+ size_t len;
SCM_VALIDATE_OPFPORT (1, sock);
SCM_VALIDATE_STRING (2, buf);
flg = scm_to_int (flags);
fd = SCM_FPORT_FDES (sock);
- SCM_SYSCALL (rv = recv (fd, SCM_STRING_CHARS (buf), SCM_STRING_LENGTH (buf), flg));
+ len = scm_i_string_length (buf);
+ dest = scm_i_string_writable_chars (buf);
+ SCM_SYSCALL (rv = recv (fd, dest, len, flg));
+ scm_i_string_stop_writing ();
+
if (rv == -1)
SCM_SYSERROR;
+ scm_remember_upto_here_1 (buf);
return scm_from_int (rv);
}
#undef FUNC_NAME
int rv;
int fd;
int flg;
+ const char *src;
+ size_t len;
sock = SCM_COERCE_OUTPORT (sock);
SCM_VALIDATE_OPFPORT (1, sock);
flg = scm_to_int (flags);
fd = SCM_FPORT_FDES (sock);
- SCM_SYSCALL (rv = send (fd, SCM_STRING_CHARS (message), SCM_STRING_LENGTH (message), flg));
+ len = scm_i_string_length (message);
+ src = scm_i_string_writable_chars (message);
+ SCM_SYSCALL (rv = send (fd, src, len, flg));
+ scm_i_string_stop_writing ();
+
if (rv == -1)
SCM_SYSERROR;
+
+ scm_remember_upto_here_1 (message);
return scm_from_int (rv);
}
#undef FUNC_NAME
int fd;
int flg;
char *buf;
- int offset;
- int cend;
+ size_t offset;
+ size_t cend;
SCM address;
int addr_size = MAX_ADDR_SIZE;
char max_addr[MAX_ADDR_SIZE];
SCM_VALIDATE_OPFPORT (1, sock);
fd = SCM_FPORT_FDES (sock);
- SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, str, buf, 4, start, offset,
- 5, end, cend);
+
+ SCM_VALIDATE_STRING (2, str);
+ scm_i_get_substring_spec (scm_i_string_length (str),
+ start, &offset, end, &cend);
+
if (SCM_UNBNDP (flags))
flg = 0;
else
/* recvfrom will not necessarily return an address. usually nothing
is returned for stream sockets. */
+ buf = scm_i_string_writable_chars (str);
addr->sa_family = AF_UNSPEC;
SCM_SYSCALL (rv = recvfrom (fd, buf + offset,
cend - offset, flg,
addr, &addr_size));
+ scm_i_string_stop_writing ();
+
if (rv == -1)
SCM_SYSERROR;
if (addr->sa_family != AF_UNSPEC)
else
address = SCM_BOOL_F;
+ scm_remember_upto_here_1 (str);
return scm_cons (scm_from_int (rv), address);
}
#undef FUNC_NAME
fd = SCM_FPORT_FDES (sock);
soka = scm_fill_sockaddr (scm_to_int (fam), address, &args_and_flags, 4,
FUNC_NAME, &size);
- if (SCM_NULLP (args_and_flags))
+ if (scm_is_null (args_and_flags))
flg = 0;
else
{
SCM_VALIDATE_CONS (5, args_and_flags);
flg = SCM_NUM2ULONG (5, SCM_CAR (args_and_flags));
}
- SCM_SYSCALL (rv = sendto (fd, SCM_STRING_CHARS (message),
- SCM_STRING_LENGTH (message),
+ SCM_SYSCALL (rv = sendto (fd,
+ scm_i_string_chars (message),
+ scm_i_string_length (message),
flg, soka, size));
if (rv == -1)
{
SCM_SYSERROR;
}
free (soka);
+
+ scm_remember_upto_here_1 (message);
return scm_from_int (rv);
}
#undef FUNC_NAME
/* standard addresses. */
#ifdef INADDR_ANY
- scm_c_define ("INADDR_ANY", scm_ulong2num (INADDR_ANY));
+ scm_c_define ("INADDR_ANY", scm_from_ulong (INADDR_ANY));
#endif
#ifdef INADDR_BROADCAST
- scm_c_define ("INADDR_BROADCAST", scm_ulong2num (INADDR_BROADCAST));
+ scm_c_define ("INADDR_BROADCAST", scm_from_ulong (INADDR_BROADCAST));
#endif
#ifdef INADDR_NONE
- scm_c_define ("INADDR_NONE", scm_ulong2num (INADDR_NONE));
+ scm_c_define ("INADDR_NONE", scm_from_ulong (INADDR_NONE));
#endif
#ifdef INADDR_LOOPBACK
- scm_c_define ("INADDR_LOOPBACK", scm_ulong2num (INADDR_LOOPBACK));
+ scm_c_define ("INADDR_LOOPBACK", scm_from_ulong (INADDR_LOOPBACK));
#endif
- /* socket types. */
+ /* socket types.
+
+ SOCK_PACKET is deliberately omitted, the GNU/Linux socket(2) and
+ packet(7) advise that it's obsolete and strongly deprecated. */
+
#ifdef SOCK_STREAM
scm_c_define ("SOCK_STREAM", scm_from_int (SOCK_STREAM));
#endif
#ifdef SOCK_DGRAM
scm_c_define ("SOCK_DGRAM", scm_from_int (SOCK_DGRAM));
#endif
+#ifdef SOCK_SEQPACKET
+ scm_c_define ("SOCK_SEQPACKET", scm_from_int (SOCK_SEQPACKET));
+#endif
#ifdef SOCK_RAW
scm_c_define ("SOCK_RAW", scm_from_int (SOCK_RAW));
#endif
+#ifdef SOCK_RDM
+ scm_c_define ("SOCK_RDM", scm_from_int (SOCK_RDM));
+#endif
/* setsockopt level. */
#ifdef SOL_SOCKET
scm_i_init_socket_Win32 ();
#endif
+#ifdef IP_ADD_MEMBERSHIP
+ scm_c_define ("IP_ADD_MEMBERSHIP", scm_from_int (IP_ADD_MEMBERSHIP));
+ scm_c_define ("IP_DROP_MEMBERSHIP", scm_from_int (IP_DROP_MEMBERSHIP));
+#endif
+
scm_add_feature ("socket");
#include "libguile/socket.x"