libsocket Interface Writer's Guide

Version 0.1.0
Last Updated 1999-05-14

libsocket Copyright 1997, 1998 by Indrek Mandre
libsocket Copyright 1997-1999 by Richard Dawe

This document is part of libsocket. It may be distributed freely, so long as it is unchanged.

Introduction

This document is intended to describe some of the internals of libsocket, in order to allow other people to work on it. This document assumes that the reader understands how sockets work and some of the terminology involved (e.g. blocking vs. non-blocking). First, however, some definitions are needed:

libsocket's design is currently compromised by the lack of support for all of BSD's socket operations in the underlying system interfaces. The best that can be done is to implement a lowest common denominator well, and maybe provide extra support where possible. The minimal functionality required by an interface will be indicated.


Socket Descriptors

The socket descriptor structure, and relevant constants, taken from lsck/if.h, is as follows:

#define __SOCKADDR_COMMON_SIZE sizeof(struct sockaddr)
#define __SOCKADDR_MAX_SIZE sizeof(struct sockaddr_un)
#define __SOCKADDR_PAD_SIZE (__SOCKADDR_MAX_SIZE - __SOCKADDR_COMMON_SIZE)

typedef struct _LSCK_SOCKET {
	/* Basic information */
	int fd;				/* File descriptor */
	int family;			/* Address family / domain */
	int type;			/* SOCK_* type */
	int protocol;			/* Protocol to use */

	/* Address information */
	struct sockaddr sockname;	/* Socket local name */
	char pad1[__SOCKADDR_PAD_SIZE];
	struct sockaddr peername;	/* Socket peer name */
	char pad2[__SOCKADDR_PAD_SIZE];
	int socknamelen;
	int peernamelen;

	/* Status information */
	unsigned char bound:1;		/* Socket has been bound */
	unsigned char accepted:1;	/* Socket has been accepted */
	unsigned char connected:1;	/* Socket has been connected */
	unsigned char connecting:1;	/* Non-blocking connect()? */
	unsigned char blocking:1;	/* Socket does blocking I/O */
	unsigned char outbound:1;	/* Socket outbound allowed */
	unsigned char inbound:1;	/* Socket inbound allowed */
	unsigned char pad3:1;
	int backlog;			/* listen() backlog */
	int send_timeout;		/* send() timeout */
	int recv_timeout;		/* recv() timeout */
	int urgent_pid;			/* Send SIGURG to this pid */

	/* Interface information */
	struct _LSCK_IF *interface;	/* Interface info table */
	LSCK_SOCKET_WSOCK wsock;
	LSCK_SOCKET_CSOCK csock;
	LSCK_SOCKET_UNIX usock;
} LSCK_SOCKET __attribute__((packed));

Much of this should be self-explanatory. libsocket duplicates any status information the underlying networking, e.g. Winsock, may have about the socket. libsocket uses this state information to avoid calling the interface as much as possible, because this may be a costly operation. If it can just look in the socket descriptor, it will be a lot faster.

Here are some pertinent details:

Why is the structure padded? It is padded to force sockname & pad1 and peername & pad2 to be right next to each other in memory.


Interface Descriptors