9.19 gauche.net - Networking

Provides a set of functions necessary for network communications
based on BSD socket interface.

The API is provided in two different levels. Lower level routines
reflect traditional BSD socket interface, such as bind(2).
Higher level routines provides more convenient way to create
typical connection-oriented server/client sockets.

This module also provides APIs to obtain various information
about hostnames, service ports, and protocols.

Gauche can handle IPv6 if it is compiled
with the --enable-ipv6 configuration option.
To check whether IPv6 is enabled or not,
you can use cond-expand with
gauche.net.ipv6 feature identifier
after loading gauche.net, as shown below.

9.19.1 Socket address

Socket address objects

An abstract base class of socket addresses. Each socket address family
is implemented as a subclass of this class.

Although socket addresses are built-in classes, you can use
make method to create an instance of a
specific socket address family.

Generic Function: sockaddr-familyaddr

Returns a symbol that indicates the family of the socket address
addr.

Generic Function: sockaddr-nameaddr

Returns a string which represents the content of the socket address
addr.

Builtin Class: <sockaddr-in>

AF_INET family socket address. To create an instance of this class,
use make method as follows:

(make <sockaddr-in> :host host :port port)

host can be a string, an integer IP address, a
u8vector IP address, or one of the keywords
:any, :broadcast, :none or :loopback.
If it is a string, it is either a host name or a dotted IP notation.
Gauche uses gethostbyname(3) to obtain the actual IP address from
host parameter. If it is a keyword :any,
or :broadcast, the address
uses INADDR_ANY, or INADDR_BROADCAST
respectively. The keyword :loopback is a synonym to the
IPv4 loopback address "127.0.0.1".

port must be a positive integer indicating the port number.
See also make-sockaddrs below, to create multiple
socket addresses on the machine which may have more than one
protocol stack.

Method: sockaddr-family(addr <sockaddr-in>)

Returns a symbol inet.

Method: sockaddr-name(addr <sockaddr-in>)

Returns a string in the form "a.b.c.d:port",
where "a.b.c.d" is dotted decimal notion of
the IP address and port is the port number.

Method: sockaddr-addr(addr <sockaddr-in>)

Method: sockaddr-port(addr <sockaddr-in>)

Returns the IP address and the port number as an integer, respectively.

Builtin Class: <sockaddr-un>

AF_UNIX family socket address. To create an instance of this class,
use make method as follows:

(make <sockaddr-un> :path path)

path must be a string specifying pathname of the socket.

Method: sockaddr-family(addr <sockaddr-un>)

Returns a symbol unix.

Method: sockaddr-name(addr <sockaddr-un>)

Returns a pathname of the socket address.

Builtin Class: <sockaddr-in6>

AF_INET6 family socket address. This is only available if
gauche is configured with –enable-ipv6 configure option.
The constructor and the slots are the same as <sockaddr-in>.
See also make-sockaddrs below, to create multiple
socket addresses on the machine which may have more than one
protocol stack.

Function: make-sockaddrshost port :optional proto

This is a higher-level utility procedure to create all possible
inet domain socket addresses that point to host:port
of protocol proto. Particularly, if the specified host has
both IPv4 and IPv6 addresses, and the running system supports both,
then both IPv4 and IPv6 socket addresses are returned. If host has
multiple IP addresses, socket addresses are created for each of these
IP address. You can make your network application much more portable
among different network stack configurations.

Passing #f to host creates the local
(server) address. You can also pass a service name (e.g. "http")
instead of an integer, to the port argument.
The value of proto can be either a symbol tcp or udp,
and the default is tcp.

It always returns a list of socket addresses. If the lookup of host
is failed, null list is returned.

Address and string conversion

Function: inet-string->addressaddress

Converts string representating of the internet address address
to an integer address. If address is parsed successfully,
returns two values: the integer address value and the recognized
protocol (the constant value 2 (= AF_INET)
for IPv4 addresses, and 10 (= AF_INET6)
for IPv6 addresses). If address can’t be
parsed, #f and #f are returned.

Like inet-string->address, but fills the given u8vector
buf by the parsed address instead of returning it as
an integer value. The integer representation of inet addresses
is likely to be a bignum, and you can avoid creating bignums
with this function. The given u8vector buf must be mutable.
Returns the protocol on success, or #f on failure.

The caller must provide big enough buffer. If buf
is larger than required, the result is filled from the top
of the u8vector and the rest of the vector remains intact.

Converts the given address to its string representation
of the protocol protocol, which can be either
2 (the constant AF_INET) or 10
(the constant AF_INET6).
An integer or a u8vector can be used as address. If it is
a u8vector, only the necessary portion of the vector is read; i.e.
the vector can be longer than the required length.

9.19.2 High-level network functions

Builtin Class: <socket>

Abstracts a socket, a communication endpoint.

For a connection-oriented socket, you can access the communication
channel by two ports associated to the socket, one for input and
another for output. socket-input-port and socket-output-port
returns those ports, respectively.

The following three functions are convenient ways to create
a connection-oriented socket. Those functions
are to provide an easy methods for typical cases,
but have less control. If you need more than these functions
provide, use low-level interface.

Function: make-client-socket:optional address-spec …

Creates and returns a client socket, connected to the address
specified by address-spec ….

(make-client-socket 'unix path)

The client socket is connected to the unix domain server socket
of address path.

(make-client-socket 'inet hostport)

The client socket is connected to the inet domain server socket
with hostname host and port port. TCP protocol is
assumed. host can be either a hostname, or
a dotted decimal notation of IPv4 address.
If gauche is compiled with –enable-ipv6, IPv6 address notation
can also be used. Port must be an exact integer specifying
a port number, or a string service name (e.g. "http").

If gauche is compiled with –enable-ipv6, and the hostname is given,
and the hostname has both IPv6 and IPv4 addresses, then
IPv6 connection is tried first, and IPv4 is used when IPv6 fails.

(make-client-socket hostport)

This works the same as above. This form is for compatibility with STk.

(make-client-socket sockaddr)

If an instance of <sockaddr> is passed,
a socket suitable for sockaddr is opened and then connected
to the given address.

This function raises an error if it cannot create a socket,
or cannot connect to the specified address.

Creates and returns a server socket, listening the address
specified by address-spec.

(make-server-socket 'unix path [:backlog num])

The socket is bound to a unix domain socket with a name path.
The keyword argument backlog is passed to socket-listen
to specify the maximum number of connection request the server can keep
before accepting them. The default is 5. If your server is very busy
and you see "connection refused" often, you might want to increase it.

The socket is bound to an inet domain TCP socket, listening
port port, which must be a non-negative exact integer
or a string service name (e.g. "http").
If port is zero, the system assigns one of available port numbers.
If a keyword argument reuse-addr? is given and true,
SO_REUSEADDR option is set to the socket before bound to
the port. This allows the process to bind the server socket
immediately after other process releases the port.

Alternatively, you can pass a list of positive exact integers to port.
In that case, Gauche tries to bind each port in the list until it succeeds.

If keyword argument sock-init is given, it should be a procedure
that takes two arguments, a created socket and the socket address.
The procedure is called just after the socket is created. It is
useful to set some special socket options.
The keyword argument backlog is the same as in unix sockets;
see the description above.

Creates one or more sockets that listen at port
on all available network interfaces of host.
You can specify a service name (such as "http") to
port, as well as an integer port number.
Returns a list of opened, bound and listened sockets.

This procedure is particularly useful when the host
has multiple protocol stacks, such as IPv4 and IPv6.
In that case, this procedure may return a list of IPv4 socket(s) and
IPv6 socket(s).
(On some OSes, single socket can listen both IPv4 and IPv6. On
such platform, a list of single socket will be returned.)

The meaning of keyword arguments are the same as of make-server-socket.

You can pass 0 to port, just like make-server-socket,
to let the system choose an available port number. If pass 0 as
port and this procedure returns multiple sockets, it is guaranteed
that all the sockets share the same port number.

Several accessors are available on the returned socket object.

Function: socket-addresssocket

Returns a socket address associated with socket.
If no address has been associated to the socket, #f is returned.

Function: socket-input-portsocket :key (buffering :modest)

Function: socket-output-portsocket :key (buffering :line)

Returns an input and output port associated with socket,
respectively.

The keyword argument buffering specifies the buffering mode
of the port. See File ports, for explanation of the
buffering mode.

Function: socket-closesocket

Closes socket. All the ports associated to
socket are closed as well.
Note: as of release 0.7.2, this procedure does not shutdown
the connection. It is because socket may be referenced
by forked process(es) and you might want to close it without
interfering the existing connection. You can call
socket-shutdown to shutdown the connection explicitly.

socket must be a connected client socket. proc is called
with two arguments, an input port that reads from the socket
and an output port that writes to the socket.
The socket is closed after proc returns or proc
raises an error.

The keyword arguments input-buffering and output-buffering
are, if given, passed as the buffering keyword arguments
of socket-input-port and socket-output-port, respectively.

This is an example of usage of high-level socket functions,
a very simple http client.

9.19.3 Low-level socket interface

These functions provide APIs similar to the system calls.
Those who are familiar to programming with socket APIs will
find these functions useful since you can have more detailed control over
the sockets.

Function: make-socketdomain type :optional protocol

Returns a socket with specified parameters.

Constant: PF_UNIX

Constant: PF_INET

Constant: PF_INET6

These constants are bound to the system’s constants
PF_UNIX, PF_INET and PF_INET6.
You can use those values for domain argument of make-socket.

(PF_INET6 is defined only if the underlying operating
system supports IPv6.)

Constant: AF_UNIX

Constant: AF_INET

Constant: AF_INET6

These constants are bound to AF_UNIX,
AF_INET and AF_INET6.

(AF_INET6 is defined only if the underlying operating
system supports IPv6.)

Constant: SOCK_STREAM

Constant: SOCK_DGRAM

Constant: SOCK_RAW

These constants are bound to SOCK_STREAM, SOCK_DGRAM
and SOCK_RAW, and suitable to pass to the type argument
of make-socket.

Function: socket-fdsocket

Returns an integer system file descriptor of the underlying socket.

Function: socket-statussocket

Returns a internal status of socket, by one of the following
symbols.

none

The socket is just created.

bound

The socket is bound to an address by socket-bind

listening

The socket is listening a connection by socket-listen

connected

The socket is connected by socket-connect or socket-accept.

shutdown

The socket is shutdown by socket-shutdown

closed

The socket is closed by socket-close.

Function: socket-bindsocket address

Binds socket to the local network address address.
It is usually used to associate specific address to the server port.
If binding failed, an error is signaled (most likely the address is
already in use).

For the inet domain address, you can pass address with port=0;
the system assigns the port number and sets the actual address to
the address slot of socket.

Function: socket-listensocket backlog

Listens socket. The socket must be already bound to some
address. backlog specifies maximum number of connection
requests to be queued.

Function: socket-acceptsocket

Accepts a connection request coming to socket.
Returns a new socket that is connected to the remote entity.
The original socket keeps waiting for further connections.
If there’s no connection requests, this call waits for one to come.

You can use sys-select to check if there’s a pending connection
request.

Function: socket-connectsocket address

Connects socket to the remote address address.
This is the way for a client socket to connect to the remote entity.

Function: socket-shutdownsocket how

Shuts down connection of socket. If how is SHUT_RD (or 0),
the receive channel of socket is disallowed.
If how is SHUT_WR (or 1), the send channel of
socket is disallowed.
If how is SHUT_RDWR (or 2), both receive and send channels are
disallowed. It is an error to call this function on a non-connected socket.

If you shut down the send channel of the socket, the remote peer
sees EOF from its receive channel. This is useful if the remote peer
expects EOF before sending something back to you.

Function: socket-getsocknamesocket

Returns a <sockaddr> instance that is the local address of
socket.

Function: socket-getpeernamesocket

Returns a <sockaddr> instance that is the peer address of
socket.

Function: socket-sendsocket msg :optional flags

Function: socket-sendtosocket msg to-address :optional flags.

Interfaces to send(2) and sendto(2), respectively.
Transmits the content of msg through socket.
msg can be either a string or a uniform vector; if you send
binary packets, uniform vectors are recommended.

Returns the nubmer of octets that are actually sent.

When socket-send is used, socket must already be connected.
On the other hand, socket-sendto can be used for non-connected
socket, and the destination address is specified by
a <sockaddr> instance to-address.

The optional flags can be a bitwise OR of the integer
constants MSG_*. See the system’s manpage of send(2)
and sendto(2) for the details.

Function: socket-sendmsgsocket msghdr :optional flags

Sends a packet described by msghdr through socket
using sendmsg(3). The msghdr argument must be a
string or u8vector, and it must be prepared as a binary representation
of struct msghdr. A reliable way to build a msghdr is
to use socket-buildmsg described below.

The flags argument is the same as socket-send and
socket-sendto.

Returns number of octets sent.

This procedure is not yet supported under the Windows native platform.
You can use the feature identifier gauche.os.windows to check
availability of this procedure (see Platform-dependent features).

Function: socket-buildmsgaddr iov control flags :optional buf

Builds a binary representation of struct msghdr which is
suitable to be given to socket-sendmsg.
You have to be familiar with sendmsg(3) system call
to understand this procedure.

The addr argument must be an instance of <sockaddr>
or #f. If it is a sockaddr, the msg_name field
of the msghdr is filled with the address.

The iov argument must be a vector or #f. If it is
a vector, each element must be either a string or a u8vector.
They are used to fill msg_iov field of the msghdr.
Their contents will be concatenated in the kernel to make a payload.

The control argument represents ancillary data, a.k.a. cmsg.
It can be #f if you don’t need ancillary data. Otherwise,
it must be a list in the following form:

((leveltypedata) …)

Where level and type are exact integers,
and data is either a string or a u8vector.
The former two are used to fill cmsg’s cmsg_level
and cmsg_type fields. The data is for
cmsg’s data (cmsg_len is calculated from data).

The flags argument is used to fill msg_flags.

If the buf argument is #f or omitted, new memories
are allocated to construct the msghdr. If a mutable
u8vector is given to buf, socket-buildmsg tries
to use it to construct the msghdr as much as possible; it allocates
memory only if buf is used up.

Returns the constructed msghdr as a u8vector.

This procedure is not yet supported under the Windows native platform.
You can use the feature identifier gauche.os.windows to check
availability of this procedure (see Platform-dependent features).

Function: socket-recv!socket buf :optional flags

Interface to recv(2). Receives a message from socket,
and stores it into buf, which must be a mutable uniform vector.
Returns the number of bytes actually written. socket must
be already connected. If the size of buf isn’t enough to
store the entire message, the rest may be discarded depending on
the type of socket.

The optional flags can be a bitwise OR of the integer
constants MSG_*. See the system’s manpage of recv(2)
for the details.

Function: socket-recvfrom!socket buf addrs :optional flags

Interface to recvfrom(2). Receives a message from
socket, which may be unconnected, and stores it to
a mutable uniform vector buf. Like socket-recv,
if the size of buf isn’t enough to store the entire message,
the rest may be discarded depending on the type of socket.

Returns two values; the number of bytes actually written into
buf, and an instance of a subclass of <sys-sockaddr>
which shows the sender’s address.

The addrs argument must be a list of instances of socket
addresses, optionally its last cdr being #t (as a special
case, if there’s zero addresses to pass, just #t may be given).
The content of each address doesn’t matter; if the protocol family
of one of them matches the sender’s address, the sender’s address
is written into the passed sockaddr object. By listing sockaddrs
of possible families, you can count on socket-recvfrom!
to allocate no memory on successful operation. It is useful if
you call socket-recvfrom! in a speed-sensitive inner loop.

If the sender’s address family doesn’t match any of the addresses
given to addrs, the behavior depends on whether the list is
terminated by () or #t. If it is terminated by (),
(i.e. addrs is a proper list), the sender’s address is simply
discarded and socket-recvfrom! returns #f as the
second value. If the list is terminated by #t,
socket-recvfrom! allocates a fresh sockaddr object and
returns it as the second value.

Two simple cases: If you pass () to addrs, the sender’s
address is always discarded, which is useful if socket is
connected (that is, you already know your sender’s address).
If you pass #t to addrs, a new socket address
object is always allocated for the sender’s address,
which is convenient if you don’t mind memory allocation.

The optional flags can be a bitwise OR of the integer
constants MSG_*. See the system’s manpage of recvfrom(2)
for the details.

Function: socket-recvsocket bytes :optional flags

Function: socket-recvfromsocket bytes :optional flags

Like socket-recv! and socket-recvfrom!, but
these returns the received message as a (possibly incomplete)
string, up to bytes size. Additionally,
socket-recvfrom always allocates a socket address
object for the sender’s address.

The use of these procedures are discouraged, since they
often returns incomplete strings for binary messages.
Using strings for binary data creates many pitfalls.
Uniform vectors (especially u8vectors) are for binary data.
(The reason these procedures return strings is merely historical.)

Variable: MSG_CTRUNC

Variable: MSG_DONTROUTE

Variable: MSG_EOR

Variable: MSG_OOB

Variable: MSG_PEEK

Variable: MSG_TRUNC

Variable: MSG_WAITALL

Pre-defined integer constants to be used as flags values
for socket-send, socket-sendto, socket-recv
and socket-recvfrom. Some of these constants may not be
defined if the underlying operating system doesn’t provide them.

Further control over sockets and protocol layers is possible
by getsockopt/setsockopt interface, as described below.

Function: socket-setsockoptsocket level option value

Function: socket-getsockoptsocket level option rsize

These are the interface to setsockopt() and getsockopt() calls.
The interface is a bit clumsy, in order to allow full access to
those low-level calls.

socket must be a non-closed socket object.
level and option is an exact integer to specify
the level of protocol stack and the option you want to deal with.
There are several variables pre-bound to system constants listed below.

To set the socket option, you can pass either an exact integer or
a string to value. If it is an integer, the value is passed
to setsockopt(2) as C int value. If it is a string, the
byte sequence is passed as is. The required type of value depends on
the option, and Gauche can’t know if the value you passed is expected
by setsockopt(2); it is your responsibility to pass the correct values.

To get the socket option, you need to tell the maximum length of expected
result by rsize parameter, for Gauche doesn’t know the amount
of data each option returns.
socket-getsockopt returns the option value as a byte string.
If you know the option value is an integer, you can pass 0 to rsize;
in that case socket-getsockopt returns the value as an exact integer.

Note about the name: I tempted to name these function socket-{set|get}opt
or socket-{set|get}-option,
but I rather took the naming consistency. Hence duplicated "sock"s.

The following predefined variables are provided.
Note that some of them are not available on all platforms.
See manpages socket(7), tcp(7) or ip(7) of
your system to find out exact specification of those values.

For “level” argument:

Variable: SOL_SOCKET

Variable: SOL_TCP

Variable: SOL_IP

These variables are bound to SOL_SOCKET, SOL_TCP and
SOL_IP, respectively.

For “option” argument:

Variable: SO_KEEPALIVE

Expects integer value. If it is not zero, enables sending of
keep-alive messages on connection-oriented sockets.

Variable: SO_OOBINLINE

Expects integer value. If it is not zero, out-of-band data is
directly placed into the receive data stream. Otherwise
out-of-band data is only passed when the
MSG_OOB flag is set during receiving.

Variable: SO_REUSEADDR

Expects integer value. If it is not zero, socket-bind
allows to reuse local addresses, unless an active listening
socket bound to the address.

Variable: SO_TYPE

Gets the socket type as an integer (like sock_stream).
Can be only used with socket-getsockopt.

Variable: SO_BROADCAST

Expects integer value. If it is not zero, datagram sockets
are allowed to send/receive broadcast packets.

Variable: SO_PRIORITY

Expects integer value, specifying the protocol-defined priority
for all packets to be sent on this socket.

Variable: SO_ERROR

Gets and clears the pending socket error as an integer.
Can be only used with socket-getsockopt.

Function: inet-checksumpacket size

Calculates one’s complement of Internet Checksum (RFC1071) of the
packet, which must be given as a uniform vector. First
size bytes of packet are used for calculation.
Returned value is in network byte order (big-endian).
It is an error if size is greater than the size of packet.

Looks up a host that has an address addr of protocol proto.
addr is a natural string representation of the address;
for ipv4, it is a dotted decimal notation. proto is a
protocol number; only AF_INET is supported currently.
If the host is found, returns a <sys-hostent> object.
Otherwise, returns #f.

An entry of the network service database. Corresponding to
struct servent in C. The following slots are available read-only.

Instance Variable of <sys-servent>: name

The formal name of the service (string).

Instance Variable of <sys-servent>: aliases

A list of alias names of the service (list of strings).

Instance Variable of <sys-servent>: port

A port number registered for this service (exact integer).

Instance Variable of <sys-servent>: proto

A protocol name for this service (string).

Function: sys-getservbynamename proto

Looks up the network service database with a service name name and
a protocol proto. Both name and proto must be a string.
If a service is found, an instance of <sys-servent> is returned.
Otherwise, #f is returned.

Looks up the network service database with a service port port and
a protocol proto. port must be an exact integer, and
proto must be a string.
If a service is found, an instance of <sys-servent> is returned.
Otherwise, #f is returned.

The new interface to keep address information.
Corresponds to struct addrinfo in C.
This is only available if gauche is configured with –enable-ipv6 option.
The following slots are provided.

Instance Variable of <sys-addrinfo>: flags

Instance Variable of <sys-addrinfo>: family

Instance Variable of <sys-addrinfo>: socktype

Instance Variable of <sys-addrinfo>: protocol

Instance Variable of <sys-addrinfo>: addrlen

Instance Variable of <sys-addrinfo>: addr

Function: sys-getaddrinfonodename servname hints

Returns a list of <sys-addrinfo> instances from the given nodename,
servname and hints.
This is only available if gauche is compiled with –enable-ipv6 option.

Function: sys-ntohsinteger

Function: sys-ntohlinteger

Function: sys-htonsinteger

Function: sys-htonlinteger

Utility functions to convert 16bit (s) or 32bit (l) integers
between network byte order (n) and host byte order
(h).

Scheme API to the netdb interface calls those byte order conversion
functions internally, so you don’t usually need them so much as in C
programs. However, it may be useful when you’re constructing or
analyzing binary packets. See also Packing Binary Data to handle
binary data.