3.2  STREAMS Sockets Programming

In VxWorks, STREAMS sockets serve as one interface to the STREAMS protocol suites. Sockets are designed to provide a consistent communication facility for tasks, regardless of whether or not the tasks are on the same machine. In addition, sockets are designed to hide as much detail as possible regarding the way in which the underlying communication occurs.

A socket is an endpoint for communication that gets bound to a port within the node. Each socket in use has a type and is associated with a communication domain when it is created. Domains are abstractions that imply both an addressing structure and a set of protocols that implement socket types within the domain.

3.2.1  Socket Architecture in VxWorks

Figure 8 shows the architecture for socket communication in a VxWorks environment. Applications make calls that are handled by the socket layer. The socket layer translates a file descriptor to a socket and invokes a routine in the protocol layer to service the call. The socket data structure is shared between the socket layer and protocol layer. The protocol layer communicates with the network driver to send and receive packets to or from the network.

3.2.2  Socket Architecture in WindNet STREAMS

The socket mechanism is implemented in the STREAMS framework, as shown in Figure 9. A user-level library (configured by defining INCLUDE_STREAMS_SOCKET in configAll.h; see §6.1 Configuring VxWorks for WindNet STREAMS) provides socket calls, such as socket( ), connect( ) , bind( ), etc. These library routines interact with a STREAMS module, sockmod, that is pushed on top of a STREAMS-based transport provider. The socket library and sockmod work in close cooperation. When semantics allow, the socket library creates TPI messages equivalent to socket( ), and sockmod passes the message to the transport provider. For other calls, the socket library does almost nothing except issue an ioctl( ) that is intercepted by sockmod, which in turn creates a TPI message and interacts with the transport provider to complete the request. §3.2.4 Addition of Transport Providers to WindNet STREAMS Sockets explains how this implementation has the undesirable effect of making it difficult to provide transport independence at the socket layer.

3.2.3  WindNet STREAMS Socket Library

The WindNet STREAMS socket library is provided to enable porting of existing socket applications to a STREAMS environment by relinking object code with the library. No source code changes should be required. Table 2 lists the basic socket routines found in the WindNet STREAMS socket library.

Table 2.   WindNet STREAMS Socket Routines


Routine
Description


socket( )
Create a socket.
bind( )
Bind a name to a socket.
listen( )
Enable connections to a STREAMS socket.
accept( )
Accept a connection on a STREAMS socket.
connect( )
Initiate a connection on a socket.
shutdown( )
Shutdown a socket connection.
send( )
Send data to a STREAMS socket.
sendto( )
Send a message to a datagram socket.
sendmsg( )
Send a message to a datagram socket.
recv( )
Receive data from a STREAMS socket.
recvfrom( )
Receive a message from a datagram socket.
recvmsg( )
Receive a message from a datagram socket.
setsockopt( )
Set socket options.
getsockopt( )
Get socket options.
getsockname( )
Get the name of a socket.
getpeername( )
Get the name of a connected peer socket.
strmSockProtoAdd( )
Add transport provider to STREAMS socket library.
read( )
Read from a socket.
write( )
Write to a socket.
ioctl( )
Perform control functions on a socket.

WindNet STREAMS sockets are compatible with the VxWorks BSD 4.3 interface. However, there are known differences between STREAMS sockets and BSD sockets. Those differences are listed in Table 3.

Table 3.   VxWorks Sockets Versus STREAMS Sockets


Subject
BSD Sockets
STREAMS Sockets


FIONREAD ioctl
FIONREAD ioctl returns the number of bytes available to be read, including any inline OOB (out-of-band) data.
This is a STREAMS issue. For example, SVR4 systems translate this ioctl into the STREAMS I  NREAD ioctl, which only reports the number of bytes in the first data message at the stream head. VxWorks supports the FIONREAD ioctl directly, so behavior is the same as for BSD sockets.
Newly-arriving OOB (out-of-band) bytes
If a marked byte is at the front of the read queue, a newly-arriving OOB byte does not clear the first mark. This behavior is inconsistent with the case when another marked byte is not at the front of the read queue.
A newly-arriving OOB byte always clears previous marked bytes, even at the front of the read queue.
Marked bytes
When OOB data is inline, and the marked (OOB) byte is at the front of the read queue, and n bytes are read, the marked byte and n-1 bytes after it will be returned.
Marked bytes are in their own 1-byte message, so only the first marked byte is returned. This difference should never be seen by a "correctly written" application.
recv( ) with the MSG_PEEK parameter
The recv( ) routine used with MSG_PEEK returns the lesser of the number of bytes requested and the number of bytes available up to any data mark.
The recv( ) routine with MSG_PEEK returns the number of bytes in the first message at the stream head.
write( )
The write( ) routine on an unconnected socket fails with error ENOTCONN.
The write( ) routine on an unconnected socket fails with error ERANGE.
Disconnected sockets and write( ) or send( )
If a write( ) or send( ) is attempted on a disconnected socket, the system call returns EPIPE, but no signal is generated.
When a T_DISCON_IND primitive is received, sockmod sets the stream head write-side error state to EPIPE. Subsequent write( ) or send( ) calls will return an error, but no signal is generated.

3.2.4  Addition of Transport Providers to WindNet STREAMS Sockets

The STREAMS socket library has an inherent deficiency that has been remedied by WindNet STREAMS: In STREAMS, there is no transport provider independence at the socket layer because the socket associates itself with the transport provider by opening the transport provider device; thus, socket( ) cannot open different providers based on socket parameter values. The WindNet STREAMS socket implementation provides transport independence through a routine, strmSockProtoAdd( ).

The strmSockProtoAdd( ) routine registers a new transport provider by adding an entry to an internally-maintained table that contains information about available transport providers. The table's data is based on the following three parameters passed by strmSockProtoAdd( ):

family
specifies the address family

type
defines the socket type

devName
defines the transport provider device name

When a socket call is made, the socket library, where the table is located, decides which transport provider to use based on the parameters passed by the socket call. The strmSockProtoAdd( ) routine is usually invoked at system initialization. It must be called before socket( ).

The strmSockProtoAdd( ) routine creates an association among the parameter values--for a unique family and type, there is a unique transport provider specified by devName-- so when socket( ) is called, the parameters that have been passed to it prompt the library to select the appropriate transport provider. For example, the following code fragment associates socket calls using the address family AF_INET and the socket type SOCK_STREAM with the transport provider /dev/tcp. The socket call establishes the transport endpoint using the TCP transport provider.

strmSockProtoAdd (AF_INET, SOCK_STREAM,"/dev/tcp");
socket (AF_INET,SOCK_STREAM,0);

In the following code fragment, socket calls that use the address family AF_INET and socket type SOCK_DGRAM are associated with the transport provider /dev/udp. The socket call establishes the transport endpoint using the UDP transport provider.

strmSockProtoAdd (AF_INET, SOCK_DGRAM,"/dev/udp");
socket (AF_INET,SOCK_DGRAM,0);

In this third example, socket calls that use the address family AF_CCITT have been associated with the socket type SOCK_STREAM with the transport provider /dev/x25.

strmSockProtoAdd (AF_CCITT,SOCK_STREAM,"/dev/x25");
socket (AF_CCITT,SOCK_STREAM,0);

3.2.5  Using Native VxWorks Sockets and WindNet STREAMS Sockets

WindNet STREAMS sockets are designed to co-exist with VxWorks BSD sockets, which are discussed in the VxWorks Programmer's Guide: Network. This is achieved using a layered operating environment, that is, the VxWorks socket library is a layer above the BSD socket and WindNet STREAMS socket layers, as shown in Figure 10.

Calls to routines in the VxWorks socket library are directed to the appropriate underlying socket library, either BSD or WindNet STREAMS, based on the default defined in configAll.h or the parameters passed to the socket layer. The BSD socket library is configured into the VxWorks system image, making it the system default. You can define configuration constants to make WindNet STREAMS sockets an alternate default. The routine socket( )creates a communication endpoint in either the BSD or WindNet STREAMS socket library based on the parameters passed to it, and thus designates the socket library to be used by your application.

The following constants have been newly added to configAll.h and configure the specified socket library into VxWorks and make it the default choice:

INCLUDE_BSD_SOCKETS
This constant is defined by default. It ensures that socket calls with the first parameter defined as AF_INET or AF_INET_BSD access the BSD socket library.

INCLUDE_STREAMS_SOCKET
Define this constant to include the STREAMS socket library into VxWorks.

DEFAULT_STREAMS_SOCKET
Define this constant to ensure that socket calls using AF_INET as the first parameter access the WindNet STREAMS socket library.

The following two VxWorks-specific constants are newly defined in sys/socket.h and when passed to socket( ) they direct socket application calls to the related socket library:

AF_INET_BSD
This address family provides access to the BSD socket library when it is used as the first parameter in the socket( ) call. It is used when DEFAULT_STREAM_SOCKET is defined in configAll.h.

AF_INET_STREAMS
This address family provides access to the WindNet STREAMS socket library when it is used as the first parameter in the socket( ) call. It is used when DEFAULT_STREAMS_SOCKET is not defined.

To configure your environment for BSD sockets, no new steps need be taken because INCLUDE_BSD_SOCKETS is defined in configAll.h by default.

To configure your environment for WindNet STREAMS sockets, define INCLUDE_STREAMS_SOCKET in configAll.h. This constant alone does not make the default socket layer the WindNet STREAMS socket library; it only configures into VxWorks WindNet STREAMS sockets. To change the default, you must define DEFAULT_STREAMS_SOCKET in configAll.h.

The following examples show how to use WindNet STREAMS sockets and BSD sockets separately or concurrently:

To use BSD sockets:

  1. When the BSD socket library is configured into VxWorks and is the default socket layer, use the following command:

socket (AF_INET, SOCK_STREAM,0) 

  1. When both libraries have been configured into VxWorks and WindNet STREAMS is the default socket layer, use the following command:

socket (AF_INET_BSD, SOCK_STREAM,0) 

To use WindNet STREAMS sockets:

  1. When the WindNet STREAMS socket library is configured into VxWorks and WindNet STREAMS is the default socket layer, use the following command:

socket (AF_INET, SOCK_STREAM,0) 

  1. When both libraries are configured into VxWorks and BSD is the default socket layer, use the following command:

socket (AF_INET_STREAMS, SOCK_STREAM, 0)