Chapter 10
OSKit Networking Framework

10.1 Introduction

The OSKit networking framework encompasses a collection of COM interfaces used by the client operating system to invoke the networking libraries. The individual networking libraries supply additional interfaces to the client operating system for initialization, and may supply additional interfaces for supporting extended features unique to particular networking protocol implementations.

At this point, we have only one interface, the oskit_socket interface, defined. Additional interfaces for configuration, routing, etc., are future work.

10.2 oskit_socket: Socket Interface

The oskit_socket COM interface defines an interface which capture the semantics of a socket as defined in the corresponding POSIX/CAE standards. The oskit_socket COM interface inherits from oskit_posixio. It can be queried for an oskit_stream interface. This query will always be successful, but the resulting oskit_stream instance might not support all methods. Generally, at least read and write will be supported. The oskit_socket COM interface provides in addition to the oskit_posixio COM interface the following methods:

accept:
accept a connection on a socket
bind:
bind a name to a socket
connect:
initiate a connection on a socket
shutdown:
shut down part of a full-duplex connection
listen:
listen for connections on a socket
getsockname:
get socket name
getpeername:
get name of connected peer
getsockopt:
get options on sockets
setsockopt:
set options on sockets
sendto:
send a message from a socket
recvfrom:
receive a message from a socket
sendmsg:
send a message from a socket
recvmsg:
receive a message from a socket

Note that these methods are not minimal, but correspond very closely to the traditional BSD interfaces.

Note: the following paragraphs have a certain likelihood to change. The main reason for this is the obviously undesirable connection between the way socket factories and the socket interface interact. On a more positive note, everything right now is so close to the BSD interfaces that the reader familiar with those shouldn’t have any problems understanding these.

10.2.1 oskit_socket_factory_t: socket factories

SYNOPSIS

#include <oskit/net/socket.h>

oskit_error_t oskit_socket_factory_create( oskit_socket_factory_t *factory, oskit_u32_t domain, oskit_u32_t type, oskit_u32_t protocol, [out] oskit_socket_t **newsocket);

DESCRIPTION

Socket instances are created by socket factories.

A socket factory is an instance of the oskit_socket_factory COM interface. Implementations of this interface will be provided by the networking stack(s) included in the OSKit. This interface implements a single method corresponding to the socket(2) call in addition to the oskit_iunknown interface.

Each instance of socket has a type and a protocol associated with it. This type and protocol is given to the socket by its factory, and cannot be changed during the lifetime of that socket instance.

PARAMETERS
factory:
The socket factory used to create this socket.
domain:
The domain parameter specifies a communications domain within which communication will take place; this selects the protocol family which should be used. Some common formats are
OSKIT_PF_LOCAL Host-internal protocols
OSKIT_PF_INET DARPA Internet protocols
OSKIT_PF_ISO ISO protocols
OSKIT_PF_CCITT ITU-T protocols, like X.25
OSKIT_PF_NS Xerox Network Systems protocols

OSKIT_PF_INET is the only format for which the OSKit currently contains an implementation.

type:
The socket will have the indicated type, which specifies the semantics of communication. Currently defined types are
OSKIT_SOCK_STREAM stream socket
OSKIT_SOCK_DGRAM datagram socket
OSKIT_SOCK_RAW raw-protocol interface
OSKIT_SOCK_RDM reliably-delivered message
OSKIT_SOCK_SEQPACKET sequenced packet stream

An OSKIT_SOCK_STREAM type provides sequenced, reliable, two-way connection based byte streams. An out-of-band data transmission mechanism may be supported. An OSKIT_SOCK_DGRAM socket supports datagrams (connectionless, unreliable messages of a fixed (typically small) maximum length). An OSKIT_SOCK_SEQPACKET socket may provide a sequenced, reliable, two-way connection-based data transmission path for datagrams of fixed maximum length. OSKIT_SOCK_RAW sockets provide access to internal network protocols and interfaces.

protocol:
The protocol specifies a particular protocol to be used with the socket. Normally only a single protocol exists to support a particular socket type within a given protocol family. However, it is possible that many protocols may exist, in which case a particular protocol must be specified. The protocol number to use is particular to the communication domain in which communication is to take place.

Protocols for the OSKIT_PF_INET protocol family are defined in oskit/c/netinet/in.h.

newsocket:
The new oskit_socket_t instance that was created.
RETURNS

Returns 0 on success, or an error code specified in <oskit/error.h>, on error.

10.2.2 accept: accept a connection on a socket

SYNOPSIS

#include <oskit/net/socket.h>

oskit_error_t oskit_socket_accept(oskit_socket_t *s, [out] struct oskit_sockaddr *name, [in/out] oskit_size_t *anamelen, [out] struct oskit_socket **newopenso);

DESCRIPTION

The accept method extracts the first connection request on the queue of pending connections, creates a new socket with the same properties of s and returns it. The socket must have been bound to an address with bind and it must be listening for connections after a listen.

If no pending connections are present on the queue, accept blocks the caller until a connection is present.

PARAMETERS
s:
The socket from which connections are to accepted.
name:
Filled with the address of the connecting entity as known to the communication layer.
anamelen:
Initially, the amount of space pointed to by name, on return it will contain the amount actually used.
newopenso:
Newly created socket.
RETURNS

Returns 0 on success, or an error code specified in <oskit/error.h>, on error.

10.2.3 bind: bind a name to a socket

SYNOPSIS

#include <oskit/net/socket.h>

oskit_error_t oskit_socket_bind(oskit_socket_t *s, const struct oskit_sockaddr *name, oskit_size_t namelen);

DESCRIPTION

bind assigns a name to an unnamed socket. When a socket is created, it exists in a name space (address family) but has no name assigned. bind requests that name be assigned to the socket.

PARAMETERS
s:
The socket to which a name is to be bound.
name:
The name to which the socket is to be bound.
namelen:
The length of name in bytes.
RETURNS

Returns 0 on success, or an error code specified in <oskit/error.h>, on error.

10.2.4 connect: initiate a connection on a socket

SYNOPSIS

#include <oskit/net/socket.h>

oskit_error_t oskit_socket_connect(oskit_socket_t *s, const struct oskit_sockaddr *name, oskit_size_t namelen);

DESCRIPTION

If s is of type OSKIT_SOCK_DGRAM, this call specifies the peer with which the socket is to be associated; this address is that to which datagrams are to be sent, and the only address from which datagrams are to be received. If the socket is of type OSKIT_SOCK_STREAM, this call attempts to make a connection to another socket. The other socket is specified by name, which is an address in the communications space of the socket. Each communications space interprets the name parameter in its own way. Generally, stream sockets may successfully connect only once; datagram sockets may use connect multiple times to change their association. Datagram sockets may dissolve the association by connecting to an invalid address, such as a null address.

PARAMETERS
s:
The socket from which the connection is to be initiated.
name:
The address of the entity to which the connection is to be established.
namelen:
The length of name in bytes.
RETURNS

Returns 0 on success, or an error code specified in <oskit/error.h>, on error.

10.2.5 shutdown: shut down part of a full-duplex connection

SYNOPSIS

#include <oskit/net/socket.h>

oskit_error_t oskit_socket_shutdown(oskit_socket_t *s, oskit_u32_t how);

DESCRIPTION

The shutdown call causes all or part of a full-duplex connection on the socket s to be shut down.

PARAMETERS
s:
The socket which is to be shut down.
how:
Specifies what is to be disallowed:
  • receives
  • sends
  • sends and receives
RETURNS

Returns 0 on success, or an error code specified in <oskit/error.h>, on error.

10.2.6 listen: listen for connections on a socket

SYNOPSIS

#include <oskit/net/socket.h>

oskit_error_t oskit_socket_listen(oskit_socket_t *s, oskit_u32_t backlog);

DESCRIPTION

A willingness to accept incoming connections and a queue limit for incoming connections are specified with listen, and then the connections are accepted with accept. The listen call applies only to sockets of type OSKIT_SOCK_STREAM or OSKIT_SOCK_SEQPACKET.

The backlog parameter defines the maximum length the queue of pending connections may grow to. If a connection request arrives with the queue full the client may receive an error with an indication of connection refused, or, if the underlying protocol supports retransmission, the request may be ignored so that retries may succeed.

PARAMETERS
s:
The socket where connections will be accepted.
backlog:
Maximum number of pending connections.
RETURNS

Returns 0 on success, or an error code specified in <oskit/error.h>, on error.

10.2.7 getsockname: get socket name

SYNOPSIS

#include <oskit/net/socket.h>

oskit_error_t oskit_socket_getsockname(oskit_socket_t *s, [out] struct oskit_sockaddr *asa, [in/out] oskit_size_t *anamelen);

DESCRIPTION

getsockname returns the current name for the specified socket.

PARAMETERS
s:
The socket whose name is to be determined.
name:
Contains the name of the socket upon return.
anamelen:
Initially, the amount of space pointed to by name, on return it will contain the amount actually used, i.e., the actual size of the name.
RETURNS

Returns 0 on success, or an error code specified in <oskit/error.h>, on error.

10.2.8 getpeername: get name of connected peer

SYNOPSIS

#include <oskit/net/socket.h>

oskit_error_t oskit_socket_getpeername(oskit_socket_t *s, [out] struct oskit_sockaddr *asa, [in/out] oskit_size_t *anamelen);

DESCRIPTION

getpeername returns the name of the peer connected to socket s.

PARAMETERS
s:
The socket connected to the peer whose name is to be returned.
name:
Contains the peer’s name upon return.
anamelen:
Initially, the amount of space pointed to by name, on return it will contain the amount actually used. The name is truncated if the buffer provided is too small.
RETURNS

Returns 0 on success, or an error code specified in <oskit/error.h>, on error.

10.2.9 getsockopt: get options on sockets

SYNOPSIS

#include <oskit/net/socket.h>

oskit_error_t oskit_socket_getsockopt(oskit_socket_t *s, oskit_u32_t level, oskit_u32_t name, [out] void *val, [in/out] oskit_size_t *valsize);

DESCRIPTION

Get the current options associated with a socket. Options may exist at multiple protocol levels.

PARAMETERS
s:
The socket whose options are to be queried or set.
level:
The level at which the option resides. See setsockopt for details.
name:
name and any specified options are passed uninterpreted to the appropriate protocol module for interpretation. See setsockopt for details.
val, valsize:
The parameters val and valsize are used to access option values. For getsockopt, valsize initially contains the size of the buffer pointed to by val, and modified on return to indicate the actual size of the value returned. If no option value is to be supplied or returned, val may be NULL.
RETURNS

Returns 0 on success, or an error code specified in <oskit/error.h>, on error.

10.2.10 setsockopt: set options on sockets

SYNOPSIS

#include <oskit/net/socket.h>

oskit_error_t oskit_socket_setsockopt(oskit_socket_t *s, oskit_u32_t level, oskit_u32_t name, const void *val, oskit_size_t valsize);

DESCRIPTION

setsockopt manipulates the options associated with a socket. Options may exist at multiple protocol levels.

PARAMETERS
s:
The socket whose options are to be queried or set.
level:
When manipulating socket options the level at which the option resides and the name of the option must be specified. To manipulate options at the socket level, level is specified as OSKIT_SOL_SOCKET. To manipulate options at any other level the protocol number of the appropriate protocol controlling the option is supplied. For example, to indicate that an option is to be interpreted by the TCP protocol, level should be set to IPPROTO_TCP.
name:
name and any specified options are passed uninterpreted to the appropriate protocol module for interpretation. Definitions for socket level options are described below. Options at other protocol levels vary in format and name.

Most socket-level options utilize an int parameter for val. For setsockopt, the parameter should be non-zero to enable a boolean option, or zero if the option is to be disabled. OSKIT_SO_LINGER uses a struct oskit_linger parameter, which specifies the desired state of the option and the linger interval (see below). OSKIT_SO_SNDTIMEO and OSKIT_SO_RCVTIMEO use a struct timeval parameter, defined in <oskit/c/sys/time.h>

The following options are recognized at the socket level. Except as noted, each may be examined with getsockopt and set with setsockopt.

OSKIT_SO_DEBUG enables recording of debugging information
OSKIT_SO_REUSEADDR enables local address reuse
OSKIT_SO_REUSEPORT enables duplicate address and port bindings
OSKIT_SO_KEEPALIVE enables keep connections alive
OSKIT_SO_DONTROUTE enables routing bypass for outgoing messages
OSKIT_SO_LINGER linger on close if data present
OSKIT_SO_BROADCAST enables permission to transmit broadcast messages
OSKIT_SO_OOBINLINE enables reception of out-of-band data in band
OSKIT_SO_SNDBUF set buffer size for output
OSKIT_SO_RCVBUF set buffer size for input
OSKIT_SO_SNDLOWAT set minimum count for output
OSKIT_SO_RCVLOWAT set minimum count for input
OSKIT_SO_SNDTIMEO set timeout value for output
OSKIT_SO_RCVTIMEO set timeout value for input
OSKIT_SO_TYPE get the type of the socket (get only)
OSKIT_SO_ERROR get and clear error on the socket (get only)

OSKIT_SO_DEBUG enables debugging in the underlying protocol modules. OSKIT_SO_REUSEADDR indicates that the rules used in validating addresses supplied in bind should allow reuse of local addresses. OSKIT_SO_REUSEPORT allows completely duplicate bindings by multiple clients if they all set OSKIT_SO_REUSEPORT before binding the port. This option permits multiple instances of a program to each receive UDP/IP multicast or broadcast datagrams destined for the bound port. OSKIT_SO_KEEPALIVE enables the periodic transmission of messages on a connected socket. Should the connected party fail to respond to these messages, the connection is considered broken and clients using the socket are notified when attempting to send data. OSKIT_SO_DONTROUTE indicates that outgoing messages should bypass the standard routing facilities. Instead, messages are directed to the appropriate network interface according to the network portion of the destination address.

OSKIT_SO_LINGER controls the action taken when unsent messages are queued on a socket and the socket is released. If the socket promises reliable delivery of data and OSKIT_SO_LINGER is set, the system will block on the last release attempt until it is able to transmit the data or until it decides it is unable to deliver the information (a timeout period, termed the linger interval, is specified in the setsockopt call when OSKIT_SO_LINGER is requested. If OSKIT_SO_LINGER is disabled, the last release will succeed immediately.

The option OSKIT_SO_BROADCAST requests permission to send broadcast datagrams on the socket. Broadcast was a privileged operation in earlier versions of the system. With protocols that support out-of-band data, the OSKIT_SO_OOBINLINE option requests that out-of-band data be placed in the normal data input queue as received; it will then be accessible with recv or read calls without the OSKIT_MSG_OOB flag. Some protocols always behave as if this option were set.

OSKIT_SO_SNDBUF and OSKIT_SO_RCVBUF are options to adjust the normal buffer sizes allocated for output and input buffers, respectively. The buffer size may be increased for high-volume connections, or may be decreased to limit the possible backlog of incoming data. An absolute limit may be places on these values.

OSKIT_SO_SNDLOWAT is an option to set the minimum count for output operations. Most output operations process all of the data supplied by the call, delivering data to the protocol for transmission and blocking as necessary for flow control. Nonblocking output operations will process as much data as permitted subject to flow control without blocking, but will process no data if flow control does not allow the smaller of the low water mark value or the entire request to be processed.

The default value for OSKIT_SO_SNDLOWAT is set to a convenient size for network efficiency, often 1024.

OSKIT_SO_RCVLOWAT is an option to set the minimum count for input operations. In general, receive calls will block until any (non-zero) amount of data is received, then return with the smaller of the amount available or the amount requested. The default value for OSKIT_SO_RCVLOWAT is 1. If OSKIT_SO_RCVLOWAT is set to a larger value, blocking receive calls normally wait until they have received the smaller of the low water mark value or the requested amount. Receive calls may still return less than the low water mark if an error occurs, a signal is caught, or the type of data next in the receive queue is different than that returned.

OSKIT_SO_SNDTIMEO is an option to set a timeout value for output operations. It accepts a struct timeval parameter with the number of seconds and microseconds used to limit waits for output operations to complete. If a send operation has blocked for this much time, it returns with a partial count or with the error OSKIT_EWOULDBLOCK if no data were sent.

This timer is restarted each time additional data are delivered to the protocol, implying that the limit applies to output portions ranging in size from the low water mark to the high water mark for output.

OSKIT_SO_RCVTIMEO is an option to set a timeout value for input operations. It accepts a struct timeval parameter with the number of seconds and microseconds used to limit waits for input operations to complete.

This timer is restarted each time additional data are received by the protocol, and thus the limit is in effect an inactivity timer. If a receive operation has been blocked for this much time without receiving additional data, it returns with a short count or with the error OSKIT_EWOULDBLOCK if no data were received.

Finally, OSKIT_SO_TYPE and OSKIT_SO_ERROR are options used only with getsockopt. OSKIT_SO_TYPE returns the type of the socket, such as OSKIT_SOCK_STREAM. OSKIT_SO_ERROR returns any pending error on the socket and clears the error status. It may be used to check for asynchronous errors on connected datagram sockets or for other asynchronous errors.

val, valsize:
The parameters val and valsize are used to access option values for setsockopt. If no option value is to be supplied or returned, val may be NULL.
RETURNS

Returns 0 on success, or an error code specified in <oskit/error.h>, on error.

10.2.11 recvfrom, recvmsg: receive a message from a socket

SYNOPSIS

#include <oskit/net/socket.h>

oskit_error_t oskit_socket_recvfrom(oskit_socket_t *s, [out] void *buf, oskit_size_t len, oskit_u32_t flags, [out] struct oskit_sockaddr *from, [in/out] oskit_size_t *fromlen, [out] oskit_size_t *retval);

oskit_error_t oskit_socket_recvmsg(oskit_socket_t *s, [in/out] struct oskit_msghdr *msg, oskit_u32_t flags, [out] oskit_size_t *retval);

DESCRIPTION

recvfrom and recvmsg are used to receive messages from a socket, and may be used to receive data on a socket whether or not it is connection-oriented.

Note: The recv library function can be implemented using recvfrom with a nil from parameter.

If no messages are available at the socket, the receive call waits for a message to arrive. The receive calls normally return any data available, up to the requested amount, rather than waiting for receipt of the full amount equested; this behavior is affected by the socket-level options OSKIT_SO_RCVLOWAT and OSKIT_SO_RCVTIMEO described in getsockopt.

PARAMETERS
s:
The socket from the message is to be received.
buf :
Buffer in which the message is to be copied.
len:
Length of the buffer provided.
flags:
The flags argument is formed by or’ing one or more of the values:
OSKIT_MSG_OOB process out-of-band data
OSKIT_MSG_PEEK peek at incoming message
OSKIT_MSG_WAITALL wait for full request or error

The OSKIT_MSG_OOB flag requests receipt of out-of-band data that would not be received in the normal data stream. Some protocols place expedited data at the head of the normal data queue, and thus this flag cannot be used with such protocols. The OSKIT_MSG_PEEK flag causes the receive operation to return data from the beginning of the receive queue without removing that data from the queue. Thus, a subsequent receive call will return the same data. The OSKIT_MSG_WAITALL flag requests that the operation block until the full request is satisfied. However, the call may still return less data than requested if an error or disconnect occurs, or the next data to be received is of a different type than that returned.

from:
If from is non-nil, and the socket is not connection-oriented, the source address of the message is filled in.
fromlen:
Initialized to the size of the buffer associated with from, and modified on return to indicate the actual size of the address stored there.
msg:
The recvmsg method uses a struct oskit_msghdr structure to minimize the number of directly supplied parameters.

struct oskit_msghdr {

  oskit_addr_t msg_name; /* optional address */
  oskit_u32_t msg_namelen; /* size of address */
  struct oskit_iovec *msg_iov; /* scatter/gather array */
  oskit_u32_t msg_iovlen; /* # elements in msg_iov */
  oskit_addr_t msg_control; /* ancillary data, see below */
  oskit_u32_t msg_controllen; /* ancillary data buffer len */
  oskit_u32_t msg_flags; /* flags on received message */

};

Here msg_name and msg_namelen specify the destination address if the socket is unconnected; msg_name may be given as a null pointer if no names are desired or required. msg_iov and msg_iovlen describe scatter gather locations.

msg_control, which has length msg_controllen, points to a buffer for other protocol control related messages or other miscellaneous ancillary data.

The msg_flags field is set on return according to the message received. OSKIT_MSG_EOR indicates end-of-record; the data returned completed a record (generally used with sockets of type OSKIT_SOCK_SEQPACKET). OSKIT_MSG_TRUNC indicates that the trailing portion of a datagram was discarded because the datagram was larger than the buffer supplied. OSKIT_CMSG_TRUNC indicates that some control data were discarded due to lack of space in the buffer for ancillary data. OSKIT_MSG_OOB is returned to indicate that expedited or out-of-band data were received.

retval:
Contains the number of characters received, i.e., the total length of the message upon return. If a message is too long to fit in the supplied buffer, excess bytes may be discarded depending on the type of socket the message is received from.
RETURNS

Returns 0 on success, or an error code specified in <oskit/error.h>, on error.

10.2.12 sendto, sendmsg: send a message from a socket

SYNOPSIS

#include <oskit/net/socket.h>

oskit_error_t oskit_socket_sendto(oskit_socket_t *s, const void *buf, oskit_size_t len, oskit_u32_t flags, const struct oskit_sockaddr *to, oskit_size_t tolen, [out] oskit_size_t *retval);

oskit_error_t oskit_socket_sendmsg(oskit_socket_t *s, const struct oskit_msghdr *msg, oskit_u32_t flags, [out] oskit_size_t *retval);

DESCRIPTION

sendto, sendmsg are used to transmit a message to another socket. The C library send may be implemented by passing a NULL to parameter. It may be used only when the socket is in a connected state, while sendto and sendmsg may generally be used at any time.

Send will block if no messages space is available at the socket to hold the message to be transmitted.

PARAMETERS
s:
The socket from which the message is to be sent.
buf :
len:
len gives the length of the message. If the message is too long to pass atomically through the underlying protocol, the error OSKIT_EMSGSIZE is returned, and the message is not transmitted.
flags:
The flags parameter may include one or more of the following:
OSKIT_MSG_OOB process out-of-band data
OSKIT_MSG_PEEK peek at incoming message
OSKIT_MSG_DONTROUTE bypass routing, use direct interface
OSKIT_MSG_EOR data completes record
OSKIT_MSG_EOF data completes transaction

The flag OSKIT_MSG_OOB is used to send “out-of-band” data on sockets that support this notion (e.g. OSKIT_SOCK_STREAM); the underlying protocol must also support “out-of-band” data. OSKIT_MSG_EOR is used to indicate a record mark for protocols which support the concept. OSKIT_MSG_EOF requests that the sender side of a socket be shut down, and that an appropriate indication be sent at the end of the specified data; this flag is only implemented for OSKIT_SOCK_STREAM sockets in the OSKIT_PF_INET protocol family.

to, tolen:
The address of the target is given by to with tolen specifying its size.
msg:
See recvmsg for a description of the oskit_msghdr structure.
retval:
Upon return *retval contains the number of characters sent.
RETURNS

Returns 0 on success. No indication of failure to deliver is implicit in a send. Locally detected errors are indicated by an error code specified in <oskit/error.h>.