osiSock.h

Platform independent socket support library API.

osiSock library contains platform independent APIs for creating sockets, converting between socket address structures and human readable strings, and configuring sockets.

Enums

enum epicsSocketSystemCallInterruptMechanismQueryInfo

Enum specifying how to interrupt a blocking socket system call.

This enum specifies how to interrupt a blocking socket system call. Fortunately, on most systems the combination of a shutdown of both directions and/or a signal is sufficent to interrupt a blocking send, receive, or connect call. For odd ball systems this is stubbed out in the osi area.

Values:

enumerator esscimqi_socketCloseRequired

Calling close() required to interrupt.

enumerator esscimqi_socketBothShutdownRequired

calling shutdown() for both read and write required to interrupt

enumerator esscimqi_socketSigAlarmRequired

NO LONGER USED/SUPPORTED.

Functions

SOCKET epicsSocketCreate(int domain, int type, int protocol)

Create a socket object.

Ask the operating system to create a socket and return its file descriptor.

Parameters:
  • domain – The socket domain, e.g. PF_INET

  • type – The type of socket, e.g. SOCK_STREAM (tcp) or SOCK_DGRAM (udp)

  • protocol – Typically unused and set to 0.

Returns:

A file descriptor referring to the socket, or -1 on error.

SOCKET epicsSocketAccept(SOCKET sock, struct sockaddr *pAddr, osiSocklen_t *addrlen)

Accept a connection on a listening stream socket.

epicsSocketAccept is used with connection-based sockets. It takes the next connection request in the queue and returns a new socket that can be used to communicate with the listener.

Parameters:
  • sock – socket with pending connections to accept

  • pAddr – If not NULL, this socket contains the address of the peer whose connection is being accepted

  • addrlen[inout] Caller must initialize this to the length of the structure pointed to by pAddr, or set to NULL if pAddr is NULL. This function will update the value of this parameter to the actual size of the peer address.

Returns:

A new socket used for communicating with the peer just accepted, or -1 on error.

void epicsSocketDestroy(SOCKET)

Close and free resources held by a SOCKET object.

Close and free resources held by a SOCKET object.

void epicsSocketEnableAddressReuseDuringTimeWaitState(SOCKET s)

Allows a socket to bind ignoring other sockets in TIME_WAIT state.

Allows a socket to bind while other sockets hold the same address and port but are in the TIME_WAIT state. TIME_WAIT is a state where a socket has closed locally, but is waiting to be closed on the remote end. If the remote end doesn’t respond, this can block another socket from binding to that address:port for a long time (possibly minutes). This option allows the socket to bind to an address:port combo, even if there’s another socket with the same address:port that’s waiting for the remote side to close its connection.

See also: Linux’s SO_REUSEADDR in setsockopt.

Parameters:

s – The socket to ignore other TIME_WAIT sockets when binding

void epicsSocketEnableAddressUseForDatagramFanout(SOCKET s)

Allows multiple sockets to use the same family, local address, and local port.

Allows multiple sockets to use the same family, local address, and port. By having multiple sockets open with this setting enabled, the OS will distribute the datagrams (for UDP sockets) or connection requests (for TCP/stream sockets) among the sockets with this option set. Note that all sockets binding to the same address and port must have this option set.

As an example, this option could be a way to implement a form of load balancing between multiple threads or processes with sockets bound to the same address:port.

Parameters:

s – The socket to put in “Fanout” mode (aka REUSEPORT mode)

enum epicsSocketSystemCallInterruptMechanismQueryInfo epicsSocketSystemCallInterruptMechanismQuery()

Query what approach to use to interrupt blocking socket calls.

This function tells you what approach to use to interrupt calls blocked on socket operations.

Returns:

enum representing whether to call close() or shutdown(RW) to interrupt blocking socket syscalls.

unsigned sockAddrToA(const struct sockaddr *paddr, char *pBuf, unsigned bufSize)

Convert socket address to ASCII.

Converts a socket address to an ASCII string. Conversion occurs in this order:

  1. look for matching host name and typically add trailing IP port

  2. failing that, convert to raw ascii address (typically this is a dotted IP address with trailing port)

  3. failing that, writes “<Ukn Addr Type>” into pBuf

Parameters:
  • paddr – sockaddr structure to convert to ascii address:port

  • pBuf[out] Pointer to the output buffer contantaining the address:port string

  • bufSize – Length of pBuf array

Returns:

The number of character elements stored in buffer not including the null termination, but always writes at least a null terminator in the string (if bufSize >= 1)

unsigned ipAddrToA(const struct sockaddr_in *pInetAddr, char *pBuf, unsigned bufSize)

Convert IP address to ASCII.

Convert an IP address to an ASCII string. Conversion occurs in this order: 1) look for matching host name and add trailing port 2) convert to raw dotted IP address with trailing port

Parameters:
  • pInetAddr – sockaddr_in structure to convert to address string

  • pBuf[out] Pointer to the char array where the address string will be stored

  • bufSize – Length of the array to which pBuf points

Returns:

The number of character elements stored in buffer not including the null termination, but always writes at least a null terminator in the string (if bufSize >= 1)

unsigned sockAddrToDottedIP(const struct sockaddr *paddr, char *pBuf, unsigned bufSize)

Convert to raw dotted IP address with trailing port.

Convert an address to a raw dotted IP address. Compared to sockAddrToA(), this call will always convert to a raw dotted IP (e.g. 192.168.0.1) and not use host names (e.g. localhost) when available

Parameters:
  • paddr – sockaddr structure containing the node and service info to convert to strings

  • pBuf[out] Pointer to a character buffer where the output string will be placed.

  • bufSize – Size of the array pointed to by pBuf

Returns:

The number of character elements stored in buffer not including the null termination, but always writes at least a null terminator in the string (if bufSize >= 1)

unsigned ipAddrToDottedIP(const struct sockaddr_in *paddr, char *pBuf, unsigned bufSize)

Convert to raw dotted IP address with trailing port.

Convert a sockaddr_in to a raw dotted IP address string with trailing port. Similar to sockAddrToDottedIP but takes a sockaddr_in structure.

Parameters:
  • paddr – sockaddr_in structure containing the node and service info to convert to strings

  • pBuf[out] Pointer to a character buffer where the output string will be placed

  • bufSize – Size of the array pointed to by pBuf

Returns:

The number of character elements stored in buffer not including the null termination, but always writes at least a null terminator in the string (if bufSize >= 1)

unsigned ipAddrToHostName(const struct in_addr *pAddr, char *pBuf, unsigned bufSize)

Convert inet address to a host name string.

Convert an inet address to a host name string. There are many OS specific implementation stubs for this routine

Parameters:
  • pAddr – sockaddr_in structure containing the node and service info to convert to strings

  • pBuf[out] Pointer to a character buffer where the output string will be placed

  • bufSize – Size of the array pointed to by pBuf

Returns:

the number of character elements stored in buffer not including the null termination. This will be zero if a matching host name cant be found.

int aToIPAddr(const char *pAddrString, unsigned short defaultPort, struct sockaddr_in *pIP)

Attempt to convert ASCII string to an IP address.

Attempt to convert ASCII string to an IP address. Conversion occurs this order:

  1. look for traditional doted ip with optional port

  2. look for raw number form of ip address with optional port

  3. look for valid host name with optional port

Parameters:
  • pAddrString – IP address string to convert to a sockaddr_in (e.g. “192.168.0.1:80”)

  • defaultPort – The default port (service) to use if not specified in pAddrString

  • pIP[out] Pointer to a sockaddr_in where the converted address info will be stored

Returns:

negative value on error, 0 on success.

int hostToIPAddr(const char *pHostName, struct in_addr *pIPA)

Attempt to convert ASCII host name string with optional port to an IP address.

Convert an in_addr struct to a human readable hostname.

Parameters:
  • pHostName – ASCII host name to convert

  • pIPA[out] Pointer to the in_addr structure where the hostname information will be stored

Returns:

0 on success, negative on error.

int osiSockAttach(void)

attach to BSD socket library

Attach to the BSD socket library in preparation for using sockets. If the OS does not require attaching to the socket library, this function does nothing.

Returns:

true on success, false on error.

void osiSockRelease(void)

release BSD socket library

Release the BSD socket library if the OS requires it. For platforms that do not require attaching and releasing to use the socket library, this function does nothing.

void epicsSocketConvertErrorToString(char *pBuf, unsigned bufSize, int error)

convert socket error numbers to a string

There are several system functions which set errno on failure. This function converts that error number into a string describing the error.

Parameters:
  • pBuf[out] Pointer to char array where the error string will be stored

  • bufSize – Length of the array pointed to by pBuf

  • error – The error number to describe in string form

void epicsSocketConvertErrnoToString(char *pBuf, unsigned bufSize)

Convert the currently set errno to a string.

errno is a global integer that gets set when certain functions return an error. This function converts that error value into a string describing the error.

Parameters:
  • pBuf[out] Pointer to char array where the error string will be stored

  • bufSize – Length of the array pointed to by pBuf

int sockAddrAreIdentical(const osiSockAddr *plhs, const osiSockAddr *prhs)

Compares two osiSockAddrs.

Compares two osiSockAddrs

Returns:

true if addresses are identical, false otherwise.

void osiSockDiscoverBroadcastAddresses(ELLLIST *pList, SOCKET socket, const osiSockAddr *pMatchAddr)

Add available broadcast addresses to a list.

Add available broadcast addresses to a list. This routine is provided with the address of an ELLLIST, a socket, and a match address. When the routine returns there will be one additional entry in the list for each network interface found that is up and isn’t a loop back interface (match addr is INADDR_ANY), or only the interfaces that match the specified addresses (match addr is other than INADDR_ANY). If the interface supports broadcasting then add its broadcast address to the list. If the interface is a point to point link then add the destination address of the point to point link to the list.

Any mutex locking required to protect pList is applied externally.

Example

ELLLIST ifaces = ELLLIST_INIT;
ELLNODE * cur;
SOCKET dummy = epicsSocketCreate(AF_INET, SOCK_DGRAM, 0);
osiSockAddr match;

memset(&match, 0, sizeof(match));
match.ia.sin_family = AF_INET;
match.ia.sin_addr.s_addr = htonl(INADDR_ANY);

osiSockDiscoverBroadcastAddresses(&ifaces, dummy, &match);
for (cur = ellFirst(&ifaces); cur; cur = ellNext(cur)) {
    char name[64];
    osiSockAddrNode * n = CONTAINER(cur, osiSockAddrNode, node);
    node->addr.ia.sin_port = htons(5555);
    sockAddrToDottedIP(&node->addr.sa, name, sizeof(name);
    fprintf(stderr, "Node is %s", name);
}
ellFree(&ifaces);
epicsSocketDestroy(dummy);

Parameters:
  • pList[out] Pointer to a list where network interfaces will be added as new osiSockAddrNode’s

  • socket – (May be unused)

  • pMatchAddr – Only add addresses that match this address. Use match.ia.sin_addr.s_addr = htonl(INADDR_ANY) to match any address.

Returns:

The broadcast addresses of each network interface found.

osiSockAddr osiLocalAddr(SOCKET socket)

Returns the osiSockAddr of the first non-loopback interface found that is operational (up flag is set). If no valid address can be located then return an osiSockAddr with the address family set to unspecified (AF_UNSPEC).

Unfortunately in EPICS 3.13 beta 11 and before the CA repeater would not always allow the loopback address as a local client address so current clients alternate between the address of the first non-loopback interface found and the loopback address when subscribing with the CA repeater until all CA repeaters have been updated to current code.

Note

After all CA repeaters have been restarted this osi interface can be eliminated.

union osiSockAddr
#include <osiSock.h>

Union to switch between sockaddr_in and sockaddr.

A union to switch between sockaddr_in and sockaddr. Several socket related calls require casting between a sockaddr and a sockaddr_in. This union makes that casting between the two more convenient.

Public Members

struct sockaddr_in ia
struct sockaddr sa
struct osiSockAddrNode
#include <osiSock.h>

Stores a list of socket addresses.

Container to store a list of socket addresses

Public Members

ELLNODE node
osiSockAddr addr