# Package SB-BSD-SOCKETS

A thinly-disguised BSD socket API for SBCL. Ideas stolen from the BSD socket API for C and Graham Barr's IO::Socket classes for Perl.

We represent sockets as CLOS objects, and rename a lot of methods and arguments to fit Lisp style more closely.

## Contents

1. General concepts
2. Methods applicable to all sockets
3. Socket Options
4. Methods applicable to a particular subclass
   1. INET-SOCKET - Internet Protocol (TCP, UDP, raw) sockets
   2. Methods on UNIX-SOCKET - Unix-domain sockets
5. Name resolution (DNS, /etc/hosts, &c)

## General concepts

Most of the functions are modelled on the BSD socket API. BSD sockets are widely supported, portably ("portable" by Unix standards, at least) available on a variety of systems, and documented. There are some differences in approach where we have taken advantage of some of the more useful features of Common Lisp - briefly

- Where the C API would typically return -1 and set errno, bsd-sockets signals an error. All the errors are subclasses of SOCKET-CONDITION and generally correspond one for one with possible `errno` values

- We use multiple return values in many places where the C API would use p[ass-by-reference values

- We can often avoid supplying an explicit length argument to functions because we already know how long the argument is.

- IP addresses and ports are represented in slightly friendlier fashion than "network-endian integers". See the section on Internet domain sockets for details.

## SOCKETs

Class: SOCKET

Slots:

- FILE-DESCRIPTOR :
- FAMILY :
- PROTOCOL :
- TYPE :
- STREAM :

(socket-bind socket &rest address) | Generic Function

(socket-accept (socket socket)) | Method

> Perform the accept(2) call, returning a newly-created connected socket and the peer address as multiple values

(socket-connect socket &rest address) | Generic Function

(socket-peername (socket socket)) | Method

> Return the socket's peer; depending on the address family this may return multiple values

(socket-name (socket socket)) | Method

> Return the address (as vector of bytes) and port that the socket is bound to, as multiple values

(socket-receive (socket socket) buffer length &key oob peek waitall (element-type 'character)) | Method

> Read LENGTH octets from SOCKET into BUFFER (or a freshly-consed buffer if NIL), using recvfrom(2). If LENGTH is NIL, the length of BUFFER is used, so at least one of these two arguments must be non-NIL. If BUFFER is supplied, it had better be of an element type one octet wide. Returns the buffer, its length, and the address of the peer that sent it, as multiple values. On datagram sockets, sets MSG_TRUNC so that the actual packet length is returned even if the buffer was too small

(socket-listen (socket socket) backlog) | Method

> Mark SOCKET as willing to accept incoming connections. BACKLOG defines the maximum length that the queue of pending connections may grow to before new connection attempts are refused. See also listen(2)

(socket-close (socket socket)) | Method

> Close SOCKET. May throw any kind of error that write(2) would have thrown. If SOCKET-MAKE-STREAM has been called, calls CLOSE on that stream instead

(socket-make-stream (socket socket) &rest args) | Method

> Find or create a STREAM that can be used for IO on SOCKET (which must be connected). ARGS are passed onto SB-SYS:MAKE-FD-STREAM.

## Socket Options

A subset of socket options are supported, using a fairly general framework which should make it simple to add more as required - see sockopt.lisp for details. The name mapping from C is fairly straightforward: `SO_RCVLOWAT` becomes `sockopt-receive-low-water` and `(setf sockopt-receive-low-water)`. |

(sockopt-reuse-address (socket socket) argument) | Accessor

> Return the value of the SO-REUSEADDR socket option for SOCKET. This can also be updated with SETF.

(sockopt-keep-alive (socket socket) argument) | Accessor

> Return the value of the SO-KEEPALIVE socket option for SOCKET. This can also be updated with SETF.

(sockopt-oob-inline (socket socket) argument) | Accessor

> Return the value of the SO-OOBINLINE socket option for SOCKET. This can also be updated with SETF.

(sockopt-bsd-compatible (socket socket) argument) | Accessor

> Return the value of the SO-BSDCOMPAT socket option for SOCKET. This can also be updated with SETF.

(sockopt-pass-credentials (socket socket) argument) | Accessor

> Return the value of the SO-PASSCRED socket option for SOCKET. This can also be updated with SETF.

(sockopt-debug (socket socket) argument) | Accessor

> Return the value of the SO-DEBUG socket option for SOCKET. This can also be updated with SETF.

(sockopt-dont-route (socket socket) argument) | Accessor

> Return the value of the SO-DONTROUTE socket option for SOCKET. This can also be updated with SETF.

(sockopt-broadcast (socket socket) argument) | Accessor

> Return the value of the SO-BROADCAST socket option for SOCKET. This can also be updated with SETF.

(sockopt-tcp-nodelay (socket socket) argument) | Accessor

> Return the value of the TCP-NODELAY socket option for SOCKET. This can also be updated with SETF.

## INET-domain sockets

The TCP and UDP sockets that you know and love. Some representation issues:

- These functions do not accept hostnames directly: see name resolution
- Internet addresses are represented by vectors of `(unsigned-byte 8)` - viz. `#(127 0 0 1)`. Ports are just integers: `6010`. No conversion between network- and host-order data is needed from the user of this package.
- socket addresses are represented by the two values for address and port, so for example, `(socket-connect s #(192.168.1.1) 80)`

Class: INET-SOCKET

Slots:

- FAMILY :

(make-inet-address dotted-quads) | Function

> Return a vector of octets given a string DOTTED-QUADS in the format "127.0.0.1"

(get-protocol-by-name name) | Function

> Returns the network protocol number associated with the string NAME, using getprotobyname(2) which typically looks in NIS or /etc/protocols

(make-inet-socket type protocol) | Function

> Make an INET socket. Deprecated in favour of make-instance

## File-domain sockets

File-domain (AF_FILE) sockets are also known as Unix-domain sockets, but were renamed by POSIX presumably on the basis that they may be available on other systems too.

A file-domain socket address is a string, which is used to create a node in the local filesystem. This means of course that they cannot be used across a network.

|

Class: UNIX-SOCKET

Slots:

- FAMILY :

## Name Service

Presently name service is implemented by calling whatever gethostbyname(2) uses. This may be any or all of /etc/hosts, NIS, DNS, or something completely different. Typically it's controlled by /etc/nsswitch.conf

Direct links to the asynchronous resolver(3) routines would be nice to have eventually, so that we can do DNS lookups in parallel with other things

Class: HOST-ENT

Slots:

- NAME :
- ALIASES :
- ADDRESS-TYPE :
- ADDRESSES :

(host-ent-address (host-ent host-ent)) | Method

(get-host-by-name host-name) | Function

> Returns a HOST-ENT instance for HOST-NAME or throws some kind of condition. HOST-NAME may also be an IP address in dotted quad notation or some other weird stuff - see gethostbyname(3) for grisly details.

(get-host-by-address address) | Function

> Returns a HOST-ENT instance for ADDRESS, which should be a vector of (integer 0 255), or throws some kind of error. See gethostbyaddr(3) for grisly details.

(name-service-error where) | Function

(non-blocking-mode (socket socket)) | Method

> Is SOCKET in non-blocking mode?

# Tests

There should be at least one test for pretty much everything you can do with the package. In some places I've been more diligent than others; more tests gratefully accepted.

Tests are in the file `tests.lisp` and also make good examples.

|

## Unix-domain sockets

A fairly rudimentary test that connects to the syslog socket and sends a message. Priority 7 is kern.debug; you'll probably want to look at /etc/syslog.conf or local equivalent to find out where the message ended up |