Extensible Connection-oriented Messaging (XCM)
Loading...
Searching...
No Matches
Macros | Functions
xcm.h File Reference

Core XCM API. More...

#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
#include <sys/types.h>
#include <xcm_attr_map.h>
#include <xcm_compat.h>

Go to the source code of this file.

Macros

#define XCM_NONBLOCK   (1<<0)
 
#define XCM_SO_RECEIVABLE   (1<<0)
 
#define XCM_SO_SENDABLE   (1<<1)
 
#define XCM_SO_ACCEPTABLE   (1<<2)
 

Functions

struct xcm_socket * xcm_connect (const char *remote_addr, int flags)
 
struct xcm_socket * xcm_connect_a (const char *remote_addr, const struct xcm_attr_map *attrs)
 
struct xcm_socket * xcm_server (const char *local_addr)
 
struct xcm_socket * xcm_server_a (const char *local_addr, const struct xcm_attr_map *attrs)
 
int xcm_close (struct xcm_socket *socket)
 
void xcm_cleanup (struct xcm_socket *socket)
 
struct xcm_socket * xcm_accept (struct xcm_socket *server_socket)
 
struct xcm_socket * xcm_accept_a (struct xcm_socket *server_socket, const struct xcm_attr_map *attrs)
 
int xcm_send (struct xcm_socket *__restrict conn_socket, const void *__restrict buf, size_t len)
 
int xcm_receive (struct xcm_socket *__restrict conn_socket, void *__restrict buf, size_t capacity)
 
int xcm_await (struct xcm_socket *socket, int condition)
 
int xcm_fd (struct xcm_socket *socket)
 
int xcm_finish (struct xcm_socket *socket)
 
int xcm_set_blocking (struct xcm_socket *socket, bool should_block)
 
bool xcm_is_blocking (struct xcm_socket *socket)
 
const char * xcm_remote_addr (struct xcm_socket *conn_socket)
 
const char * xcm_local_addr (struct xcm_socket *socket)
 

Detailed Description

Core XCM API.

Macro Definition Documentation

◆ XCM_NONBLOCK

#define XCM_NONBLOCK   (1<<0)

Flag used in xcm_connect()

◆ XCM_SO_RECEIVABLE

#define XCM_SO_RECEIVABLE   (1<<0)

Flag bit denoting a socket where the application likely can receive data.

◆ XCM_SO_SENDABLE

#define XCM_SO_SENDABLE   (1<<1)

Flag bit denoting a socket where the application likely can send data.

◆ XCM_SO_ACCEPTABLE

#define XCM_SO_ACCEPTABLE   (1<<2)

Flag bit denoting a socket with a pending incoming connection.

Function Documentation

◆ xcm_connect()

struct xcm_socket * xcm_connect ( const char *  remote_addr,
int  flags 
)

Connects to a remote server socket.

This function returns a connection socket, which is used to send messages to, and receive messages from the server.

In BSD Sockets terms, this call does both socket() and connect().

By default, xcm_connect() blocks for the time it takes for the transport to determine if the named remote endpoint exists, and is responding (including any initial handshaking, key exchange etc). If the remote server socket is not yet bound, it's up to the application to retry.

If the XCM_NONBLOCK flag is set, xcm_connect() will work in a non-blocking fashion and will always return immediately, either leaving the connection socket in a connected state, a partly connected state, or signaling an error.

Setting XCM_NONBLOCK will leave the connection in non-blocking mode (see xcm_set_blocking() for details).

See Event-driven Programming Support for an overview how non-blocking mode is used.

For non-blocking connection establishment attempts, the application may use xcm_finish() the query the result. It should use xcm_fd() and select() to wait for the appropriate time to make the xcm_finish() call (although it may be called at any point).

xcm_connect() with the XCM_NONBLOCK flag set will leave the connection in non-blocking mode (see xcm_set_blocking() for details).

Since the "xcm.service" attribute defaults to "messaging", this function cannot be used to create connectionx sockets with the byte stream service type.

Parameters
[in]remote_addrThe remote address which to connect.
[in]flagsEither 0, or XCM_NONBLOCK for a non-blocking connect.
Returns
Returns a socket reference on success, or NULL if an error occured (in which case errno is set).
errno Description
EINVAL Invalid address format.
ENOPROTOOPT Transport protocol not available.

See xcm_finish() for other possible errno values.

See also
xcm_close

◆ xcm_connect_a()

struct xcm_socket * xcm_connect_a ( const char *  remote_addr,
const struct xcm_attr_map *  attrs 
)

Connects to a remote server socket, with attributes.

This function is equivalent to xcm_connect(), only it also allows the caller to specify a set of Socket Attributes to be applied as a part of the connection establishment.

The primary reasons for this function is to allow setting attributes that needs to be set prior to, or during, actual connection establishment. In addition, xcm_connect_a() serves as a convenience function, letting applications avoid repeated xcm_attr_set() calls.

Parameters
[in]remote_addrThe remote address which to connect.
[in]attrsA set of attributes to be applied to the connection socket, or NULL. Only accessed during the call.
Returns
Returns a socket reference on success, or NULL if an error occured (in which case errno is set).

See xcm_connect() and xcm_attr_set() for possible errno values.

◆ xcm_server()

struct xcm_socket * xcm_server ( const char *  local_addr)

Creates a server socket and binds it to a specific address.

This function creates a server socket and binds it to a specific address. After this call has completed, clients may connect to the address specified.

This call is the equivalent of socket()+bind()+listen() in BSD Sockets. In case remote_addr has a DNS domain name (as opposed to an IP address), an xcm_server() call also includes a blocking name resolution (e.g. gethostbyname()).

Since the "xcm.service" attribute defaults to "messaging", this function cannot be used to create server sockets with the byte stream service type.

Parameters
[in]local_addrThe local address to which this socket should be bound.
Returns
Returns a server socket reference on success, or NULL if an error occured (in which case errno is set).
errno Description
EACCESS Permission to create the socket was denied.
EADDRINUSE Local socket address is already in use.
ENOMEM Insufficient memory.
EINVAL Invalid address format.
ENOPROTOOPT Transport protocol not available.
EMFILE The per-process limit on the number of open file descriptors has been reached.
ENFILE The limit on the total number of open file descriptors has been reached.
EPROTO A protocol error occured.
ENOENT DNS domain name resolution failed.
See also
xcm_close

◆ xcm_server_a()

struct xcm_socket * xcm_server_a ( const char *  local_addr,
const struct xcm_attr_map *  attrs 
)

Creates and binds to a server socket, with attributes.

This function is equivalent to xcm_server(), only it also allows the caller to specify a set of Socket Attributes to be applied as a part of server socket creation.

Parameters
[in]local_addrThe local address to which this socket should be bound.
[in]attrsA set of attributes to be applied to the socket, or NULL. Only accessed during the call.
Returns
Returns a server socket reference on success, or NULL if an error occured (in which case errno is set).

See xcm_server() and xcm_attr_set() for possible errno values.

◆ xcm_close()

int xcm_close ( struct xcm_socket *  socket)

Close an endpoint.

This function close an XCM socket, including both signaling to the far and freeing of any local resources associated with this socket.

xcm_close() will not block, and applications wanting to finish any outstanding tasks on a socket in non-blocking mode should use xcm_finish() to do so.

Parameters
[in]socketThe socket to be closed, or NULL (in case xcm_close() is a no-operation).
Returns
Always returns 0.
See also
xcm_cleanup

◆ xcm_cleanup()

void xcm_cleanup ( struct xcm_socket *  socket)

Cleans up any local resources tied to an XCM socket not owned by the caller process.

After a fork() call, either of the two processes (the parent, or the child) must be designated the owner of every XCM socket the parent owned.

The owner may continue to use the XCM socket normally.

The non-owner may use xcm_cleanup() to free any local memory tied to this socket, without impacting the connection state in the owner process.

The non-owner may not call xcm_close() or any other XCM API call.

The owner may not call xcm_cleanup().

Parameters
[in]socketThe socket which local resources are to be freed, or NULL (in case xcm_cleanup() is a no-operation).

◆ xcm_accept()

struct xcm_socket * xcm_accept ( struct xcm_socket *  server_socket)

Retrieve a pending incoming connection from the server socket's queue.

xcm_accept() retrieves the first connection request from the server socket's queue of pending connections.

In case the server socket is in non-blocking mode, the XCM connection socket returned from xcm_accept() will also be in non-blocking mode.

Parameters
[in]server_socketThe server socket on which to attempt to accept one pending connection.
Returns
Returns a newly created XCM connection socket on success, or NULL if an error occured (in which case errno is set).

See xcm_finish() for possible errno values.

◆ xcm_accept_a()

struct xcm_socket * xcm_accept_a ( struct xcm_socket *  server_socket,
const struct xcm_attr_map *  attrs 
)

Retrieve a pending incoming connection, with attributes.

This function is equivalent to xcm_accept(), only it also allows the caller to specify a set of Socket Attributes to be applied as a part of accepting the new connection socket.

Such attributes will override any value inherited from the server socket.

Parameters
[in]server_socketThe server socket on which to attempt to accept one pending connection.
[in]attrsA set of attributes to be applied to the socket, or NULL. Only accessed during the call.
Returns
Returns a newly created XCM connection socket on success, or NULL if an error occured (in which case errno is set).

See xcm_accept() and xcm_attr_set() for possible errno values.

◆ xcm_send()

int xcm_send ( struct xcm_socket *__restrict  conn_socket,
const void *__restrict  buf,
size_t  len 
)

Send message on a particular connection.

The xcm_send() function is used to send a message (or a sequence of bytes, for byte stream transports) out on a connection socket.

Parameters
[in]conn_socketThe connection socket the data will be sent on.
[in]bufA pointer to the data buffer.
[in]lenThe length of the buffer in bytes. Zero-length buffers are not allowed for messaging type transports.
Returns
For messaging transports, 0 is returned on success. For byte stream transports, the number of bytes accepted into the XCM layer is returned (which may be shorter than len, but which is always greater than zero). In case of an error, -1 is returned (and errno is set).
errno Description
EMSGSIZE Message is too large. See also the maximum size attribute in Generic Attributes. Only applicable to messaging transports.

See xcm_finish() for more errno values.

◆ xcm_receive()

int xcm_receive ( struct xcm_socket *__restrict  conn_socket,
void *__restrict  buf,
size_t  capacity 
)

Receive message on a particular connection.

The xcm_receive() function is used to receive data on a connection socket. For messaging type transport connections, xcm_receive() produces at most one message, in its entirety. For byte stream transports, xcm_receive() returns a sequence of bytes.

If the connection is of the messaging service type and the capacity of the user-supplied buffer is smaller than the actual message length, the message will be truncated and the part that fits will be stored in the buffer. The return value will be the length of the truncated message (i.e. the capacity).

Parameters
[in]conn_socketThe connection socket the data will receive be on.
[out]bufThe user-supplied buffer where the incoming data will be stored.
[in]capacityThe capacity in bytes of the buffer.
Returns
Returns the amount (> 0 bytes) of data stored in the buffer, 0 if the remote end has closed the connection, or -1 if an error occured (in which case errno is set).

See xcm_finish() for possible errno values.

◆ xcm_await()

int xcm_await ( struct xcm_socket *  socket,
int  condition 
)

Inform socket of which operations the application is waiting to perform.

This function is only used by event-driven application and with XCM sockets in non-blocking mode. For an overview on this subject, see Event-driven Programming Support.

Using xcm_await(), the application informs the XCM socket what conditions it's waiting for (i.e. what XCM operations it wants to perform). These conditions are stored in the socket, and won't change until the application calls xcm_await() again.

The condition parameter is a bitmask, with the valid bits being XCM_SO_RECEIVABLE or XCM_SO_SENDABLE (for connection socket) or XCM_SO_ACCEPTABLE (for server sockets). If no bits are set, the application is not interested in anything beyond the XCM socket to finish any outstanding tasks.

Typically, the application would call xcm_await() when an XCM operation (such as xcm_receive()) has failed with errno set to EAGAIN. However, the application may also call xcm_await() even though neither xcm_send(), xcm_receive(), nor xcm_finish() has failed in such a manner.

In case any of the conditions the application is asking for are believed to be met already at the time of the xcm_await() call, the XCM socket fd (see xcm_fd() for details) will be marked as ready to be read.

The conditions specified by the application are future operation it wishes to perform on a socket (as opposed to finishing operations the socket has already accepted). For example, if an application use xcm_send() to transmit a message, and the XCM socket accept this request (by returning 0 on the call), the application shouldn't send XCM_SO_SENDABLE flag for the reason of having XCM finishing the transmission; the task of actually handing over message to the lower layer is performed by XCM regardless of the conditions specified.

Even though XCM socket fd is marked readable (by select()), and thus the application-specified conditions for a particular connection socket are likely met, there's no guarantee that the API operation (i.e. xcm_send(), xcm_receive() or xcm_accept()) will succeed.

If an application is waiting for both XCM_SO_SENDABLE and XCM_SO_RECEIVABLE, is should try both to send and receive when the socket fd is marked readable.

Parameters
[in]socketThe XCM socket.
[in]conditionThe condition the application is waiting for.
Returns
Returns 0 on success, or -1 if an error occured (in which case errno is set).
errno Description
EINVAL The socket is not in non-blocking mode, or the condition bits are invalid.

◆ xcm_fd()

int xcm_fd ( struct xcm_socket *  socket)

Returns XCM socket fd.

This call retrieves an XCM socket's file descriptor, for an XCM socket in non-blocking mode.

When this fd becomes readable, the XCM socket is ready to make progress.

Progress can mean both progress toward the goal of reaching the application's desired socket condition (see xcm_await() for details), or finishing any outstanding task the XCM socket has.

Note that the XCM socket fd is only ever marked readable (as opposed to writable). This is true even if the application is waiting to send a message on the socket. Marked readable means that the fd is, for example, marked with EPOLLIN, in case epoll_wait() is used, or has its bit set in the readfs fd_set, in case select() is used.

When the XCM socket fd becomes readable, an application would typically perform the actions it specified in xcm_await()'s condition parameter. It is not forced to do so, but may choose to perform other API operations instead. However, if neither xcm_send() nor xcm_receive() is called, the application must call xcm_finish(). The xcm_finish() call must be made, even though the condition parameter was set to zero. This is to allow the socket make progress on its background tasks. See Finishing Outstanding Tasks for details.

The fd is owned by the XCM socket, and must not be closed or otherwise manipulated by the application, other than used in select() (or the equivalent). It is no longer valid, when the corresponding XCM socket is closed.

Parameters
[in]socketThe connection or server socket.
Returns
Returns a fd in the form of a non-negative integer on success, or -1 if an error occured (in which case errno is set).
errno Description
EINVAL The socket is not in non-blocking mode.
See also
xcm_await

◆ xcm_finish()

int xcm_finish ( struct xcm_socket *  socket)

Attempts to finish an ongoing non-blocking background operation.

This call is used by an application having issued xcm_connect() with the XCM_NONBLOCK flag set (or xcm_connect_a() with the "xcm.blocking" attribute set to false), xcm_accept() or xcm_send() call on a connection socket in non-blocking mode, wishing to finish outstanding processing related to that operation, and to know if it succeeded or not.

In addition, xcm_finish() must be called if the conditions on a non-blocking socket are met (as signaled by select() marking the socket fd returned by xcm_fd() as readable), unless the application calls xcm_send(), xcm_receive() or xcm_accept() on that socket. See Finishing Outstanding Tasks for details.

xcm_finish() may be called at any time.

Parameters
[in]socketThe connection or server socket.
Returns
Returns 0 if the connection has been successfully been established, or -1 if it has not (in which case errno is set).

These errno values are possible not only for xcm_finish(), but also for xcm_connect(), xcm_accept(), xcm_send(), and xcm_receive().

errno Description
EPIPE The connection is closed.
EAGAIN The socket is marked non-blocking (with xcm_set_blocking()) and the requested operation would block.
ECONNRESET Connection reset by peer.
ECONNREFUSED No-one is listening on the remote address.
ECONNABORTED A connection has been aborted due to host-internal reasons.
EHOSTUNREACH Remote host is unreachable.
ENETUNREACH Network is unreachable.
ETIMEDOUT No or lost network connectivity.
ENOMEM Insufficient memory (or other resources) to perform operation.
EINTR The operation was interrupted by a UNIX signal.
EPROTO A non-recoverable protocol error occurred.
EMFILE The per-process limit on the number of open file descriptors has been reached.
ENFILE The limit on the total number of open file descriptors has been reached.
EACCES Permission to create the socket was denied.
ENOENT DNS domain name resolution failed.

◆ xcm_set_blocking()

int xcm_set_blocking ( struct xcm_socket *  socket,
bool  should_block 
)

Enabled or disabled non-blocking operation on this socket.

In blocking mode (which is the default), xcm_send() and xcm_receive() calls does not return until a message has been handed over to the system (in case of send), or received from the system (in case of receive), or an error has occured (whichever happens first).

In non-blocking mode, xcm_send() and xcm_receive() will return immediately, regardless if XCM has been enable to fulfill the application's request or not.

Server sockets may also be set into non-blocking mode, in which case xcm_accept() won't block.

Connection sockets created as a result of xcm_connect() may be set into non-blocking mode already from the start, by means of the XCM_NONBLOCK flag to xcm_connect(), in which case also the connection establishment process is non-blocking.

For an overview of the use of non-blocking mode, see Event-driven Programming Support.

To set a non-blocking connection socket into blocking mode, it needs to have finished all outstanding tasks. See Finishing Outstanding Tasks for details.

Setting the "xcm.blocking" attribute is an alternative to using this function. See Generic Attributes.

Parameters
[in]socketThe socket.
[in]should_blockSet to true for blocking operation, false for non-blocking mode.
Returns
Returns 0 on success, or -1 if an error occured (in which case errno is set).
errno Description
EAGAIN The connection socket has unfinished work that needs to completed before mode can be switched.

◆ xcm_is_blocking()

bool xcm_is_blocking ( struct xcm_socket *  socket)

Query whether or not a socket is in non-blocking mode.

For an overview of the use of non-blocking mode, see Event-driven Programming Support.

Reading the "xcm.blocking" attribute is an alternative to using this function. See Generic Attributes.

Parameters
[in]socketThe socket.
Returns
Returns true if the socket is in blocking mode, or false if it is in non-blocking mode.
See also
xcm_set_blocking

◆ xcm_remote_addr()

const char * xcm_remote_addr ( struct xcm_socket *  conn_socket)

Returns the address of the remote endpoint for this connection.

This operation only works for sockets representing connections.

The address returned is in string format, and the pointer returned is to an buffer allocated as a part of the socket state, and need not and should not be free'd by the user.

Reading the "xcm.remote_addr" attribute is an alternative to using this function. See Generic Attributes.

Parameters
[in]conn_socketThe connection socket.
Returns
Returns the remote endpoint address, or NULL if an error occurred (in which case errno is set).

◆ xcm_local_addr()

const char * xcm_local_addr ( struct xcm_socket *  socket)

Returns the address of the local endpoint for this socket.

Just like xcm_remote_addr(), but returns the local endpoint address.

This function applies to both server and connection sockets.

Reading the "xcm.local_addr" attribute is an alternative to using this function. See Generic Attributes.

Parameters
[in]socketA server or connection socket.
Returns
Returns the local endpoint address, or NULL if an error occurred (in which case errno is set).