*
* 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
*/
+ 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 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
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_from_ulong_long (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_from_ulong (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. */
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
#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))
+ {
+ /* 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
+
+ if (optval == NULL)
{
/* Most options take an int. */
- long lv = SCM_NUM2LONG (4, value);
- int val = (int) lv;
-
- SCM_ASSERT_RANGE (SCM_ARG4, value, val == lv);
- optlen = (int) sizeof (int);
- (*(int *) optval) = val;
+ 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;
result = scm_c_make_vector (3, SCM_UNSPECIFIED);
- SCM_VECTOR_SET(result, 0,
- scm_from_short (fam));
- SCM_VECTOR_SET(result, 1,
- scm_from_ulong (ntohl (nad->sin_addr.s_addr)));
- SCM_VECTOR_SET(result, 2,
- scm_from_ushort (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_from_short (fam));
- SCM_VECTOR_SET(result, 1, scm_from_ipv6 (nad->sin6_addr.s6_addr));
- SCM_VECTOR_SET(result, 2, scm_from_ushort (ntohs (nad->sin6_port)));
- SCM_VECTOR_SET(result, 3, scm_from_uint32 (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_from_ulong (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_from_short (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_I_STRING_CHARS (buf), SCM_I_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;
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_I_STRING_CHARS (message),
- SCM_I_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;
fd = SCM_FPORT_FDES (sock);
SCM_VALIDATE_STRING (2, str);
- buf = SCM_I_STRING_CHARS (str);
- scm_i_get_substring_spec (SCM_I_STRING_LENGTH (str),
+ scm_i_get_substring_spec (scm_i_string_length (str),
start, &offset, end, &cend);
if (SCM_UNBNDP (flags))
/* 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)
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
{
flg = SCM_NUM2ULONG (5, SCM_CAR (args_and_flags));
}
SCM_SYSCALL (rv = sendto (fd,
- SCM_I_STRING_CHARS (message),
- SCM_I_STRING_LENGTH (message),
+ scm_i_string_chars (message),
+ scm_i_string_length (message),
flg, soka, size));
if (rv == -1)
{
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"