Table of Contents

Table of Chapters

5. SOCKETS

5.1 Overview

This section is documentation for the InterNiche Sockets layer. Sockets is an API, primarily used today for TCP programming, which was developed during the early 1980s at U.C. Berkeley for UNIX. Dozens of books and tutorials are available for Sockets programming (one of the compelling arguments for their use), so this section is devoted to functional descriptions of the Sockets subset as supported by the InterNiche TCP/IP stack. It is not a tutorial.

Programmers new to Sockets may observe that there is a good deal of extra "baggage" here not required for a TCP API. There are historical reasons for this. When Sockets was developed, it was fashionable in academic computing to view all IO devices as a file-system-like, (or "streaming") device. This was, obviously, in the days before mice and GUIs. Sockets were initially developed to allow inter-process communication via stream devices - one process would write to a connection socket and another process would read what was written. Sockets was meant to be a one-size-fits-all solution for data IO. On many UNIX systems you can actually pass a socket to the read() and write() calls in place of a file descriptor. When the Berkeley researchers wanted to extend the endpoints of the socket outside the host system so that processes on two separate systems could talk, they implemented TCP (as well as other protocols) under the Sockets. This required extending Sockets to indicate what type of service was desired. The AF_INET (as opposed to AF_UNIX) parameter in the t_socket() call is a vestige of this; as is the multiplicity of overlapping routines such as t_write(), t_send(), and t_sendto() which all do similar things on different types of Sockets.

This use of TCP as a carrier for Sockets was TCP's first major popular application outside of the DARPA projects where it was developed. So in a very real sense, TCP owes its widespread popularity today to Berkeley UNIX and Sockets.

Over the years, many simpler, cleaner TCP APIs have been proposed, but, by the time TCP became popular on non-UNIX platforms, it was too late. As with the attempts in the 1970s to switch the United States to the metric system, people had become accustomed to the status quo and were unwilling to switch. Sockets had become entrenched.

So for better or worse, Sockets is the de-facto standard for TCP programming. For all its warts, it still compares favorably with many of the baroque API standards from big commercial software vendors.

The calls documented in this section are compatible with those on UNIX systems insofar as TCP use goes. Example networking code from other Sockets-based systems should work here, and most of what is in the books and tutorials apply as well. We've tried to update the man-pages herein to reflect any differences there are.

One general difference is that all the function names in the InterNiche package start with "t_", e.g. socket() is t_socket(). This is so that embedded systems which already use some of the socket names will not have a conflict at link time. By adding #defines in your tcpport.h file, the original Sockets function names can be used in source code.

Another is the UNIX errno mechanism has been replaced by an error holder attached to each socket structure and assigned a value whenever an error occurs. Thus when a socket call indicates failure, such as t_socket() returning -1, you can examine this member or call t_errno(long s) to find out what went wrong. Possible values for Sockets errors are listed below. These are a subset of the standard Berkeley errors.

5.2 Sockets Errors

/* BSD Sockets errors */
#define ENOBUFS         1
#define ETIMEDOUT       2
#define EISCONN         3
#define EOPNOTSUPP      4
#define ECONNABORTED    5
#define EWOULDBLOCK     6
#define ECONNREFUSED    7
#define ECONNRESET      8
#define ENOTCONN        9
#define EALREADY        10
#define EINVAL          11
#define EMSGSIZE        12
#define EPIPE           13
#define EDESTADDRREQ    14
#define ESHUTDOWN       15
#define ENOPROTOOPT     16
#define EHAVEOOB        17
#define ENOMEM          18
#define EADDRNOTAVAIL   19
#define EADDRINUSE      20
#define EAFNOSUPPORT    21

5.3 Quick List for Sockets Prototypes

extern long t_socket (int, int, int);
extern int t_bind (long, struct sockaddr *, int);
extern int t_listen (long, int);
extern long t_accept (long, struct sockaddr *, int *);
extern int t_connect (long, struct sockaddr *, int);
extern int t_getpeername (long, struct sockaddr *, int *);
extern int t_getsockname (long, struct sockaddr *, int *);
extern int t_setsockopt (long, int, int, void *, int);
extern int t_getsockopt (long, int, int, void *, int);
extern int t_recv (long, char *, int, int);
extern int t_send (long, char *, int, int);
extern int t_recvfrom (long s, char * buf, int len, int flags, struct sockaddr *, int *);
extern int t_sendto (long s, char * buf, int len, int flags, struct sockaddr *, int);
extern int t_shutdown (long, int);
extern int t_socketclose (long);
extern int t_errno (long s);
extern int t_select(fd_set * in, fd_set * out, fd_set * ev, long tmo_seconds);

5.4 Quick List for Socket Options

/* Generic/TCP socket options          */
#define SO_DEBUG           0x0001    /* turn on debugging info recording    */
#define SO_ACCEPTCONN      0x0002    /* socket has had listen()    */
#define SO_REUSEADDR       0x0004    /* allow local address reuse    */
#define SO_KEEPALIVE       0x0008    /* keep connections alive    */
#define SO_DONTROUTE       0x0010    /* just use interface addresses    */
#define SO_BROADCAST       0x0020    /* permit sending of broadcast msgs    */
#define SO_USELOOPBACK     0x0040    /* bypass hardware when possible    */
#define SO_LINGER          0x0080    /* linger on close if data present    */
#define SO_OOBINLINE       0x0100    /* leave received OOB data in line    */
#define SO_TCPSACK         0x0200    /* Allow TCP SACK    */
#define SO_WINSCALE        0x0400    /* Set scaling window option    */
#define SO_TIMESTAMP       0x0800    /* Set TCP timestamp option    */
#define SO_BIGCWND         0x1000    /* Large initial Congenstion window    */
#define SO_HDRINCL         0x2000   /* user access to IP hdr for SOCK_RAW    */
#define SO_NOSLOWSTART     0x4000   /* suppress slowstart on this socket    */
#define SO_FULLMSS         0x8000   /* force packets to all be MAX size    */
#define SO_SNDBUF          0x1001    /* send buffer size    */
#define SO_RCVBUF          0x1002    /* receive buffer size    */
#define SO_SNDLOWAT        0x1003    /* send low-water mark    */
#define SO_RCVLOWAT        0x1004    /* receive low-water mark    */
#define SO_SNDTIMEO        0x1005    /* send timeout    */
#define SO_RCVTIMEO        0x1006    /* receive timeout    */
#define SO_ERROR           0x1007    /* get error status and clear    */
#define SO_TYPE            0x1008    /* get socket type    */
#define SO_HOPCNT          0x1009    /* Hop count to get to dst    */
#define SO_MAXMSG          0x1010    /* get/set TCP_MSS (max segment size)    */
#define SO_RXDATA          0x1011    /* get count of bytes in sb_rcv    */
#define SO_TXDATA          0x1012    /* get count of bytes in sb_snd    */
#define SO_MYADDR          0x1013    /* return my IP address    */
#define SO_NBIO            0x1014    /* set socket into NON-blocking mode    */
#define SO_BIO             0x1015    /* set socket into blocking mode    */
#define SO_NONBLOCK        0x1016    /* set/get blocking mode via param    */
#define SO_CALLBACK        0x1017    /* set/get zero_copy callback routine    */
/* TCP User-settable options (used with setsockopt).   */
#define TCP_ACKDELAYTIME   0x2001    /* Set time for delayed acks    */
#define TCP_NODELAY        0x2002    /* suppress delayed ACKs    */
#define TCP_MAXSEG         0x2003    /* set maximum segment size    */

/* IP socket options          */
#define IP_OPTIONS          1   /* buf/ip_opts; set/get IP options    */
#define IP_HDRINCL          2   /* int; header is included with data    */
#define IP_TOS              3   /* int; IP type of service and preced.    */
#define IP_TTL_OPT          4   /* int; IP time to live    */
#define IP_RECVOPTS         5   /* bool; receive all IP opts w/dgram    */
#define IP_RECVRETOPTS      6   /* bool; receive IP opts for response    */
#define IP_RECVDSTADDR      7   /* bool; receive IP dst addr w/dgram    */
#define IP_RETOPTS          8   /* ip_opts; set/get IP options    */

/* Multicast socket options          */
#define IP_MULTICAST_IF     9   /* u_char; set/get IP multicast i/f   */
#define IP_MULTICAST_TTL    10    /* u_char; set/get IP multicast ttl    */
#define IP_MULTICAST_LOOP   11    /* u_char; set/get IP multicast loopback   */
#define IP_ADD_MEMBERSHIP   12    /* ip_mreq; add an IP group membership    */
#define IP_DROP_MEMBERSHIP  13    /* ip_mreq; drop an IP group membership    */

5.5 Sockets API Calls Reference

Name

t_socket()

Syntax

long t_socket (int domain, int type, int protocol);

Description

t_socket() creates an endpoint for communication and returns a descriptor. The domain parameter specifies a communications domain within which communication will take place; this selects the protocol family which should be used. The protocol family generally is the same as the address family for the addresses supplied in later operations on the socket. These families are defined in the include file socket.h. The only currently understood format is:

PF_INET (ARPA Internet protocols)

The socket has the indicated type, which specifies the semantics of communication. Currently defined types are:

SOCK_STREAM      /* TCP*/
SOCK_DGRAM       /* UDP */
SOCK_RAW         /* IP */

A SOCK_STREAM type provides sequenced, reliable, two-way connection based byte streams. A SOCK_DGRAM socket supports datagrams (connectionless, unreliable messages of a fixed, typically small, maximum length). A SOCK_RAW socket provides lower-layer protocol access.

Sockets of type SOCK_STREAM are full-duplex byte streams, similar to pipes. A stream socket must be in a connected state before any data may be sent or received on it. A connection to another socket is created with a t_connect() call. Once connected, data may be transferred using t_send() and t_recv() calls. When a session has been completed, a t_socketclose() may be performed. Out-of-band data may also be transmitted as described in the t_send() page and received as described in t_recv().

The communications protocols used to implement a SOCK_STREAM ensure that data is not lost or duplicated. If a piece of data for which the peer protocol has buffer space cannot be successfully transmitted within a reasonable length of time, then the connection is considered broken and calls will indicate an error with -1 returns and with ETIMEDOUT as the specific code in the global variable t_errno. The protocols optionally keep sockets "warm" by forcing transmissions roughly every minute in the absence of other activity. An error is then indicated if no response can be elicited on an otherwise idle connection for a extended period (such as five minutes).

SOCK_DGRAM sockets allow sending of datagrams to correspondents named in t_sendto() calls. Datagrams are generally received with t_recvfrom(), which returns the next datagram with its return address.

SOCK_RAW sockets allow the application access to IP-layer protocols with a datagram-like interface; the application specifies the protocol of interest as the protocol argument to t_socket().

The operation of sockets is controlled by socket level options. These options are defined in the file socket.h. t_getsockopt() and t_setsockopt() are used to get and set options, respectively.

The SO_NOSLOWSTART option suppresses the standard TCP "slow-start" feature. Normally when newly connected, the TCP socket which is passed a large block of data to send (for example an FTP data connection) will send about two full-sized data segments, and then wait for a response form the other side before sending more. If the speed of the response indicates the network can handle more traffic, the connection will send more segments in reply. The number of segments will keep increasing until they are limited by internal resources or the receives window size.

In situations where a machine on an ethernet is sending it's packets through a router to a slower media (i.e. DSL) this slow start behaviour prevents the socket from flooding the router. The SO_NOSLOWSTART option defeats this feature, allowing the first data burst on the net to be a maximum number of segments allowed.

SO_FULLMSS prevents the socket from sending any data until the socket has buffered enough data to send a full sized packet. The size is determined by the network hardware, usually about 1460 data bytes. This should be used judiciously, since it may prevent proper operation of typical network applications. The problem is that an application command will not be sent until enough commands are buffered to produce the full-sized packet. For applications like FTP and HTTP, the average command is much too small to trigger the send. This option will not be available unless the TCP layer has been compiled with the #define SUPPORT_SO_FULLMSS in ipport.h.

The TCP_NODELAY disables the Nagle algorithm, and prevents attempts to coalesce small packets less than the TCP_MSS, while awaiting acknowledgement for data already sent.

TCP_ACKDELAYTIME sets the delay time for TCP delayed ACKs. The number of milliseconds of delay is passed to setsockopt() as a parameter. The millisecond time specified will by rounded off to the nearest "cticks" value. This option will not be available unless the TCP layer has been compiled with the #define DO_DELAY_ACKS in ipport.h. Builds which are compiled with this define will do delayed acks on all sockets by default, with a value of 1 ctick.

The TCP_NOACKDELAY option defeats delayed acking on specific sockets and is not be available unless the TCP layer has been compiled with the #define DO_DELAY_ACKS in ipport.h. Builds which are compiled with this define will do delayed acks on all sockets by default, with a value of 1 ctick. Setting TCP_NOACKDELAY will cause sockets to ack immediately as decided by the TCP code, with no delay.

TCP_MAXSEG is used to set the TCP MSS (Maximum Segment Size) value of the socket. Normally this value default to the size of the largest datagram supported on the underlying media, minus room for TCP, IP, and media headers. On ethernet this number is 1460 octets. This option can be called anytime after the socket is created, and should be called before the socket is connected. Calling after connection will produce unpredictable results. The value passed should generally be smaller than the default value as larger values may result in IP fragmentation.

Returns

t_socket() returns a non-negative descriptor on success. On failure, it returns -1 and sets an internal to one of the errors listed in section 5.2 to indicate the error. The t_errno can be retrieved by a call to t_errno(s).

See Also

t_accept(), t_bind(), t_connect(), t_getsockname(), t_getsockopt(), t_listen(), t_recv(), t_select(), t_send(), t_shutdown()

Name

t_listen()

Syntax

int t_listen(long s, int backlog);

Description

To accept connections, a socket is first created with t_socket(), a backlog for incoming connections is specified with t_listen() and then the connections are accepted with t_accept(). The t_listen() call applies only to sockets of type SOCK_STREAM. The backlog parameter defines the maximum length for the queue of pending connections (not maximum open connections). If a connection request arrives with the queue full the client will receive an error with an indication of ECONNREFUSED.

Returns

Returns 0 on success. On failure, it returns -1 and sets an internal t_errno to one of the errors listed in section 5.2 to indicate the error. The t_errno can be retrieved by a call to t_errno(s).

See Also

t_accept(), t_connect()

Name

t_connect()

Syntax

int t_connect(long s, struct sockaddr *name, int namelen);

Description

The parameter s is a socket. If it is of type SOCK_DGRAM or SOCK_RAW, then this call specifies the peer with which the socket is to be associated; the address is to which datagrams are sent and the only address from which datagrams are received. If it is of type SOCK_STREAM, then 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 t_connect() only once, however in the Interniche Sockets implementation even for a streams socket, if NB_CONNECT is defined in ipport.h_h or the socket is a non-blocking socket, then a socket allows repeated calls to t_connect(). These calls will return 0 once the socket is connected, or a SOCKET_ERROR if it is in the process of connecting.

Datagram and raw sockets may use t_connect() multiple times to change their association. Datagram and raw sockets may also dissolve the association by connecting to an invalid address, such as a zero address.

Returns

This returns 0 on success. On failure, it returns -1 and sets an internal t_errno to one of the errors listed in section 5.2 to indicate the error. The t_errno can be retrieved by a call to t_errno(s).

See Also

t_accept(), t_connect(), t_getsockname(), t_select(), t_socket()

Name

t_socketclose()

Syntax

int t_socketclose(long s);

Note: this is just close() on traditional Sockets systems.

Description

The t_socketclose() call causes all of a full-duplex connection on the socket associated with s to be shut down and the socket descriptor associated with s to be returned to the free socket descriptor pool. Once a socket is closed, no further socket calls should be made with it.

Returns

This returns 0 on success. On failure, it returns -1 and sets an internal t_errno to one of the errors listed in section 5.2 to indicate the error. The t_errno can be retrieved by a call to t_errno(s).

See Also

t_accept(), t_socket()

Name

t_select()

Syntax

int t_select (fd_set * readfds, fd_set * writefds, fd_set * exceptfds; long tv);

void FD_SET (long so, fd_set * set)

void FD_CLR (long so, fd_set * set)

void FD_ISSET (long so, fd_set * set)

void FD_ZERO (fd_set * set)

Description

t_select() examines the socket descriptor sets whose addresses are passed in readfds, writefds, and exceptfds to see if some of their descriptors are ready for reading, ready for writing or have an exception condition pending. On return, t_select() replaces the given descriptor sets with subsets consisting of those descriptors that are ready for the requested operation. The total number of ready descriptors in all the sets is returned. Any of readfds, writefds, and exceptfds may be given as NULL pointers if no descriptors are of interest. Selecting true for reading on a socket descriptor upon which a t_listen() call has been performed indicates that a subsequent t_accept() call on that descriptor will not block.

In the standard Berkeley UNIX Sockets API, the descriptor sets are stored as bit fields in arrays of integers. This works in the UNIX environment because under UNIX socket descriptors are file system descriptors which are guaranteed to be small integers that can be used as indexes into the bit fields. In the InterNiche stack, socket descriptor are pointers and thus a bit field representation of the descriptor sets is not feasible. Because of this, the InterNiche Sockets API differs from the Berkeley standard in that the descriptor sets are represented as instances of the following structure:

typedef struct fd_set {      /* the select socket array manager */
   unsigned fd_count;      /* how many are SET? */
   long fd_array[FD_SETSIZE];   /* an array of SOCKETs */
} fd_set;

Instead of a socket descriptor being represented in a descriptor set via an indexed bit, an InterNiche socket descriptor is represented in a descriptor set by its presence in the fd_array field of the associated fd_set structure. Despite this non-standard representation of the descriptor sets themselves, the following standard entry points are provided for manipulating such descriptor sets: FD_ZERO(&fdset) initializes a descriptor set fdset to the null set. FD_SET(fd, &fdset) includes a particular descriptor, fd, in fdset. FD_CLR(fd, &fdset) removes fd from fdset. FD_ISSET(fd, &fdset) is nonzero if fd is a member of fdset, zero otherwise. These entry points behave according to the standard Berkeley semantics.

The porting engineer should be aware that the value of FD_SETSIZE defines the maximum number of descriptors that can be represented in a single descriptor set. The default value of FD_SETSIZE of 12 is defined in tcp/tcpport.h. This value can be increased to accommodate a larger maximum number of descriptors at the cost of increased processor stack usage.

Another difference between the Berkeley and InterNiche t_select() calls is the representation of the timeout parameter. Under Berkeley Sockets, the timeout parameter is represented by a pointer to a structure. Under InterNiche Sockets, a timeout is specified by the tv parameter, which defines the maximum number of seconds that should elapse before the call to t_select() returns. A tv parameter equal to 0 implies that t_select() should return immediately (effectively a poll of the sockets in the descriptor sets). Note that there is no provision for no timeout, that is, there is no way to specify that t_select() block forever unless one of its descriptors becomes ready. The maximum value (the longest time in seconds) that can be specified for the tv parameter can be calculated by dividing the largest value that can be represented in a variable of type long by the TPS constant (system ticks per second). On PC based systems where longs are typically 32 bits and TPS is 18, this works out to be over 3 years.

The final difference between the Berkeley and InterNiche versions of t_select() is the absence in the InterNiche version of the Berkeley width parameter. The width parameter is of use only when descriptor sets are represented as bit arrays and was thus deleted in the InterNiche implementation.

Returns

t_select() returns a non-negative value on success. A positive value indicates the number of ready descriptors in the descriptor sets. 0 indicates that the time limit specified by tv expired.

See Also

t_accept(), t_connect(), t_listen(), t_recv(), t_send()

Notes

Under rare circumstances, t_select() may indicate that a descriptor is ready for writing when in fact an attempt to write would block. This can happen if system resources necessary for a write are exhausted or otherwise unavailable. If an application deems it critical that writes to a file descriptor not block, it should set the descriptor for non-blocking I/O. See discussion of t_setsockopt().

Name

t_recv()

t_recvfrom()

Syntax

int t_recv(long s, char * buf, int len, int flags);

int t_recvfrom(long s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen);

Description

s is a socket created with t_socket(). t_recv() and t_recvfrom() are used to receive messages from another socket. t_recv() may be used only on a connected socket (see t_connect()), while t_recvfrom() may be used to receive data on a socket whether it is in a connected state or not.

If from is not a NULL pointer, the source address of the message is filled in. fromlen is a value-result parameter, initialized to the size of the buffer associated with from, and modified on return to indicate the actual size of the address stored there. The length of the message is returned. 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 (see t_socket()).

If no messages are available at the socket, the receive call waits for a message to arrive, unless the socket is non-blocking (see t_setsockopt()) in which case -1 is returned with the external variable t_errno set to EWOULDBLOCK.

Note that t_recv() will return an EPIPE if an attempt is made to read from an unconnected socket.

The t_select() call may be used to determine when more data arrive.

The flags parameter is formed by OR-ing one or more of the following:

MSG_OOBRead any "out-of-band" data present on the socket, rather than the regular "in-band" data.
MSG_PEEK"Peek" at the data present on the socket; the data are returned, but not consumed, so that a subsequent receive operation will see the same data.

Returns

These calls return the number of bytes received, or -1 if an error occurred. On failure, they set an internal t_errno to one of the errors listed in section 5.2 to indicate the error. The t_errno can be retrieved by a call to t_errno(s).

See Also

t_connect(),t_getsockopt(),t_select(), t_send(), t_socket()

Name

t_send()

t_sendto()

Syntax

int t_send(long s, char *buf, int len, int flags);

int t_sendto(long s, char *buf, int len, int flags, struct sockaddr *to, int tolen);

Description

t_send() and t_sendto() are used to transmit the message addressed by buf to another socket. t_send() may be used only when the socket is in a connected state, while t_sendto() may be used at any time, in which case the address of the target is given by the to parameter. The length of the message is given by len.

No indication of failure to deliver is implicit in a t_send(). Locally detected errors are indicated by a Return Value of -1.

If no messages space is available at the socket to hold the message to be transmitted, then t_send() normally blocks, unless the socket has been placed in non-blocking I/O mode. The t_select() call may be used to determine when it is possible to send more data.

The flags parameter may include one or more of the following:

#define MSG_OOB         0x1   /* process out-of-band data */
#define MSG_DONTROUTE   0x4   /* bypass routing, use direct interface */

The flag MSG_OOB is used to send "out-of-band" data on sockets that support this notion (e.g. SOCK_STREAM); the underlying protocol must also support "out-of-band" data. MSG_DONTROUTE is usually used only by diagnostic or routing programs.

Returns

The call returns the number of characters sent, or -1 if an error occurred. On failure, it sets an internal t_errno to one of the errors listed in section 5.2 to indicate the error. The t_errno can be retrieved by a call to t_errno(s).

See Also

t_recv(), t_select(), t_getsockopt(), t_socket()

Name

t_accept()

Syntax

long t_accept(long s, struct sockaddr *addr, int *addrlen);

Description

The argument s is a socket that has been created with t_socket(), bound to an address with t_bind() and is listening for connections after a t_listen(). t_accept() extracts the first connection on the queue of pending connections, creates a new socket with the same properties of s and allocates a new file descriptor for the socket. If no pending connections are present on the queue, and the socket is not marked as non-blocking, t_accept() blocks the caller until a connection is present. If the socket is marked non-blocking and no pending connections are present on the queue, t_accept() returns an error as described below. The accepted socket is used to read and write data to and from the socket which connected to this one; it is not used to accept more connections. The original socket s remains open for accepting further connections.

The argument addr is a result parameter that is filled in with the address of the connecting entity as known to the communications layer, i.e. the exact format of the addr parameter is determined by the domain in which the communication is occurring. The addrlen is a value-result parameter. It should initially contain the amount of space pointed to by addr. On return it will contain the actual length (in bytes) of the address returned. This call is used with connection-based socket types, currently with SOCK_STREAM.

It is possible to t_select() a socket for the purposes of doing an t_accept() by selecting it for read.

Returns

t_accept() returns a non-negative descriptor for the accepted socket on success. On failure, it returns -1 and sets an internal t_errno to one of the errors listed in section 5.2 to indicate the error. The t_errno can be retrieved by a call to t_errno(s).

See Also

t_bind(), t_connect(), t_listen(), t_select(), t_socket()

Name

t_bind()

Syntax

int t_bind(long , struct sockaddr *name, int namelen);

Description

t_bind() assigns a name to an unnamed socket. When a socket is created with t_socket() it exists in a name space (address family) but has no name assigned. t_bind() requests that the name pointed to by name be assigned to the socket.

Returns

t_bind() returns 0 on success. On failure, it returns -1 and sets an internal t_errno to one of the errors listed in section 5.2 to indicate the error. The t_errno can be retrieved by a call to t_errno(s).

See Also

t_connect(), t_getsockname(), t_listen(), t_socket()

Name

t_shutdown()

Syntax

int t_shutdown(long s, int how);

Description

The t_shutdown() call causes all or part of a full-duplex connection on the socket associated with s to be shut down. If how is 0, then further receives will be disallowed. If how is 1, then further sends will be disallowed. If how is 2, then further sends and receives will be disallowed.

Returns

This returns 0 on success. On failure, it returns -1 and sets an internal t_errno to one of the errors listed in section 5.2 to indicate the error. The t_errno can be retrieved by a call to t_errno(s).

See Also

t_connect(), t_socket()

Name

t_getpeername()

Syntax

int t_getpeername(long s, struct sockaddr *name, int * addrlen);

Description

Fills in the passed struct sockaddr with the IP addressing information of the connected host.

Returns

This returns 0 on success. On failure, it returns -1 and sets an internal t_errno to one of the errors listed in section 5.2 to indicate the error. The t_errno can be retrieved by a call to t_errno(s).

See Also

t_bind(), t_socket()

Name

t_getsockname()

Syntax

int t_getsockname(long s, struct sockaddr *name, int * addrlen);

Description

t_getsockname() returns the current name for the specified socket, in the passed struct sockaddr.

Returns

This returns 0 on success. On failure, it returns -1 and sets an internal t_errno to one of the errors listed in section 5.2 to indicate the error. The t_errno can be retrieved by a call to t_errno(s).

See Also

t_bind(), t_getpeername(), t_socket()

Name

t_getsockopt()

t_setsockopt()

Syntax

int t_getsockopt(long s, int level, int optname, char *optval, int optlen);

int t_setsockopt(long s, int level, int optname, char *optval, int optlen);

Description

t_getsockopt() and t_setsockopt() manipulate options associated with a socket. The optname parameter identifies an option that is to be set with t_setsockopt() or retrieved with t_getsockopt().

The parameter optval is used to specify option values for t_setsockopt(). On calls to t_setsockopt() it generally contains a pointer to a variable or structure, the contents of which will define the value of the option to be set. On calls to t_getsockopt() it generally points to a variable or structure into which the value for the requested option is to be returned.

The include file socket.h contains definitions for option names, described below. Most options take a pointer to an int variable for optval. For t_setsockopt(), the variable addressed by the parameter should be non-zero to enable a Boolean option or zero if the option is to be disabled.

SO_LINGER uses a struct linger parameter defined in socket.h. This parameter specifies the desired state of the option and the linger interval (see below).

In addition to those referenced in section 5.4 (Quick List for Socket Options), the following options are recognized by the InterNiche stack. Except as noted, each may be examined with t_getsockopt() and set with t_setsockopt().

SO_DEBUGtoggle recording of debugging information
SO_REUSEADDRtoggle local address reuse
SO_KEEPALIVEtoggle keep connections alive
SO_DONTROUTEtoggle routing bypass for outgoing messages
SO_LINGERlinger on close if data present
SO_BROADCASTtoggle permission to transmit broadcast messages
SO_OOBINLINEtoggle reception of out-of-band data in band
SO_SNDBUFset buffer size for output
SO_RCVBUFset buffer size for input
SO_TYPEget the type of the socket (get only)
SO_ERRORget and clear error on the socket (get only)
SO_CALLBACKset a callback function for the socket (set only)
IP_HDRINCLset inclusion of IP header in data (SOCK_RAW only)
SO_DEBUGenables debugging in the underlying protocol modules.

SO_REUSEADDR

indicates that the rules used in validating addresses supplied in a t_bind() call should allow reuse of local addresses. 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. If the process is waiting in t_select() when the connection is broken, t_select() returns true for any read or write events selected for the socket. 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.
SO_LINGERcontrols the action taken when unsent messages are queued on socket and a t_socketclose() is performed. If the socket promises reliable delivery of data and SO_LINGER is set, the system will block the caller on the t_socketclose() 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 t_setsockopt() call when SO_LINGER is requested). If SO_LINGER is disabled and a t_socketclose() is issued, the system will process the close in a manner that allows the caller to continue as quickly as possible.

The option SO_BROADCAST requests permission to send broadcast datagrams on the socket. Note that the InterNiche stack supports the setting and getting of this option for compatibility but does not check its value when transmitting broadcast messages.

With protocols that support out-of-band data, the 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 t_recv() calls without the MSG_OOB flag. SO_SNDBUF and SO_RCVBUF are options to adjust the normal buffer sizes allocated for the 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. The system places an absolute limit on these values.

SO_TYPE and SO_ERROR are options used only with t_getsockopt(). SO_TYPE returns the type of the socket, for example SOCK_STREAM. 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.

The IP_HDRINCL option is used only with sockets of type SOCK_RAW. The option value (pointed to by optval) is expected to be an integer; if it is non-zero it allows application access to the IP header, meaning that received datagrams include an IP header and sent datagrams are expected to be constructed with an IP header at the start of the buffer passed to the t_send() function. Its default setting is zero.

The options SO_NONBLOCK, SO_NBIO, and SO_BIO are unique to the InterNiche stack (these options do not appear in the Berkeley Sockets API) and are used to control whether a socket uses blocking or non-blocking IO.

SO_NONBLOCK allows the caller to specify blocking or non-blocking IO that works the same as the other Boolean socket options. That is, optval points to an integer value which will contain a non-zero value to set non-blocking IO or a 0 value to reset non-blocking IO. This means that we can get the current blocking or non-blocking status of a socket with t_getsockopt().

For compatibility, older InterNiche Sockets options SO_NBIO and SO_BIO are still supported. SO_NBIO is used to specify that a socket use non-blocking IO. SO_BIO is used to specify that a socket use blocking IO. The use of t_setsockopt() to set these options is different than that of the standard Boolean options in that the value in optval is not used. All that is necessary is to specify the appropriate option name in optname.

SO_NBIOSet socket to use non-blocking IO.
SO_BIOSet socket to use blocking IO.

The SO_CALLBACK option is also specific to the InterNiche stack and is only available if the stack has been built with the TCP_ZEROCOPY option enabled. See section 6, "TCP Zero-Copy" for more information about this option.

Returns

These return 0 on success. On failure, they return -1 and set an internal t_errno to one of the errors listed in section 5.2 to indicate the error. The t_errno can be retrieved by a call to t_errno(s).

See Also

Section 5.4 Quick List for Socket Options

t_socket()