diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 000000000..e69de29bb diff --git a/api/0.11/annotated.html b/api/0.11/annotated.html new file mode 100644 index 000000000..d5ed74401 --- /dev/null +++ b/api/0.11/annotated.html @@ -0,0 +1,87 @@ + + +
+ + + + +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
Cxcm_addr_host | |
Cxcm_addr_ip |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Files | |
xcm.h | |
This file contains the core Extensible Connection-oriented Messaging (XCM) API. | |
xcm_addr.h | |
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses. | |
xcm_attr.h | |
This file contains the XCM attribute access API. See Socket Attributes for an overview. | |
xcm_attr_types.h | |
This file contains type definitions for the XCM attribute access API. | |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
▼ include | |
xcm.h | This file contains the core Extensible Connection-oriented Messaging (XCM) API |
xcm_addr.h | This is an API for building and parsing Connection-oriented Messaging (XCM) addresses |
xcm_attr.h | This file contains the XCM attribute access API. See Socket Attributes for an overview |
xcm_attr_types.h | This file contains type definitions for the XCM attribute access API |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Macros | |
#define | XCM_VERSION_API_MAJOR 0 |
#define | XCM_VERSION_API_MINOR 22 |
#define | XCM_VERSION_API "0.22" |
#define XCM_VERSION_API_MAJOR 0 | +
The XCM API/ABI major version this library version implements.
+ +#define XCM_VERSION_API_MINOR 22 | +
The XCM API/ABI minor version this library version implements.
+ +#define XCM_VERSION_API "0.22" | +
The complete XCM API version in string format.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Macros | |
#define | XCM_VERSION_MAJOR 1 |
#define | XCM_VERSION_MINOR 7 |
#define | XCM_VERSION_PATCH 0 |
#define | XCM_VERSION "1.7.0" |
#define XCM_VERSION_MAJOR 1 | +
The XCM library major version.
+ +#define XCM_VERSION_MINOR 7 | +
The XCM library minor version.
+ +#define XCM_VERSION_PATCH 0 | +
The XCM library patch version.
+ +#define XCM_VERSION "1.7.0" | +
The complete XCM library version in string format.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This is the documentation for the Extensible Connection-oriented Messaging (XCM) programming APIs.
+XCM consists of of three parts; the core API in xcm.h, an address helper library API in xcm_addr.h, and the attribute access API in xcm_attr.h.
+XCM provides a connection-oriented, reliable messaging service with in-order delivery. The design goal is to allow a straight-off mapping to TCP and TLS, but also allow more efficient transport for local communication.
+XCM reuses much of the terminology (and semantics) of the BSD Sockets API.
+XCM has a client-server model. A server creates a server socket (with xcm_server()) bound to a specific address (in case of TCP or TLS, a TCP port on a particular IP interface), after which clients may initiate connections to the server. On a successful attempt, two connection sockets will be created; one on the server side (returned from xcm_accept()), and one of the client side (returned from xcm_connect()). Thus, a server serving multiple clients will have multiple sockets; one server socket and N connection sockets, one each for every client. A client will have one connection socket for each server it is connected to.
+Messages are always sent and received on a particular connection socket (and never on a server socket).
+In-order delivery - that messages arrive at the receiver in the same order they were sent by the sender side - is guaranteed, but only for messages sent on the same connection.
+XCM transports support flow control. Thus, if the sender message rate or bandwidth is higher than the network or the receiver can handle on a particular connection, xcm_send() in the sender process will eventually block (or return an error EAGAIN, if in non-blocking mode). Unless XCM is used for bulk data transfer (as oppose to signaling traffic), xcm_send() blocking because of slow network or a slow receiver should be rare indeed in practice. TCP, TLS, and UNIX domain socket transports all have large enough windows and socket buffers to allow a very large amount of outstanding data.
+In XCM, the application is in control of which transport will be used, with the address supplied to xcm_connect() and xcm_server() including both the transport name and the transport address.
+However, there is nothing preventing a XCM transport to use a more an abstract addressing format, and internally include multiple "physical" IPC transport options. This model is used by the UTLS Transport.
+Addresses are represented as strings with the following general syntax: @tt <transport-name>:<transport-address> @endtt
+For the UX UNIX Domain Socket transport, the addresses has this more specific form:
+
The addresses of the UXF UNIX Domain Socket transport variant follow the following format:
+
For the TCP, TLS, UTLS and SCTP transports the syntax is:
+
'*' is a shorthand for '0.0.0.0' (=bind to all IPv4 interfaces). '[*]' is the IPv6 equivalent.
+For example:
For TCP, TLS, UTLS and SCTP server socket addresses, the port can be set to 0, in which case XCM (or rather, the Linux kernel) will allocate a free TCP port.
+For transports allowing a DNS domain name as a part of the address, the transport will attempt resoĺv the name to an IP address. A DNS domain name may resolv to zero or more IPv4 addresses and/or zero or more IPv6 addresses. XCM relies on the system's configuration to prioritize between IPv4 and IPv6.
+XCM accepts IPv4 addresses in the dotted-decimal format
XCM allows only complete addresses with three '.', and not the archaic, classful, forms, where some bytes where left out, and thus the address contained fewer separators.
+XCM transports attempts to detect a number of conditions which can lead to lost connectivity, and does so even on idle connections.
+If the remote end closes the connection, the local xcm_receive() will return 0. If the process on the remote end crashed, xcm_receive() will return -1 and set errno ECONNRESET. If network connectivity to the remote end is lost, xcm_receive() will return -1 and errno will be set to ETIMEDOUT.
+In general, XCM follow the UNIX system API tradition when it comes to error handling. Where possible, errors are signaled to the application by using unused parts of the value range of the function return type. For functions returning signed integer types, this means the value of -1 (in case -1 is not a valid return value). For functions returning pointers, NULL is used to signal that an error has occurred. For functions where neither -1 or NULL can be used, or where the function does not return anything (side-effect only functions), an 'int' is used as the return type, and is used purely for the purpose to signal success (value 0), or an error (-1) to the application.
+The actual error code is stored in the thread-local errno variable. The error codes are those from the fixed set of errno values defined by POSIX, found in errno.h. Standard functions such as perror() and strerror() may be used to turn the code into a human-readable string.
+In non-blocking operation, given the fact the actual transmission might be defered (and the message buffered in the XCM layer), and that message receive processing might happen before the application has called receive, the error being signaled at the point of a certain XCM call might not be a direct result of the requested operation, but rather an error discovered previously.
+The documentation for xcm_finish() includes a list of generic error codes, applicable xcm_connect(), xcm_accept(), xcm_send() and xcm_receive().
+Also, for errors resulting in an unusable connection, repeated calls will produce the same errno.
+In UNIX-style event-driven programming, a single application thread handles multiple clients (and thus multiple XCM connection sockets) and the task of accepting new clients on the XCM server socket concurrently (although not in parallel). To wait for events from multiple sources, an I/O multiplexing facility such as select(2) or poll(2) is used.
+XCM supports this programming model. However, due to the extensive user space state/buffering required for some XCM transports, and the weak correlation between fd read/write state and actual XCM-level message send/receive that follows, XCM is forced to deviate from the BSD Sockets semantics in this regard.
+XCM allows the application to use select() and poll() by direct calls, or using any of the many event-loop libraries. For simplicity, being the most well-known of options, select() is used in this documentation to denote the whole family of POSIX I/O multiplexing facilities.
+An event-driven application will set the XCM sockets it handles into non-blocking mode (xcm_set_blocking() or the XCM_NONBLOCK flag to xcm_connect()).
+For XCM sockets in non-blocking mode, all potentially blocking API calls related to XCM connections, calls - xcm_connect(), xcm_accept(), xcm_send(), and xcm_receive() - finish immediately.
+Many such potentially blocking calls will finish immediately and with success. For xcm_send(), xcm_connect() and xcm_accept(), XCM signaling success means that the XCM layer has accepted the request. It may or may not have completed the request.
+In case the XCM_NONBLOCK flag is set in the xcm_connect() call, or in case the a XCM server socket is in non-blocking mode at the time of a xcm_accept() call, the newly created XCM connection returned to the application may be in a semi-operational state, with some internal processing and/or signaling with the remote peer still required before actual message transmission and reception may occur.
+The application may attempt to send or receive messages on such semi-operational connections.
+There are ways for an application wishing to know when connection establishment or the task of accepting a new client have finished to do so. See Finishing Outstanding Tasks for more information.
+To receive a message on a XCM connection socket in non-blocking mode, the application may wait for the right conditions to arise, by means of calling xcm_want() with the XCM_SO_RECEIVABLE flag set. When select() signals that these conditions are true, the application should issue xcm_receive() to attempt to retrieve a message.
+xcm_receive() may also called on speculation, prior to any xcm_want() call, to poll the socket for incoming messages.
+A XCM connection socket may buffer a number of messages, and thus the application should, for optimal performance, repeat xcm_receive() until it returns an error, and errno is set to EAGAIN. However, an application may choose to call xcm_want() with XCM_SO_RECEIVABLE set, but in that case, if there are buffered messages, the xcm_want() call will return 0, signaling that the socket doesn't have to do anything in order for the application to receive a message.
+Similar to receiving a message, an application may use xcm_want() to wait for the right conditions to occur to allow the transmission of a message. Just like with xcm_receive(), it may also choose to issue a xcm_send() call on speculation, falling back to xcm_want() and select() only in the face of XCM being unable to accept a new message. XCM will signal that this is the case by having xcm_send() returning an error with errno to EAGAIN.
+For send operations on non-blocking connection sockets, XCM may buffer whole or part of the message before transmission to the lower layer. This may be due to socket output buffer underrun, or the need for some in-band signaling, like security keys exchange, to happen before the transmission of the complete message may finish. The XCM layer will (re-)attempt to hand the message over to the lower layer at a future call to xcm_finish(), xcm_send(), or xcm_receive().
+An application should never attempt to draw any conclusions directly based the state of the fd or fds used by the XCM socket. The fds may be readable, and yet there may be no message to read from XCM, or it may not be readable, but yet there might be one or several messages buffered in the XCM layer. The same lack of correlation holds true also for xcm_send() and the fd writable/non-writable fd state. In addition, XCM may also used file descriptor for other purposes.
+For applications wishing to know when any outstanding message transmission has finished, it may use xcm_finish() to do so. Normally, applications aren't expected to require this kind of control. Please also not that the fact a message has left the XCM layer doesn't necessarily mean it has successfully been delivered to the recipient.
+xcm_connect(), xcm_accept(), xcm_send() may all leave the connection in a state where work is initiated, but not completed. In addition, the transport may also busy with an internal tasks, such filling its internal buffer with incoming messages, being involved in a key exchange operation (TLS hand shake) or keep alive message transmission or reception.
+Prior to the select() call, the application must query any XCM connection or server socket it has in non-blocking mode, asking it what events it is waiting for, and on what file descriptor. This is true even if the application neither wants to send or receive (on a connection socket), or accept incoming connections (on a server socket).
+The file descriptor, and the type of event, may change if the application issues any xcm_* calls on that connection. Easiest for the application is likely to query the connection socket immediately prior to each and every select() call.
+After waking up from a select() call, where the conditions required by a non-blocking XCM socket are met, the application must, if no xcm_send(), xcm_receive() or xcm_accept() calls are to be made, call xcm_finish(). This is to allow the socket to finish any outstanding tasks, even in the face of an application having no immediate further use of the socket.
+The query is made with xcm_want(), and it returns an array of file descriptors and, for each fd, the event type(s) the socket is interested in for that fd.
+In case the XCM socket has any such needs, the application should wait until the conditions are met (by means of select()). Upon the conditions are met, the application may continue to use the socket.
+Prior to changing a socket from non-blocking to blocking mode, any outstanding tasks must be finished.
+There might be situations that the fd or the fds tied to a XCM connection is marked (by select()) with the appropriate ready status (typically, but not always, write) for a xcm_send() operation to success, but a send may still block (or fail with EAGAIN, if in non-blocking mode). One such may be that the are indeed socket buffer space, but not enough to fit the complete message.
+The same situation may arise for xcm_receive(). Even though the fd tied to a XCM connection is marked with the appropriate ready status for a message to be received, a xcm_receive() may fail, since the complete message has not yet arrived.
+Thus, an application may never trust that a xcm_send() or xcm_receive() in blocking mode won't block, and similarly may never trust a send or receive operation to never fail and return EAGAIN, regardless of fd status.
+See Waiting for Read May Mean Waiting for Write for other reasons that a send or receive may always potentially block.
+XCM is designed to allow transports where all the processing is done in the application's thread of control (i.e. no separate OS threads or processes for a connection to do whatever in-band signaling is required for handling retransmission, dead peer detection, key exchange etc). One transport involving a lot of this kind of processing is the TLS Transport.
+For sockets in blocking mode, this complexity is hidden from the application (except in the form of message reception or transmission latency jitter).
+For event-driven applications, with their XCM connections in non-blocking mode, this has a non-obvious effect; in order to receive a message, the XCM transport may ask the application to have its thread wait (with select()) for the connection's fd to be marked writable. This is because in order to receive the message, the transport may need to complete some in-band signaling. For example, it may require some new keys for encrypting the outgoing message, since the old have expired.
+The other way around may also be true; that in order to write a message, the transport may need to have the application to wait for the fd to become readable (since it needs to receive some signaling message from the remote peer in order to proceed).
+The same holds true also for accept operation on server sockets; in order to accept an incoming request, the transport may ask the application to wait for the fd to be come writable.
+In this example, the application connects and immediately tries to send a message. This may fail (for example, in case TCP and/or TLS-level connection establishement has not yet been completed), in which case the application will fall back and wait with the use of xcm_want() and select().
+In case the application wants to know when the connection establishment has finished, it may use xcm_finish() to do so, like in the below example sequence.
+While connecting to a server socket, the client's connection attempt may be refused immediately.
+In many cases, the application is handed a connection socket before the connection establishment is completed. Any errors occuring during this process is handed over to the application at the next XCM call; would it be xcm_finish(), xcm_send() or xcm_receive().
+In this example, the application runs into a situation where the operation requested may be perfomed immediately (since XCM already have a buffered message).
+In this example the application flushes any internal XCM buffers before shutting down the connection, to ensure that any buffered messages are delivered to the lower layer.
+In this sequence, a server accepts a new connection, and continues to attempt to receive a message on this connection, while still, concurrently, is ready to accept more clients on the server socket.
+Tied to an XCM server or connection socket is a set of read-only key-value pairs known as attributes. Which attributes are available varies across different transports, and different socket types.
+The attribute names are strings, and follows a hierarchical naming schema. For example, all generic XCM attributes, expected to be implemented by all transports, have the prefix "xcm.". Transport-specific attributes are prefixed with the transport or protocol name (e.g. "tcp." for TCP-specific attributes applicable to the TLS and TCP transports).
+The attribute value is coded in the native C data types and byte order. Strings are NUL-terminated, and the NUL character is included in the length of the attribute. There are three value types; a boolean type, a 64-bit signed integer type and a string type. See xcm_attr_types.h for details.
+The attribute access API is in xcm_attr.h.
+Retrieving an integer attribute may look like this (minus error handling):
Process-wide and/or read/write attributes may be supported in the future.
+These attributes are expected to be found on XCM sockets regardless of transport type.
+For TCP transport-specific attributes, see TCP Socket Attributes, and for TLS, see TLS Socket Attributes.
+Attribute Name | Socket Type | Value Type | Description |
---|---|---|---|
xcm.type | All | String | The socket type - "server" or "connection". |
xcm.transport | All | String | The transport type. |
xcm.local_addr | All | String | See xcm_local_addr(). |
xcm.remote_addr | Connection | String | See xcm_remote_addr(). |
xcm.max_msg_size | Connection | Integer | The maximum size of any message transported by this connection. |
XCM has a set of generic message counters, which keeps track of the number of messages crossing a certain boundary for a particular connection, and a sum of their size.
+Some of the message and byte counter attributes use the concept of a "lower layer". What this means depends on the transport. For the UX And TCP transports, it is the Linux kernel. For example, for TCP, if the xcm.to_lower_msgs is incremented, it means that XCM has successfully sent the complete message to the kernel's networking stack for further processing. It does not means it has reached the receiving process. It may have, but it also may be sitting on the local or remote socket buffer, on a NIC queue, or be in-transmit in the network. For TLS, the lower layer is OpenSSL.
+All the "xcm.*_bytes" counters count the length of the XCM message payload (as in the length field in xcm_send()), and thus does not include any underlying headers.
+The message counters only count messages succesfully sent and/or received.
+Attribute Name | Socket Type | Value Type | Description |
---|---|---|---|
xcm.from_app_msgs | Connection | Integer | Messages sent from the application and accepted into XCM. |
xcm.from_app_bytes | Connection | Integer | The sum of the size of all messages counted by xcm.from_app_msgs. |
xcm.to_app_msgs | Connection | Integer | Messages delivered from XCM to the application. |
xcm.to_app_bytes | Connection | Integer | The sum of the size of all messages counter by xcm.to_app_msgs. |
xcm.from_lower_msgs | Connection | Integer | Messages received by XCM from the lower layer. |
xcm.from_lower_bytes | Connection | Integer | The sum of the size of all messages counted by xcm.from_lower_msgs. |
xcm.to_lower_msgs | Connection | Integer | Messages successfully sent by XCM into the lower layer. |
xcm.to_lower_bytes | Connection | Integer | The sum of the size of all messages counted by xcm.to_lower_msgs. |
XCM includes a control interface, which allows iteration over the OS instance's XCM server and connection sockets (for processes with the appropriate permissions), and access to their attributes (see Socket Attributes).
+The control interface is optional by means of build-time configuration.
+For each XCM server or connection socket, there is a corresponding UNIX domain socket which is used for control signaling (i.e. state retrieval).
+By default, the control interface's UNIX domain sockets are stored in the /run/xcm/ctl
directory.
This directory needs to be created prior to running any XCM applications (for the control interface to worker properly) and should be writable for all XCM users.
+A particular process using XCM may be configured to use a non-default directory for storing the UNIX domain sockets used for the control interface by means of setting the XCM_CTL
variable. Please note that using this setting will cause the XCM connections to be not visible globally on the OS instance (unless all other XCM-using processes also are using this non-default directory).
The XCM socket state the control interface allows access to (i.e. the attributes) is owned by the various processes is the system using the XCM library. Thus, to avoid synchronization issues, the control interface is driven by the application's thread(s), although the application is kept unaware of this fact.
+If the control interface is enabled, some of the file descriptors returned to the application (in xcm_want()) will are not tied to the data interface (i.e. xcm.h and the messaging I/O), but rather the control interface.
+The control interface is using one file descriptor for the a UNIX domain server socket, and zero or more fds for any control interface clients attached.
+Generally, since the application is left unaware (from an API perspective) from the existence of the control interface, errors are not reported up to the application. They are however logged.
+Application threads owning XCM sockets, but which are busy with non-XCM processing for a long duration of time, or otherwise are leaving their XCM sockets unattended to (in violation of XCM API contract), will not respond on the control interface's UNIX domain sockets (corresponding to their XCM sockets). Only the prescence of these sockets may be detected, but their state cannot be retrieved.
+Internally, the XCM implementation has control interface client library, but this library's API is not public at this point.
+XCM includes a command-line program xcmctl
which uses the Control API to iterate of the system's current XCM sockets, and allow access (primarily for debugging purposes) to the sockets' attributes.
Unlike BSD sockets, a XCM socket may not be shared among different threads without synchronization external to XCM. With proper external serialization, a socket may be shared by different threads in the same process, although it might provide difficult in practice since a thread in a blocking XCM function will continue to hold the lock, and thus preventing other threads from accessing the socket at all. For non-blocking sockets, the contract of xcm_want() may be broken in so far the conditions on which a thread is waiting for may be change, if another thread calls into that connection socket.
+It is however safe to "give away" a XCM socket from one thread to another, provided the appropriate memory fences are used.
+These limitations (compared to BSD Sockets) are in place to allow socket state outside the kernel (which is required for TCP framing and TLS).
+Sharing a XCM socket between threads in different processes is not possible.
+After a fork() call, either of the two process (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 not call any other XCM API call than xcm_cleanup(), which frees local memory tied to this socket in the non-owner's process address space, without impacting the connection state in the owner process.
+The core XCM API functions are oblivious to the transports used. However, the support for building, and parsing addresses (which some applications are expected to do) are available only for a set of pre-defined set of transports. There is nothing preventing xcm_addr.h from being extended, and also nothing prevents an alternative XCM implementation to include more transports without touching the address helper API.
+The UX transport uses UNIX Domain (AF_UNIX, also known as AF_LOCAL) Sockets.
+UX sockets may only be used with the same OS instance (or, more specifically, between processes in the same Linux kernel network namespace).
+UNIX Domain Sockets comes in a number of flavors, and XCM uses the SOCK_SEQPACKET variety. SOCK_SEQPACKET sockets are connection-oriented, preserves message boundaries and delivers messages in the same order they were sent; perfectly matching XCM semantics and provides for an near-trivial mapping.
+UX is the most efficient of the XCM transports.
+The standard UNIX Domain Sockets as defined by POSIX uses the file system as its namespace, with the sockets also being files. However, for simplicity and to avoid situations where stale socket files (originating from crashed processes) causing problems, the UX transport uses a Linux-specific extension, allowing a private UNIX Domain Socket namespace. This is known as the abstract namespace (see the unix(7) man page for details). With the abstract namespace, server socket address allocation has the same life time as TCP ports (i.e. if the process dies, the address is free'd).
+The UX transport enables the SO_PASSCRED BSD socket option, to give the remote peer a name (which UNIX domain connection socket doesn't have by default). This is for debugging and observability purposes. Without a remote peer name, in server processes with multiple incoming connections to the same server socket, it's difficult to say which of the server-side connection sockets goes to which remote peer. The kernel-generated, unique, name is an integer in the form "%05x" (printf format). Applications using hardcoded UX addresses should avoid such names by, for example, using a prefix.
+The UTLS Transport also indirectly uses the UX namespace, so care should be taken to avoid any clashes between UX and UTLS sockets in the same network namespace.
+The UXF transport is identical to the UX transport, only it uses the standard POSIX naming mechanism. The name of a server socket is a file system path, and the socket is also a file.
+The UXF sockets resides in a file system namespace, as opposed to UX sockets, which live in a network namespace.
+Upon xcm_close(), the socket will be closed and the file removed. If an application crashes or otherwise fails to run xcm_close(), it will leave a file in the file system pointing toward a non-existing socket. This file will prevent the creation another server socket with the same name.
+The TCP transport uses the Transmission Control Protocol (TCP), by means of the BSD Sockets API.
+TCP is a byte-stream service, but the XCM TCP transport adds framing on top of the stream. A single-field 32-bit header containing the message length in network byte order is added to every message.
+TCP uses TCP Keepalive to detect lost network connectivity between the peers.
+The TCP transport supports IPv4 and IPv6.
+Since XCM is designed for signaling traffic, the TCP transport disables the Nagle algorithm of TCP to avoid its excessive latency.
+The TCP attributes are retrieved from the kernel (struct tcp_info in linux/tcp.h). See the tcp(7) manual page, and its section on the TCP_INFO socket option.
+Attribute Name | Socket Type | Value Type | Description |
---|---|---|---|
tcp.rtt | Connection | Integer | The current TCP round-trip estimate (in us). |
tcp.total_retrans | Connection | Integer | The total number of retransmitted TCP segments. |
tcp.segs_in | Connection | Integer | The total number of segments received. |
tcp.segs_out | Connection | Integer | The total number of segments sent. |
tcp.segs_in
and tcp.segs_out
are only present when running XCM on Linux kernel 4.2 or later.The TLS transport uses TLS to provide a secure, private, two-way authenticated transport.
+TLS is a byte-stream service, but the XCM TLS transport adds framing in the same manner as does the XCM TCP transport.
+The TLS transport supports IPv4 and IPv6.
+The TLS transport disables the Nagle algorithm of TCP.
+The TLS transport expect the certificate, trust chain and private key files to be found in a file system directory - the certificate directory. The default path are configured at build-time, but can be overriden on a per-process basis by means of a UNIX environment variable. Prior to creating any TLS or UTLS sockets (typically before program start), set XCM_TLS_CERT
to change the certificate directory.
The TLS transport will, at the time of XCM socket creation (xcm_connect() or xcm_server()), look up the process' current network namespace. In case the namespace is given a name per the iproute2 methods and conventions, XCM will retrieve this name and use it in the certificate and key lookup.
+In the certificate directory, the TLS transport expects the certificate to follow the below naming convention (where <ns> is the namespace):
The private key is stored in:
The trust chain is stored in:
For the default namespace (or any other network namespace not named according to iproute2 standards), the certificate need to be stored in a file "cert.pem", the private key in "key.pem" and the trust chain in "tc.pem".
+In case the certificate, key or trust chain files are not in place (for a particular namespace), a xcm_server() call will return an error and set errno to EPROTO. The application may choose to retry at a later time.
+TLS has all the TCP-level attributes of the TCP transport; see TCP Socket Attributes.
+The UTLS transport provides a hybrid transport, utilizing both the TLS and UX transports internally for actual connection establishment and message delivery.
+On the client side, at the time of xcm_connect(), the UTLS transport determines if the server socket can be reached by using the UX transport (i.e. if the server socket is located on the same OS instance, in the same network namespace). If not, UTLS will attempt to reach the server by means of the TLS transport.
+For a particular UTLS connection, either TLS or UX is used (never both). XCM connections to a particular UTLS server socket may be a mix of the two different types.
+In the UTLS transport, xcm_want() will return at least two file descriptors; one for the TCP BSD socket file descriptor utilized for TLS, and one for the UNIX domain socket. However, the applications should not depend on this (or the fact that other transports might return fewer).
+For an UTLS server socket with the address @tt utls:<ip>:<port> @endtt, two underlying addresses will be allocated; @tt tls:<ip>:<port> @endtt and @tt ux:<ip>:<port> @endtt .
+Or, in the case DNS is used: @tt tls:<hostname>:<port> @endtt and @tt ux:<hostname>:<port> @endtt .
+A wildcard should never be used when creating a UTLS server socket.
+If a DNS hostname is used in place of the IP address, both the client and server need employ DNS, and also agree upon which hostname to use (in case there are several pointing at the same IP address).
+Failure to adhere to the above two rules will prevent a client from finding a local server. Such a client will instead establish a TLS connection to the server.
+The SCTP transport uses the Stream Control Transmission Protocol (SCTP). SCTP provides a reliable, message-oriented service. In-order delivery is optional, and to adhere to XCM semantics (and for other reasons) XCM leaves SCTP in-order delivery enabled.
+The SCTP transport utilizes the native Linux kernel's implementation of SCTP, via the BSD Socket API. The operating mode is such that there is a 1:1-mapping between an association and a socket (fd).
+The SCTP transport supports IPv4 and IPv6.
+To minimize latency, the SCTP transport disables the Nagle algorithm.
+Namespaces is a Linux kernel facility concept for creating multiple, independent namespaces for kernel resources of a certain kind.
+Linux Network Namespaces will affect all transports, including the UX transport.
+XCM has no explicit namespace support, but the application is rather expected to use the Linux kernel facilities for this functionality (i.e. switch to the right namespace before xcm_server() och xcm_connect()).
+In case the system follows the iproute2 conventions in regards to network namespace naming, the TLS and UTLS transports support per-network namespace TLS certificates and private keys.
+XCM, in its current form, does not support binding to a local socket before doing connect() - something that is possible with BSD Sockets, but very rarely makes sense.
+XCM also doesn't have a sendmmsg() or recvmmsg() equivalent. Those could easily be added, and would provide some major performance improvements for applications that are sending or receiving multiple messages on the same connection on the same time. *mmsg() equivalents have been left out because there are strong doubts there are such applications.
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
#include <xcm_addr.h>
+Data Fields | ||
enum xcm_addr_type | type | |
union { | ||
+ struct xcm_addr_ip ip | ||
+ char name [254] | ||
}; | ||
Hostname or IPv4/IPv6 address data type.
+enum xcm_addr_type xcm_addr_host::type | +
Type tag
+ +union { ... } xcm_addr_host | +
Union containing the actual hostname, IPv4 or IPv6 address bytes
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
#include <xcm_addr.h>
+Data Fields | ||
sa_family_t | family | |
union { | ||
in_addr_t ip4 | ||
uint8_t ip6 [16] | ||
} | addr | |
IPv4 or IPv6 address data type.
+sa_family_t xcm_addr_ip::family | +
Type tag; AF_INET or AF_INET6
+ +in_addr_t xcm_addr_ip::ip4 | +
Contains the IPv4 address in network byte order (in case family is set to AF_INET).
+ +uint8_t xcm_addr_ip::ip6[16] | +
Contains the IPv6 address (in case family is set to AF_INET6).
+ +union { ... } xcm_addr_ip::addr | +
Union containing the actual IPv4 or a IPv6 address bytes
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
Library Version | |
API Version |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the core Extensible Connection-oriented Messaging (XCM) API. +More...
+#include <errno.h>
#include <stdbool.h>
#include <sys/types.h>
Go to the source code of this file.
++Macros | |
#define | XCM_NONBLOCK (1<<0) |
#define | XCM_FD_READABLE (1<<0) |
#define | XCM_FD_WRITABLE (1<<1) |
#define | XCM_FD_EXCEPTION (1<<2) |
#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_server (const char *local_addr) |
int | xcm_close (struct xcm_socket *socket) |
void | xcm_cleanup (struct xcm_socket *socket) |
struct xcm_socket * | xcm_accept (struct xcm_socket *server_socket) |
int | xcm_send (struct xcm_socket *conn_socket, const void *buf, size_t len) |
int | xcm_receive (struct xcm_socket *conn_socket, void *buf, size_t capacity) |
int | xcm_want (struct xcm_socket *socket, int condition, int *fds, int *events, size_t capacity) |
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) |
This file contains the core Extensible Connection-oriented Messaging (XCM) API.
+#define XCM_NONBLOCK (1<<0) | +
Flag used in xcm_connect()
+ +#define XCM_FD_READABLE (1<<0) | +
Flag bit denoting a readable fd event in xcm_want().
+ +#define XCM_FD_WRITABLE (1<<1) | +
Flag bit denoting a writable fd event.
+ +#define XCM_FD_EXCEPTION (1<<2) | +
Flag bit denoting a exception fd event.
+ +#define XCM_SO_RECEIVABLE (1<<0) | +
Flag bit denoting a socket where the application likely can receive a message.
+ +#define XCM_SO_SENDABLE (1<<1) | +
Flag bit denoting a socket where the application likely can send a message.
+ +#define XCM_SO_ACCEPTABLE (1<<2) | +
Flag bit denoting a socket with a pending incoming connection.
+ +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_want() to retrieve the needed information to be able to wait 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).
+[in] | remote_addr | The remote address which to connect. |
[in] | flags | Either 0, or XCM_NONBLOCK for a non-blocking connect. |
errno | Description |
---|---|
EINVAL | Invalid address format. |
ENOPROTOOPT | Transport protocol not available. |
EMFILE | The limit on the total number of open fds has been reached. |
ENOENT | DNS domain name resolution failed. |
See xcm_finish() for other possible errno values.
+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), a xcm_server() call also includes a blocking name resolution (e.g. gethostbyname()).
+[in] | local_addr | The local address to which this socket should be bound. |
errno | Description |
---|---|
EACCESS | Permission to create the socket is denied. |
EADDRINUSE | Local socket address is already in use. |
ENOMEM | Insufficient memory. |
EINVAL | Invalid address format. |
ENOPROTOOPT | Transport protocol not available. |
EMFILE | The limit on the total number of open fds has been reached. |
EPROTO | A protocol error occured. |
ENOENT | DNS domain name resolution failed. |
int xcm_close | +( | +struct xcm_socket * | +socket | ) | ++ |
Close an endpoint.
+This function close a 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.
+[in] | socket | The socket to be closed, or NULL (in case xcm_close() is a no-operation). |
void xcm_cleanup | +( | +struct xcm_socket * | +socket | ) | ++ |
Cleans up any local resources tied to a 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().
+[in] | socket | The socket which local resources are to be freed, or NULL (in case xcm_cleanup() is a no-operation). |
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.
+[in] | server_socket | The server socket on which to attempt to accept one pending connection. |
errno | Description |
---|---|
EMFILE | The limit on the total number of open fds has been reached. |
See xcm_finish() for other possible errno values.
+ +int xcm_send | +( | +struct xcm_socket * | +conn_socket, | +
+ | + | const void * | +buf, | +
+ | + | size_t | +len | +
+ | ) | ++ |
Send message on a particular connection.
+The xcm_send() function is used to send a message out on a connection socket. A XCM connection goes from a client to a server, and this connection socket may represent either one of the two endpoints.
+[in] | conn_socket | The connection socket the message will be sent on. |
[in] | buf | A pointer to the message data buffer. |
[in] | len | The length of the message in bytes. Zero-length messages are not allowed. |
errno | Description |
---|---|
EMSGSIZE | Message is too large. See also Generic Attributes. |
See xcm_finish() for more errno values.
+ +int xcm_receive | +( | +struct xcm_socket * | +conn_socket, | +
+ | + | void * | +buf, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Receive message on a particular connection.
+The xcm_receive() function is used to receive message on a connection socket. A XCM connection goes from a client to a server, and this connection socket may represent either one of the two endpoints.
+If 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).
+[in] | conn_socket | The connection socket the message will receive be on. |
[out] | buf | The user-supplied buffer where the incoming message will be stored. |
[in] | capacity | The capacity in bytes of the buffer. |
See xcm_finish() for possible errno values.
+ +int xcm_want | +( | +struct xcm_socket * | +socket, | +
+ | + | int | +condition, | +
+ | + | int * | +fds, | +
+ | + | int * | +events, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Query the socket what events on which file descriptors it's waiting for.
+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.
+With xcm_want(), the application will inform the XCM socket what condition it's waiting for (i.e. what XCM operation it wants to perform), and in return the XCM socket will provide a set of file descriptors and, for each fd, information on what type of event on that fd it require to make progress. Progress can mean both progress toward the goal of reaching the application's desired socket condition, or finishing any outstanding task the XCM socket has.
+In case any of the conditions the application is asking for are believed to be already met, the xcm_want() call will return 0.
+In case the XCM socket has no outstanding tasks, and the application is not asking for any operation that the XCM socket believes it can't immediate fulfill, the call will return 0.
+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.
+Note that XCM may ask the application to wait for the connection's fd or fds to become writable, even if the application is waiting to receive a message. It may also ask the application to wait for the connection's fd to become readable, even if the application is attemting to send a messaging. For the quirks of xcm_want(), see Waiting for Read May Mean Waiting for Write.
+Even though the conditions for a particular connection socket are met (fd is becoming writable, for example), there's no guarantee that the xcm_send() or xcm_receive() won't block (or in case of non-blocking mode, won't fail and set EAGAIN).
+The XCM socket fds may only be used with select(). Supplying this fd to any other OS calls (such as setsockopt(2), read(2) etc) is prohibited.
+The information received on which fd to use, and what events on that fd are relevant for the connection socket in its current state, are only valid until more xcm_* calls are made on this socket. See Finishing Outstanding Tasks for more information.
+The fd is an positive integer, unique within this process.
+The condition parameter is a bitmask, with the bits being XCM_SO_RECEIVABLE, XCM_SO_SENDABLE, and/or XCM_SO_ACCEPTABLE. If no bits are set, the application is not interested in anything beyond this XCM socket to finish any outstanding task.
+Each element in the events array is an int used as a bitmask. The bitmask at position N in the events array represents the file descriptor events the XCM transport is waiting for, for fd at position N in the fds array. The bits are XCM_FD_READABLE, XCM_FD_WRITABLE and/or XCM_FD_EXCEPTION. At least one bit is always set.
+If a socket is waiting for multiple events (for example, both readable and writable on the same fd, or readable on one fd, and writeable on another), the condition is met whenever any of the events occur (as oppose to all events).
+[in] | socket | The XCM socket. |
[in] | condition | The condition the application is waiting for. |
[out] | fds | An user-supplied array to store the fds. |
[out] | events | An user-supplied array of int to store the bitmask of each of the fds in the fds array. |
[in] | capacity | The length of the fds and events arrays. |
errno | Description |
---|---|
EOVERFLOW | The user-supplied buffer was too small to fit the socket's fds. |
EINVAL | The socket is not in blocking mode, or the condition bits are invalid. |
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, xcm_accept() or xcm_send() call on a connection socket in non-blocking mode, wishing to finish outstanding processing related to that operation, to know if it succeeded or not.
+In addition, xcm_finish() must be called if the conditions set by xcm_want() are met (as signaled by select(), 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.
+[in] | socket | The connection or server socket. |
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. |
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.
+[in] | socket | The socket. |
[in] | should_block | Set to true for blocking operation, false for non-blocking mode. |
errno | Description |
---|---|
EAGAIN | The connection socket has unfinished work that needs to completed before mode can be switched. |
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.
+[in] | socket | The socket. |
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.
+[in] | conn_socket | The connection socket. |
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.
+[in] | socket | A server or connection socket. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses. +More...
+#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <errno.h>
#include <xcm_addr_compat.h>
Go to the source code of this file.
++Data Structures | |
struct | xcm_addr_ip |
struct | xcm_addr_host |
+Macros | |
#define | XCM_UTLS_PROTO "utls" |
#define | XCM_TLS_PROTO "tls" |
#define | XCM_TCP_PROTO "tcp" |
#define | XCM_SCTP_PROTO "sctp" |
#define | XCM_UX_PROTO "ux" |
#define | XCM_UXF_PROTO "uxf" |
+Enumerations | |
enum | xcm_addr_type { xcm_addr_type_name +, xcm_addr_type_ip + } |
+Functions | |
int | xcm_addr_parse_proto (const char *addr_s, char *proto, size_t capacity) |
int | xcm_addr_parse_utls (const char *utls_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_tls (const char *tls_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_tcp (const char *tcp_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_sctp (const char *sctp_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_ux (const char *ux_addr_s, char *ux_path, size_t capacity) |
int | xcm_addr_parse_uxf (const char *uxf_addr_s, char *uxf_path, size_t capacity) |
int | xcm_addr_make_utls (const struct xcm_addr_host *host, unsigned short port, char *utls_addr_s, size_t capacity) |
int | xcm_addr_make_tls (const struct xcm_addr_host *host, unsigned short port, char *tls_addr_s, size_t capacity) |
int | xcm_addr_make_tcp (const struct xcm_addr_host *host, unsigned short port, char *tcp_addr_s, size_t capacity) |
int | xcm_addr_make_sctp (const struct xcm_addr_host *host, unsigned short port, char *sctp_addr_s, size_t capacity) |
int | xcm_addr_make_ux (const char *ux_name, char *ux_addr_s, size_t capacity) |
int | xcm_addr_make_uxf (const char *uxf_name, char *uxf_addr_s, size_t capacity) |
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses.
+#define XCM_UTLS_PROTO "utls" | +
Protocol string for the combined TLS+UX transport.
+ +#define XCM_TLS_PROTO "tls" | +
Protocol string for the Transport Layer Security (TLS) transport.
+ +#define XCM_TCP_PROTO "tcp" | +
Protocol string for the TCP transport.
+ +#define XCM_SCTP_PROTO "sctp" | +
Protocol string for the SCTP transport.
+ +#define XCM_UX_PROTO "ux" | +
Protocol string for the UNIX Domain socket (AF_UNIX SEQPACKET) transport (using the abstract namespace).
+ +#define XCM_UXF_PROTO "uxf" | +
Protocol string for the UNIX Domain socket (AF_UNIX SEQPACKET) transport (using file system-based naming).
+ +int xcm_addr_parse_proto | +( | +const char * | +addr_s, | +
+ | + | char * | +proto, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses the protocol part of a XCM address.
+[in] | addr_s | The XCM address string. |
[out] | proto | The buffer where to store the protocol part of the address. |
[in] | capacity | The buffer length in bytes. |
errno | Description |
---|---|
EINVAL | Malformed address. |
ENAMETOOLONG | The user-supplied buffer is too small to fit the protocol. |
int xcm_addr_parse_utls | +( | +const char * | +utls_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a UTLS XCM address.
+[in] | utls_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TLS port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_tls | +( | +const char * | +tls_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a TLS XCM address.
+[in] | tls_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TLS port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_tcp | +( | +const char * | +tcp_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a TCP XCM address.
+[in] | tcp_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TCP port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_sctp | +( | +const char * | +sctp_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parse a SCTP XCM address.
+[in] | sctp_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The SCTP port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_ux | +( | +const char * | +ux_addr_s, | +
+ | + | char * | +ux_path, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses an UX (UNIX Domain Socket) XCM address.
+[in] | ux_addr_s | The string to sparse. |
[out] | ux_path | The UNIX (NUL-terminated) abstract name portion of the UX address. |
[in] | capacity | The length of the user-supplied path buffer. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_uxf | +( | +const char * | +uxf_addr_s, | +
+ | + | char * | +uxf_path, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses an UXF (UNIX Domain Socket) XCM address.
+[in] | uxf_addr_s | The string to sparse. |
[out] | uxf_path | The UNIX (NUL-terminated) path name portion of the UXF address. |
[in] | capacity | The length of the user-supplied path buffer. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_make_utls | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +utls_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a UTLS XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | utls_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_tls | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +tls_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a TLS XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | tls_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_tcp | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +tcp_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a TCP XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | tcp_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_sctp | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +sctp_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a SCTP XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | sctp_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_ux | +( | +const char * | +ux_name, | +
+ | + | char * | +ux_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds an UX XCM address string from the supplied UNIX Domain Socket name.
+[in] | ux_name | The UNIX Domain Socket name. |
[out] | ux_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid format of or too long UNIX Domain Socket address. |
int xcm_addr_make_uxf | +( | +const char * | +uxf_name, | +
+ | + | char * | +uxf_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds an UXF XCM address string from the supplied file system path.
+[in] | uxf_name | The UNIX Domain path. |
[out] | uxf_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid format of or too long UNIX Domain Socket address. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the XCM attribute access API. See Socket Attributes for an overview. +More...
+ +Go to the source code of this file.
++Typedefs | |
typedef void(* | xcm_attr_cb) (const char *attr_name, enum xcm_attr_type type, void *value, size_t value_len, void *cb_data) |
+Functions | |
int | xcm_attr_get (struct xcm_socket *socket, const char *name, enum xcm_attr_type *type, void *value, size_t capacity) |
void | xcm_attr_get_all (struct xcm_socket *socket, xcm_attr_cb cb, void *cb_data) |
This file contains the XCM attribute access API. See Socket Attributes for an overview.
+typedef void(* xcm_attr_cb) (const char *attr_name, enum xcm_attr_type type, void *value, size_t value_len, void *cb_data) | +
The signature of the user-supplied callback used in xcm_attr_get_all().
+ +int xcm_attr_get | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | enum xcm_attr_type * | +type, | +
+ | + | void * | +value, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Retrieves the value of a XCM socket attribute.
+For a list of available attributes for different socket and transport types, see Generic Attributes, TCP Socket Attributes and TLS Socket Attributes.
+For a description of the C types and buffer capacity requirements of the attribute types, see xcm_attr_types.h.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[out] | type | A pointer to a location where the type of the attribute will be stored. May be left to NULL, in case the type is known a priori. |
[out] | value | A user-supplied buffer where the value of the attribute will be stored. |
[in] | capacity | The length of the buffer (in bytes). |
errno | Description |
---|---|
ENOENT | The attribute does not exist. |
EOVERFLOW | The user-supplied buffer was too small to fit the value. |
void xcm_attr_get_all | +( | +struct xcm_socket * | +socket, | +
+ | + | xcm_attr_cb | +cb, | +
+ | + | void * | +cb_data | +
+ | ) | ++ |
Retrieves all XCM socket attributes.
+This function retrieves all available attribute names, types and their current values on a particular connection or server socket.
+The memory locations refered to by the attr_name and attr_value pointers is only guaranteed to be valid for the execution of the callback. If needed later, they need to be copied.
+[in] | socket | The connection or server socket. |
[in] | cb | The function to be called for every attribute on the socket. |
[in] | cb_data | An opaque (for XCM) pointer returned back to the application in the callback. cb_data may be NULL. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the XCM attribute map API. +More...
+ +Go to the source code of this file.
++Typedefs | |
typedef void(* | xcm_attr_map_foreach_cb) (const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len, void *user) |
+Functions | |
struct xcm_attr_map * | xcm_attr_map_create (void) |
struct xcm_attr_map * | xcm_attr_map_clone (const struct xcm_attr_map *original) |
void | xcm_attr_map_add (struct xcm_attr_map *attr_map, const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len) |
void | xcm_attr_map_add_bool (struct xcm_attr_map *attr_map, const char *attr_name, bool attr_value) |
void | xcm_attr_map_add_int64 (struct xcm_attr_map *attr_map, const char *attr_name, int64_t attr_value) |
void | xcm_attr_map_add_str (struct xcm_attr_map *attr_map, const char *attr_name, const char *attr_value) |
const void * | xcm_attr_map_get (const struct xcm_attr_map *attr_map, const char *attr_name, enum xcm_attr_type *attr_type, size_t *attr_value_len) |
const bool * | xcm_attr_map_get_bool (const struct xcm_attr_map *attr_map, const char *attr_name) |
const int64_t * | xcm_attr_map_get_int64 (const struct xcm_attr_map *attr_map, const char *attr_name) |
const char * | xcm_attr_map_get_str (const struct xcm_attr_map *attr_map, const char *attr_name) |
bool | xcm_attr_map_exists (const struct xcm_attr_map *attr_map, const char *attr_name) |
void | xcm_attr_map_del (struct xcm_attr_map *attr_map, const char *attr_name) |
size_t | xcm_attr_map_size (const struct xcm_attr_map *attr_map) |
void | xcm_attr_map_foreach (const struct xcm_attr_map *attr_map, xcm_attr_map_foreach_cb cb, void *user) |
bool | xcm_attr_map_equal (const struct xcm_attr_map *attr_map_a, const struct xcm_attr_map *attr_map_b) |
void | xcm_attr_map_destroy (struct xcm_attr_map *attr_map) |
This file contains the XCM attribute map API.
+A XCM attribute map is a set of key-value pairs. The key is an attribute name in the form of a string. One key maps to at most one value. The attribute value is either a boolean, a signed 64-bit integer, a string, or a variable-length binary object.
+typedef void(* xcm_attr_map_foreach_cb) (const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len, void *user) | +
Callback function prototype used for iteration.
+ +struct xcm_attr_map * xcm_attr_map_create | +( | +void | +) | ++ |
Create an attribute map instance.
+struct xcm_attr_map * xcm_attr_map_clone | +( | +const struct xcm_attr_map * | +original | ) | ++ |
Create a copy of an attribute map instance.
+[in] | attr_map | The original attribute map instance, to be copied. |
void xcm_attr_map_add | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | enum xcm_attr_type | +attr_type, | +
+ | + | const void * | +attr_value, | +
+ | + | size_t | +attr_value_len | +
+ | ) | ++ |
Associate a key with a value.
+This function associates the attribute key attr_name
to the attribute value attr_value
in the attribute map attr_map
. If the key attr_name
already exists, its value is replaced.
Both the key and the value will be copied, and thus attr_name
and attr_value
will still be owned by the caller at call completion.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_type | The type of the value to be added. |
[in] | attr_value | The value of the attribute to be added. |
[in] | attr_value_len | The length (in bytes) of the value. |
void xcm_attr_map_add_bool | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | bool | +attr_value | +
+ | ) | ++ |
Associate a key with a boolean value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The boolean value of the attribute to be added. |
void xcm_attr_map_add_int64 | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | int64_t | +attr_value | +
+ | ) | ++ |
Associate a key with a 64-bit signed integer value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The integer value of the attribute to be added. |
void xcm_attr_map_add_str | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | const char * | +attr_value | +
+ | ) | ++ |
Associate a key with a string value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The string value of the attribute to be added. |
const void * xcm_attr_map_get | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | enum xcm_attr_type * | +attr_type, | +
+ | + | size_t * | +attr_value_len | +
+ | ) | ++ |
Retrieve the value associated with a particular key.
+This function retrieves the attribute value, value type and value length of the attribute attr_name
, in case it exists.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
[out] | attr_type | A pointer to a buffer where the value type will be stored, or NULL. |
[out] | attr_value_len | A pointer to a buffer where the length (in bytes) of the value will be stored, or NULL. |
const bool * xcm_attr_map_get_bool | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the boolean value associated with a particular key.
+This function retrieves the boolean attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_bool.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
const int64_t * xcm_attr_map_get_int64 | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the integer value associated with a particular key.
+This function retrieves the 64-bit signed integer attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_int64.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
const char * xcm_attr_map_get_str | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the string value associated with a particular key.
+This function retrieves the NUL-terminated string attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_str.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
bool xcm_attr_map_exists | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Check if an attribute named attr_name
exists in the attribute map.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute. |
void xcm_attr_map_del | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Removes an attribute from the attribute map.
+This function deletes the attribute attr_name
, in case it exists.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be deleted. |
size_t xcm_attr_map_size | +( | +const struct xcm_attr_map * | +attr_map | ) | ++ |
Returns the number of attributes in the attribute map.
+[in] | attr_map | The attribute map instance. |
attr_map
. void xcm_attr_map_foreach | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | xcm_attr_map_foreach_cb | +cb, | +
+ | + | void * | +user | +
+ | ) | ++ |
Iterates over all attributes in a map.
+This function calls the supplied callback function cb
for each attribute in attr_map
.
The map may not be modified during iteration.
+[in] | attr_map | The attribute map instance. |
[in] | cb | The callback function. |
[in] | user | An opaque pointer, supplied back to the application in every cb call. |
bool xcm_attr_map_equal | +( | +const struct xcm_attr_map * | +attr_map_a, | +
+ | + | const struct xcm_attr_map * | +attr_map_b | +
+ | ) | ++ |
Compares two attribute maps for equality (by value).
+[in] | attr_map_a | An attribute map instance. |
[in] | attr_map_b | An attribute map instance. |
attr_map_a
and attr_map_a
are equal, false otherwise. void xcm_attr_map_destroy | +( | +struct xcm_attr_map * | +attr_map | ) | ++ |
Destroys an attribute map instance.
+This function destroys the attribute map instance and frees all the resources associated with it.
+[in] | attr_map | The attribute map instance, or NULL. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains type definitions for the XCM attribute access API. +More...
+ +Go to the source code of this file.
++Enumerations | |
enum | xcm_attr_type { xcm_attr_type_bool = 1 +, xcm_attr_type_int64 = 2 +, xcm_attr_type_str = 3 + } |
This file contains type definitions for the XCM attribute access API.
+enum xcm_attr_type | +
Enumeration representing the different attribute value types.
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains obsolete parts of the XCM core API. +More...
+ +Go to the source code of this file.
++Macros | |
#define | XCM_FD_READABLE (1<<0) |
#define | XCM_FD_WRITABLE (1<<1) |
#define | XCM_FD_EXCEPTION (1<<2) |
+Functions | |
int | xcm_want (struct xcm_socket *socket, int condition, int *fds, int *events, size_t capacity) |
This file contains obsolete parts of the XCM core API.
+It should not be included directly, but rather only via <xcm.h>.
+#define XCM_FD_READABLE (1<<0) | +
Flag bit denoting a readable fd event in xcm_want().
+ +#define XCM_FD_WRITABLE (1<<1) | +
Flag bit denoting a writable fd event.
+ +#define XCM_FD_EXCEPTION (1<<2) | +
Flag bit denoting a exception fd event.
+ +int xcm_want | +( | +struct xcm_socket * | +socket, | +
+ | + | int | +condition, | +
+ | + | int * | +fds, | +
+ | + | int * | +events, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Query the socket what events on which file descriptors it's waiting for.
+Please note: this function is obsolete, replaced by xcm_fd() and xcm_await().
+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.
+With xcm_want(), the application will inform the XCM socket what condition it's waiting for (i.e. what XCM operation it wants to perform), and in return the XCM socket will provide a set of file descriptors and, for each fd, information on what type of event on that fd it require to make progress. Progress can mean both progress toward the goal of reaching the application's desired socket condition, or finishing any outstanding task the XCM socket has.
+In case any of the conditions the application is asking for are believed to be already met, the xcm_want() call will return 0.
+In case the XCM socket has no outstanding tasks, and the application is not asking for any operation that the XCM socket believes it can't immediate fulfill, the call will return 0.
+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.
+Note that XCM may ask the application to wait for the connection's fd or fds to become writable, even if the application is waiting to receive a message. It may also ask the application to wait for the connection's fd to become readable, even if the application is attemting to send a messaging. For the quirks of xcm_want(), see io_waiting.
+Even though the conditions for a particular connection socket are met (fd is becoming writable, for example), there's no guarantee that the xcm_send() or xcm_receive() won't block (or in case of non-blocking mode, won't fail and set EAGAIN).
+The XCM socket fds may only be used with select(). Supplying this fd to any other OS calls (such as setsockopt(2), read(2) etc) is prohibited.
+The information received on which fd to use, and what events on that fd are relevant for the connection socket in its current state, are only valid until more xcm_* calls are made on this socket. See Finishing Outstanding Tasks for more information.
+The fd is an positive integer, unique within this process.
+The condition parameter is a bitmask, with the bits being XCM_SO_RECEIVABLE, XCM_SO_SENDABLE, and/or XCM_SO_ACCEPTABLE. If no bits are set, the application is not interested in anything beyond this XCM socket to finish any outstanding task.
+Each element in the events array is an int used as a bitmask. The bitmask at position N in the events array represents the file descriptor events the XCM transport is waiting for, for fd at position N in the fds array. The bits are XCM_FD_READABLE, XCM_FD_WRITABLE and/or XCM_FD_EXCEPTION. At least one bit is always set.
+If a socket is waiting for multiple events (for example, both readable and writable on the same fd, or readable on one fd, and writeable on another), the condition is met whenever any of the events occur (as oppose to all events).
+[in] | socket | The XCM socket. |
[in] | condition | The condition the application is waiting for. |
[out] | fds | An user-supplied array to store the fds. |
[out] | events | An user-supplied array of int to store the bitmask of each of the fds in the fds array. |
[in] | capacity | The length of the fds and events arrays. |
errno | Description |
---|---|
EOVERFLOW | The user-supplied buffer was too small to fit the socket's fds. |
EINVAL | The socket is not in blocking mode, or the condition bits are invalid. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains functions and macros to retrieve XCM version information. The library (i.e., implementation) version uses the semver convention. +More...
+ +Go to the source code of this file.
++Macros | |
#define | XCM_VERSION_MAJOR 1 |
#define | XCM_VERSION_MINOR 5 |
#define | XCM_VERSION_PATCH 0 |
#define | XCM_VERSION "1.5.0" |
#define | XCM_VERSION_API_MAJOR 0 |
#define | XCM_VERSION_API_MINOR 20 |
#define | XCM_VERSION_API "0.20" |
+Functions | |
unsigned int | xcm_version_major (void) |
unsigned int | xcm_version_minor (void) |
unsigned int | xcm_version_patch (void) |
const char * | xcm_version (void) |
unsigned int | xcm_version_api_major (void) |
unsigned int | xcm_version_api_minor (void) |
const char * | xcm_version_api (void) |
This file contains functions and macros to retrieve XCM version information. The library (i.e., implementation) version uses the semver convention.
+#define XCM_VERSION_MAJOR 1 | +
The XCM library major version.
+ +#define XCM_VERSION_MINOR 5 | +
The XCM library minor version.
+ +#define XCM_VERSION_PATCH 0 | +
The XCM library patch version.
+ +#define XCM_VERSION "1.5.0" | +
The complete XCM library version in string format.
+ +#define XCM_VERSION_API_MAJOR 0 | +
The XCM API/ABI major version this library version implements.
+ +#define XCM_VERSION_API_MINOR 20 | +
The XCM API/ABI minor version this library version implements.
+ +#define XCM_VERSION_API "0.20" | +
The complete XCM API version in string format.
+ +unsigned int xcm_version_major | +( | +void | +) | ++ |
Retrieves the library major version.
+This function returns the implementation major version of the library used at run time.
+ +unsigned int xcm_version_minor | +( | +void | +) | ++ |
Retrieves the library minor version.
+This function returns the implementation minor version of the library used at run time.
+ +unsigned int xcm_version_patch | +( | +void | +) | ++ |
Retrieves the library patch version.
+This function returns the implementation patch version of the library used at run time.
+ +const char * xcm_version | +( | +void | +) | ++ |
Retrieves the library version as a string.
+This function returns the version of the library used at run time, in string format.
+The string returned is statically allocated, and thus must not be free'd by the caller.
+ +unsigned int xcm_version_api_major | +( | +void | +) | ++ |
Retrieves the XCM API major version.
+This function returns the API major version of the library used at run time adheres to.
+ +unsigned int xcm_version_api_minor | +( | +void | +) | ++ |
Retrieves the XCM API minor version.
+This function returns the API minor version of the library used at run time adheres to.
+ +const char * xcm_version_api | +( | +void | +) | ++ |
Retrieves the library API version as a string.
+This function returns the API version of the library used at run time adheres to.
+The string returned is statically allocated, and thus must not be free'd by the caller.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
Cxcm_addr_host | |
Cxcm_addr_ip |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Files | |
xcm.h | |
This file contains the core Extensible Connection-oriented Messaging (XCM) API. | |
xcm_addr.h | |
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses. | |
xcm_attr.h | |
This file contains the XCM attribute access API. See Socket Attributes for an overview. | |
xcm_attr_types.h | |
This file contains type definitions for the XCM attribute access API. | |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
▼ include | |
xcm.h | This file contains the core Extensible Connection-oriented Messaging (XCM) API |
xcm_addr.h | This is an API for building and parsing Connection-oriented Messaging (XCM) addresses |
xcm_attr.h | This file contains the XCM attribute access API. See Socket Attributes for an overview |
xcm_attr_types.h | This file contains type definitions for the XCM attribute access API |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Macros | |
#define | XCM_VERSION_API_MAJOR 0 |
#define | XCM_VERSION_API_MINOR 22 |
#define | XCM_VERSION_API "0.22" |
#define XCM_VERSION_API_MAJOR 0 | +
The XCM API/ABI major version this library version implements.
+ +#define XCM_VERSION_API_MINOR 22 | +
The XCM API/ABI minor version this library version implements.
+ +#define XCM_VERSION_API "0.22" | +
The complete XCM API version in string format.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Macros | |
#define | XCM_VERSION_MAJOR 1 |
#define | XCM_VERSION_MINOR 7 |
#define | XCM_VERSION_PATCH 0 |
#define | XCM_VERSION "1.7.0" |
#define XCM_VERSION_MAJOR 1 | +
The XCM library major version.
+ +#define XCM_VERSION_MINOR 7 | +
The XCM library minor version.
+ +#define XCM_VERSION_PATCH 0 | +
The XCM library patch version.
+ +#define XCM_VERSION "1.7.0" | +
The complete XCM library version in string format.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This is the documentation for the Extensible Connection-oriented Messaging (XCM) programming APIs.
+XCM consists of of three parts; the core API in xcm.h, an address helper library API in xcm_addr.h, and the attribute access API in xcm_attr.h.
+The low version number is purely a result of all XCM releases being backward compatible, and thus left the major version at 0. It's not to be taken as a sign of immaturity. The API and its implementation has been stable for several years.
+XCM provides a connection-oriented, reliable messaging service with in-order delivery. The design goal is to allow a straight-off mapping to TCP and TLS, but also allow more efficient transport for local communication.
+XCM reuses much of the terminology (and semantics) of the BSD Sockets API.
+XCM has a client-server model. A server creates a server socket (with xcm_server()) bound to a specific address (in case of TCP or TLS, a TCP port on a particular IP interface), after which clients may initiate connections to the server. On a successful attempt, two connection sockets will be created; one on the server side (returned from xcm_accept()), and one of the client side (returned from xcm_connect()). Thus, a server serving multiple clients will have multiple sockets; one server socket and N connection sockets, one each for every client. A client will have one connection socket for each server it is connected to.
+Messages are always sent and received on a particular connection socket (and never on a server socket).
+In-order delivery - that messages arrive at the receiver in the same order they were sent by the sender side - is guaranteed, but only for messages sent on the same connection.
+XCM transports support flow control. Thus, if the sender message rate or bandwidth is higher than the network or the receiver can handle on a particular connection, xcm_send() in the sender process will eventually block (or return an error EAGAIN, if in non-blocking mode). Unless XCM is used for bulk data transfer (as oppose to signaling traffic), xcm_send() blocking because of slow network or a slow receiver should be rare indeed in practice. TCP, TLS, and UNIX domain socket transports all have large enough windows and socket buffers to allow a very large amount of outstanding data.
+In XCM, the application is in control of which transport will be used, with the address supplied to xcm_connect() and xcm_server() including both the transport name and the transport address.
+However, there is nothing preventing a XCM transport to use a more an abstract addressing format, and internally include multiple "physical" IPC transport options. This model is used by the UTLS Transport.
+Addresses are represented as strings with the following general syntax: <transport-name>:<transport-address>
For the UX UNIX Domain Socket transport, the addresses has this more specific form:
+
The addresses of the UXF UNIX Domain Socket transport variant follow the following format:
+
For the TCP, TLS, UTLS and SCTP transports the syntax is:
+
'*' is a shorthand for '0.0.0.0' (=bind to all IPv4 interfaces). '[*]' is the IPv6 equivalent.
+For example:
For TCP, TLS, UTLS and SCTP server socket addresses, the port can be set to 0, in which case XCM (or rather, the Linux kernel) will allocate a free TCP port.
+For transports allowing a DNS domain name as a part of the address, the transport will attempt resoĺv the name to an IP address. A DNS domain name may resolv to zero or more IPv4 addresses and/or zero or more IPv6 addresses. XCM relies on the system's configuration to prioritize between IPv4 and IPv6.
+XCM accepts IPv4 addresses in the dotted-decimal format
XCM allows only complete addresses with three '.', and not the archaic, classful, forms, where some bytes where left out, and thus the address contained fewer separators.
+XCM transports attempts to detect a number of conditions which can lead to lost connectivity, and does so even on idle connections.
+If the remote end closes the connection, the local xcm_receive() will return 0. If the process on the remote end crashed, xcm_receive() will return -1 and set errno ECONNRESET. If network connectivity to the remote end is lost, xcm_receive() will return -1 and errno will be set to ETIMEDOUT.
+In general, XCM follow the UNIX system API tradition when it comes to error handling. Where possible, errors are signaled to the application by using unused parts of the value range of the function return type. For functions returning signed integer types, this means the value of -1 (in case -1 is not a valid return value). For functions returning pointers, NULL is used to signal that an error has occurred. For functions where neither -1 or NULL can be used, or where the function does not return anything (side-effect only functions), an 'int' is used as the return type, and is used purely for the purpose to signal success (value 0), or an error (-1) to the application.
+The actual error code is stored in the thread-local errno variable. The error codes are those from the fixed set of errno values defined by POSIX, found in errno.h. Standard functions such as perror() and strerror() may be used to turn the code into a human-readable string.
+In non-blocking operation, given the fact the actual transmission might be defered (and the message buffered in the XCM layer), and that message receive processing might happen before the application has called receive, the error being signaled at the point of a certain XCM call might not be a direct result of the requested operation, but rather an error discovered previously.
+The documentation for xcm_finish() includes a list of generic error codes, applicable xcm_connect(), xcm_accept(), xcm_send() and xcm_receive().
+Also, for errors resulting in an unusable connection, repeated calls will produce the same errno.
+In UNIX-style event-driven programming, a single application thread handles multiple clients (and thus multiple XCM connection sockets) and the task of accepting new clients on the XCM server socket concurrently (although not in parallel). To wait for events from multiple sources, an I/O multiplexing facility such as select(2) or poll(2) is used.
+XCM supports this programming model. However, due to the extensive user space state/buffering required for some XCM transports, and the weak correlation between fd read/write state and actual XCM-level message send/receive that follows, XCM is forced to deviate from the BSD Sockets semantics in this regard.
+XCM allows the application to use select() and poll() by direct calls, or using any of the many event-loop libraries. For simplicity, being the most well-known of options, select() is used in this documentation to denote the whole family of POSIX I/O multiplexing facilities.
+An event-driven application will set the XCM sockets it handles into non-blocking mode (xcm_set_blocking() or the XCM_NONBLOCK flag to xcm_connect()).
+For XCM sockets in non-blocking mode, all potentially blocking API calls related to XCM connections, calls - xcm_connect(), xcm_accept(), xcm_send(), and xcm_receive() - finish immediately.
+Many such potentially blocking calls will finish immediately and with success. For xcm_send(), xcm_connect() and xcm_accept(), XCM signaling success means that the XCM layer has accepted the request. It may or may not have completed the request.
+In case the XCM_NONBLOCK flag is set in the xcm_connect() call, or in case the a XCM server socket is in non-blocking mode at the time of a xcm_accept() call, the newly created XCM connection returned to the application may be in a semi-operational state, with some internal processing and/or signaling with the remote peer still required before actual message transmission and reception may occur.
+The application may attempt to send or receive messages on such semi-operational connections.
+There are ways for an application wishing to know when connection establishment or the task of accepting a new client have finished to do so. See Finishing Outstanding Tasks for more information.
+To receive a message on a XCM connection socket in non-blocking mode, the application may wait for the right conditions to arise, by means of calling xcm_want() with the XCM_SO_RECEIVABLE flag set. When select() signals that these conditions are true, the application should issue xcm_receive() to attempt to retrieve a message.
+xcm_receive() may also called on speculation, prior to any xcm_want() call, to poll the socket for incoming messages.
+A XCM connection socket may buffer a number of messages, and thus the application should, for optimal performance, repeat xcm_receive() until it returns an error, and errno is set to EAGAIN. However, an application may choose to call xcm_want() with XCM_SO_RECEIVABLE set, but in that case, if there are buffered messages, the xcm_want() call will return 0, signaling that the socket doesn't have to do anything in order for the application to receive a message.
+Similar to receiving a message, an application may use xcm_want() to wait for the right conditions to occur to allow the transmission of a message. Just like with xcm_receive(), it may also choose to issue a xcm_send() call on speculation, falling back to xcm_want() and select() only in the face of XCM being unable to accept a new message. XCM will signal that this is the case by having xcm_send() returning an error with errno to EAGAIN.
+For send operations on non-blocking connection sockets, XCM may buffer whole or part of the message before transmission to the lower layer. This may be due to socket output buffer underrun, or the need for some in-band signaling, like security keys exchange, to happen before the transmission of the complete message may finish. The XCM layer will (re-)attempt to hand the message over to the lower layer at a future call to xcm_finish(), xcm_send(), or xcm_receive().
+An application should never attempt to draw any conclusions directly based the state of the fd or fds used by the XCM socket. The fds may be readable, and yet there may be no message to read from XCM, or it may not be readable, but yet there might be one or several messages buffered in the XCM layer. The same lack of correlation holds true also for xcm_send() and the fd writable/non-writable fd state. In addition, XCM may also used file descriptor for other purposes.
+For applications wishing to know when any outstanding message transmission has finished, it may use xcm_finish() to do so. Normally, applications aren't expected to require this kind of control. Please also not that the fact a message has left the XCM layer doesn't necessarily mean it has successfully been delivered to the recipient.
+xcm_connect(), xcm_accept(), xcm_send() may all leave the connection in a state where work is initiated, but not completed. In addition, the transport may also busy with an internal tasks, such filling its internal buffer with incoming messages, being involved in a key exchange operation (TLS hand shake) or keep alive message transmission or reception.
+Prior to the select() call, the application must query any XCM connection or server socket it has in non-blocking mode, asking it what events it is waiting for, and on what file descriptor. This is true even if the application neither wants to send or receive (on a connection socket), or accept incoming connections (on a server socket).
+The file descriptor, and the type of event, may change if the application issues any xcm_* calls on that connection. Easiest for the application is likely to query the connection socket immediately prior to each and every select() call.
+After waking up from a select() call, where the conditions required by a non-blocking XCM socket are met, the application must, if no xcm_send(), xcm_receive() or xcm_accept() calls are to be made, call xcm_finish(). This is to allow the socket to finish any outstanding tasks, even in the face of an application having no immediate further use of the socket.
+The query is made with xcm_want(), and it returns an array of file descriptors and, for each fd, the event type(s) the socket is interested in for that fd.
+In case the XCM socket has any such needs, the application should wait until the conditions are met (by means of select()). Upon the conditions are met, the application may continue to use the socket.
+Prior to changing a socket from non-blocking to blocking mode, any outstanding tasks must be finished.
+There might be situations that the fd or the fds tied to a XCM connection is marked (by select()) with the appropriate ready status (typically, but not always, write) for a xcm_send() operation to success, but a send may still block (or fail with EAGAIN, if in non-blocking mode). One such may be that the are indeed socket buffer space, but not enough to fit the complete message.
+The same situation may arise for xcm_receive(). Even though the fd tied to a XCM connection is marked with the appropriate ready status for a message to be received, a xcm_receive() may fail, since the complete message has not yet arrived.
+Thus, an application may never trust that a xcm_send() or xcm_receive() in blocking mode won't block, and similarly may never trust a send or receive operation to never fail and return EAGAIN, regardless of fd status.
+See Waiting for Read May Mean Waiting for Write for other reasons that a send or receive may always potentially block.
+XCM is designed to allow transports where all the processing is done in the application's thread of control (i.e. no separate OS threads or processes for a connection to do whatever in-band signaling is required for handling retransmission, dead peer detection, key exchange etc). One transport involving a lot of this kind of processing is the TLS Transport.
+For sockets in blocking mode, this complexity is hidden from the application (except in the form of message reception or transmission latency jitter).
+For event-driven applications, with their XCM connections in non-blocking mode, this has a non-obvious effect; in order to receive a message, the XCM transport may ask the application to have its thread wait (with select()) for the connection's fd to be marked writable. This is because in order to receive the message, the transport may need to complete some in-band signaling. For example, it may require some new keys for encrypting the outgoing message, since the old have expired.
+The other way around may also be true; that in order to write a message, the transport may need to have the application to wait for the fd to become readable (since it needs to receive some signaling message from the remote peer in order to proceed).
+The same holds true also for accept operation on server sockets; in order to accept an incoming request, the transport may ask the application to wait for the fd to be come writable.
+In this example, the application connects and immediately tries to send a message. This may fail (for example, in case TCP and/or TLS-level connection establishement has not yet been completed), in which case the application will fall back and wait with the use of xcm_want() and select().
+In case the application wants to know when the connection establishment has finished, it may use xcm_finish() to do so, like in the below example sequence.
+While connecting to a server socket, the client's connection attempt may be refused immediately.
+In many cases, the application is handed a connection socket before the connection establishment is completed. Any errors occuring during this process is handed over to the application at the next XCM call; would it be xcm_finish(), xcm_send() or xcm_receive().
+In this example, the application runs into a situation where the operation requested may be perfomed immediately (since XCM already have a buffered message).
+In this example the application flushes any internal XCM buffers before shutting down the connection, to ensure that any buffered messages are delivered to the lower layer.
+In this sequence, a server accepts a new connection, and continues to attempt to receive a message on this connection, while still, concurrently, is ready to accept more clients on the server socket.
+Tied to an XCM server or connection socket is a set of read-only key-value pairs known as attributes. Which attributes are available varies across different transports, and different socket types.
+The attribute names are strings, and follows a hierarchical naming schema. For example, all generic XCM attributes, expected to be implemented by all transports, have the prefix "xcm.". Transport-specific attributes are prefixed with the transport or protocol name (e.g. "tcp." for TCP-specific attributes applicable to the TLS and TCP transports).
+The attribute value is coded in the native C data types and byte order. Strings are NUL-terminated, and the NUL character is included in the length of the attribute. There are three value types; a boolean type, a 64-bit signed integer type and a string type. See xcm_attr_types.h for details.
+The attribute access API is in xcm_attr.h.
+Retrieving an integer attribute may look like this (minus error handling):
Process-wide and/or read/write attributes may be supported in the future.
+These attributes are expected to be found on XCM sockets regardless of transport type.
+For TCP transport-specific attributes, see TCP Socket Attributes, and for TLS, see TLS Socket Attributes.
+Attribute Name | Socket Type | Value Type | Description |
---|---|---|---|
xcm.type | All | String | The socket type - "server" or "connection". |
xcm.transport | All | String | The transport type. |
xcm.local_addr | All | String | See xcm_local_addr(). |
xcm.remote_addr | Connection | String | See xcm_remote_addr(). |
xcm.max_msg_size | Connection | Integer | The maximum size of any message transported by this connection. |
XCM has a set of generic message counters, which keeps track of the number of messages crossing a certain boundary for a particular connection, and a sum of their size.
+Some of the message and byte counter attributes use the concept of a "lower layer". What this means depends on the transport. For the UX And TCP transports, it is the Linux kernel. For example, for TCP, if the xcm.to_lower_msgs is incremented, it means that XCM has successfully sent the complete message to the kernel's networking stack for further processing. It does not means it has reached the receiving process. It may have, but it also may be sitting on the local or remote socket buffer, on a NIC queue, or be in-transmit in the network. For TLS, the lower layer is OpenSSL.
+All the "xcm.*_bytes" counters count the length of the XCM message payload (as in the length field in xcm_send()), and thus does not include any underlying headers.
+The message counters only count messages succesfully sent and/or received.
+Attribute Name | Socket Type | Value Type | Description |
---|---|---|---|
xcm.from_app_msgs | Connection | Integer | Messages sent from the application and accepted into XCM. |
xcm.from_app_bytes | Connection | Integer | The sum of the size of all messages counted by xcm.from_app_msgs. |
xcm.to_app_msgs | Connection | Integer | Messages delivered from XCM to the application. |
xcm.to_app_bytes | Connection | Integer | The sum of the size of all messages counter by xcm.to_app_msgs. |
xcm.from_lower_msgs | Connection | Integer | Messages received by XCM from the lower layer. |
xcm.from_lower_bytes | Connection | Integer | The sum of the size of all messages counted by xcm.from_lower_msgs. |
xcm.to_lower_msgs | Connection | Integer | Messages successfully sent by XCM into the lower layer. |
xcm.to_lower_bytes | Connection | Integer | The sum of the size of all messages counted by xcm.to_lower_msgs. |
XCM includes a control interface, which allows iteration over the OS instance's XCM server and connection sockets (for processes with the appropriate permissions), and access to their attributes (see Socket Attributes).
+The control interface is optional by means of build-time configuration.
+For each XCM server or connection socket, there is a corresponding UNIX domain socket which is used for control signaling (i.e. state retrieval).
+By default, the control interface's UNIX domain sockets are stored in the /run/xcm/ctl
directory.
This directory needs to be created prior to running any XCM applications (for the control interface to worker properly) and should be writable for all XCM users.
+A particular process using XCM may be configured to use a non-default directory for storing the UNIX domain sockets used for the control interface by means of setting the XCM_CTL
variable. Please note that using this setting will cause the XCM connections to be not visible globally on the OS instance (unless all other XCM-using processes also are using this non-default directory).
The XCM socket state the control interface allows access to (i.e. the attributes) is owned by the various processes is the system using the XCM library. Thus, to avoid synchronization issues, the control interface is driven by the application's thread(s), although the application is kept unaware of this fact.
+If the control interface is enabled, some of the file descriptors returned to the application (in xcm_want()) will are not tied to the data interface (i.e. xcm.h and the messaging I/O), but rather the control interface.
+The control interface is using one file descriptor for the a UNIX domain server socket, and zero or more fds for any control interface clients attached.
+Generally, since the application is left unaware (from an API perspective) from the existence of the control interface, errors are not reported up to the application. They are however logged.
+Application threads owning XCM sockets, but which are busy with non-XCM processing for a long duration of time, or otherwise are leaving their XCM sockets unattended to (in violation of XCM API contract), will not respond on the control interface's UNIX domain sockets (corresponding to their XCM sockets). Only the prescence of these sockets may be detected, but their state cannot be retrieved.
+Internally, the XCM implementation has control interface client library, but this library's API is not public at this point.
+XCM includes a command-line program xcmctl
which uses the Control API to iterate of the system's current XCM sockets, and allow access (primarily for debugging purposes) to the sockets' attributes.
Unlike BSD sockets, a XCM socket may not be shared among different threads without synchronization external to XCM. With proper external serialization, a socket may be shared by different threads in the same process, although it might provide difficult in practice since a thread in a blocking XCM function will continue to hold the lock, and thus preventing other threads from accessing the socket at all. For non-blocking sockets, the contract of xcm_want() may be broken in so far the conditions on which a thread is waiting for may be change, if another thread calls into that connection socket.
+It is however safe to "give away" a XCM socket from one thread to another, provided the appropriate memory fences are used.
+These limitations (compared to BSD Sockets) are in place to allow socket state outside the kernel (which is required for TCP framing and TLS).
+Sharing a XCM socket between threads in different processes is not possible.
+After a fork() call, either of the two process (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 not call any other XCM API call than xcm_cleanup(), which frees local memory tied to this socket in the non-owner's process address space, without impacting the connection state in the owner process.
+The core XCM API functions are oblivious to the transports used. However, the support for building, and parsing addresses (which some applications are expected to do) are available only for a set of pre-defined set of transports. There is nothing preventing xcm_addr.h from being extended, and also nothing prevents an alternative XCM implementation to include more transports without touching the address helper API.
+The UX transport uses UNIX Domain (AF_UNIX, also known as AF_LOCAL) Sockets.
+UX sockets may only be used with the same OS instance (or, more specifically, between processes in the same Linux kernel network namespace).
+UNIX Domain Sockets comes in a number of flavors, and XCM uses the SOCK_SEQPACKET variety. SOCK_SEQPACKET sockets are connection-oriented, preserves message boundaries and delivers messages in the same order they were sent; perfectly matching XCM semantics and provides for an near-trivial mapping.
+UX is the most efficient of the XCM transports.
+The standard UNIX Domain Sockets as defined by POSIX uses the file system as its namespace, with the sockets also being files. However, for simplicity and to avoid situations where stale socket files (originating from crashed processes) causing problems, the UX transport uses a Linux-specific extension, allowing a private UNIX Domain Socket namespace. This is known as the abstract namespace (see the unix(7) man page for details). With the abstract namespace, server socket address allocation has the same life time as TCP ports (i.e. if the process dies, the address is free'd).
+The UX transport enables the SO_PASSCRED BSD socket option, to give the remote peer a name (which UNIX domain connection socket doesn't have by default). This is for debugging and observability purposes. Without a remote peer name, in server processes with multiple incoming connections to the same server socket, it's difficult to say which of the server-side connection sockets goes to which remote peer. The kernel-generated, unique, name is an integer in the form "%05x" (printf format). Applications using hardcoded UX addresses should avoid such names by, for example, using a prefix.
+The UTLS Transport also indirectly uses the UX namespace, so care should be taken to avoid any clashes between UX and UTLS sockets in the same network namespace.
+The UXF transport is identical to the UX transport, only it uses the standard POSIX naming mechanism. The name of a server socket is a file system path, and the socket is also a file.
+The UXF sockets resides in a file system namespace, as opposed to UX sockets, which live in a network namespace.
+Upon xcm_close(), the socket will be closed and the file removed. If an application crashes or otherwise fails to run xcm_close(), it will leave a file in the file system pointing toward a non-existing socket. This file will prevent the creation another server socket with the same name.
+The TCP transport uses the Transmission Control Protocol (TCP), by means of the BSD Sockets API.
+TCP is a byte-stream service, but the XCM TCP transport adds framing on top of the stream. A single-field 32-bit header containing the message length in network byte order is added to every message.
+TCP uses TCP Keepalive to detect lost network connectivity between the peers.
+The TCP transport supports IPv4 and IPv6.
+Since XCM is designed for signaling traffic, the TCP transport disables the Nagle algorithm of TCP to avoid its excessive latency.
+The TCP attributes are retrieved from the kernel (struct tcp_info in linux/tcp.h). See the tcp(7) manual page, and its section on the TCP_INFO socket option.
+Attribute Name | Socket Type | Value Type | Description |
---|---|---|---|
tcp.rtt | Connection | Integer | The current TCP round-trip estimate (in us). |
tcp.total_retrans | Connection | Integer | The total number of retransmitted TCP segments. |
tcp.segs_in | Connection | Integer | The total number of segments received. |
tcp.segs_out | Connection | Integer | The total number of segments sent. |
tcp.segs_in
and tcp.segs_out
are only present when running XCM on Linux kernel 4.2 or later.The TLS transport uses TLS to provide a secure, private, two-way authenticated transport.
+TLS is a byte-stream service, but the XCM TLS transport adds framing in the same manner as does the XCM TCP transport.
+The TLS transport supports IPv4 and IPv6.
+The TLS transport disables the Nagle algorithm of TCP.
+The TLS transport expect the certificate, trust chain and private key files to be found in a file system directory - the certificate directory. The default path are configured at build-time, but can be overriden on a per-process basis by means of a UNIX environment variable. The current value of XCM_TLS_CERT
(at the time of xcm_connect() or xcm_accept()) determines the certificate directory used for that connection.
In case the files in the certificate directory are modified, the new versions of the files will be used by new connections. The TLS transports works with differences between set of files, and thus the new generation of files need not nesserarily be newer (i.e. higher mtime).
+The certificate directory must be updated in an atomic manner, or XCM may end up using the certificate file from one generation of files and the key file from another. One way of achieving an atomic update is to have the certificate directory being a symbolic link to the directory where the actual files are located. Upon update, a new directory is created and populated, and the old symbolic link is replace with a new one in an atomic manner (i.e. with rename(2)). It's legal to switch back-and-forth between two sets of files, but the time between the back and the forth switch (assuming the atomicity-by-symlink method is used) must be enough to result in different file system modification times on the symbolic link (usually ~10 ms).
+The TLS transport will, at the time of XCM socket creation (xcm_connect() or xcm_server()), look up the process' current network namespace. In case the namespace is given a name per the iproute2 methods and conventions, XCM will retrieve this name and use it in the certificate and key lookup.
+In the certificate directory, the TLS transport expects the certificate to follow the below naming convention (where <ns> is the namespace):
The private key is stored in:
The trust chain is stored in:
For the default namespace (or any other network namespace not named according to iproute2 standards), the certificate need to be stored in a file "cert.pem", the private key in "key.pem" and the trust chain in "tc.pem".
+In case the certificate, key or trust chain files are not in place (for a particular namespace), a xcm_server() call will return an error and set errno to EPROTO. The application may choose to retry at a later time.
+TLS has all the TCP-level attributes of the TCP transport; see TCP Socket Attributes.
+Attribute Name | Socket Type | Value Type | Description |
---|---|---|---|
tls.peer_subject_key_id | Connection | String | The X509v3 Subject Key Identifier of the remote peer, or a zero-length string in case the TLS connection is not established. |
The UTLS transport provides a hybrid transport, utilizing both the TLS and UX transports internally for actual connection establishment and message delivery.
+On the client side, at the time of xcm_connect(), the UTLS transport determines if the server socket can be reached by using the UX transport (i.e. if the server socket is located on the same OS instance, in the same network namespace). If not, UTLS will attempt to reach the server by means of the TLS transport.
+For a particular UTLS connection, either TLS or UX is used (never both). XCM connections to a particular UTLS server socket may be a mix of the two different types.
+In the UTLS transport, xcm_want() will return at least two file descriptors; one for the TCP BSD socket file descriptor utilized for TLS, and one for the UNIX domain socket. However, the applications should not depend on this (or the fact that other transports might return fewer).
+For an UTLS server socket with the address utls:<ip>:<port>
, two underlying addresses will be allocated; tls:<ip>:<port>
and ux:<ip>:<port>
.
Or, in the case DNS is used: tls:<hostname>:<port>
and ux:<hostname>:<port>
.
A wildcard should never be used when creating a UTLS server socket.
+If a DNS hostname is used in place of the IP address, both the client and server need employ DNS, and also agree upon which hostname to use (in case there are several pointing at the same IP address).
+Failure to adhere to the above two rules will prevent a client from finding a local server. Such a client will instead establish a TLS connection to the server.
+The SCTP transport uses the Stream Control Transmission Protocol (SCTP). SCTP provides a reliable, message-oriented service. In-order delivery is optional, and to adhere to XCM semantics (and for other reasons) XCM leaves SCTP in-order delivery enabled.
+The SCTP transport utilizes the native Linux kernel's implementation of SCTP, via the BSD Socket API. The operating mode is such that there is a 1:1-mapping between an association and a socket (fd).
+The SCTP transport supports IPv4 and IPv6.
+To minimize latency, the SCTP transport disables the Nagle algorithm.
+Namespaces is a Linux kernel facility concept for creating multiple, independent namespaces for kernel resources of a certain kind.
+Linux Network Namespaces will affect all transports, including the UX transport.
+XCM has no explicit namespace support, but the application is rather expected to use the Linux kernel facilities for this functionality (i.e. switch to the right namespace before xcm_server() och xcm_connect()).
+In case the system follows the iproute2 conventions in regards to network namespace naming, the TLS and UTLS transports support per-network namespace TLS certificates and private keys.
+XCM, in its current form, does not support binding to a local socket before doing connect() - something that is possible with BSD Sockets, but very rarely makes sense.
+XCM also doesn't have a sendmmsg() or recvmmsg() equivalent. Those could easily be added, and would provide some major performance improvements for applications that are sending or receiving multiple messages on the same connection on the same time. *mmsg() equivalents have been left out because there are strong doubts there are such applications.
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
#include <xcm_addr.h>
+Data Fields | ||
enum xcm_addr_type | type | |
union { | ||
+ struct xcm_addr_ip ip | ||
+ char name [254] | ||
}; | ||
Hostname or IPv4/IPv6 address data type.
+enum xcm_addr_type xcm_addr_host::type | +
Type tag
+ +union { ... } xcm_addr_host | +
Union containing the actual hostname, IPv4 or IPv6 address bytes
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
#include <xcm_addr.h>
+Data Fields | ||
sa_family_t | family | |
union { | ||
in_addr_t ip4 | ||
uint8_t ip6 [16] | ||
} | addr | |
IPv4 or IPv6 address data type.
+sa_family_t xcm_addr_ip::family | +
Type tag; AF_INET or AF_INET6
+ +in_addr_t xcm_addr_ip::ip4 | +
Contains the IPv4 address in network byte order (in case family is set to AF_INET).
+ +uint8_t xcm_addr_ip::ip6[16] | +
Contains the IPv6 address (in case family is set to AF_INET6).
+ +union { ... } xcm_addr_ip::addr | +
Union containing the actual IPv4 or a IPv6 address bytes
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
Library Version | |
API Version |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the core Extensible Connection-oriented Messaging (XCM) API. +More...
+#include <errno.h>
#include <stdbool.h>
#include <sys/types.h>
Go to the source code of this file.
++Macros | |
#define | XCM_NONBLOCK (1<<0) |
#define | XCM_FD_READABLE (1<<0) |
#define | XCM_FD_WRITABLE (1<<1) |
#define | XCM_FD_EXCEPTION (1<<2) |
#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_server (const char *local_addr) |
int | xcm_close (struct xcm_socket *socket) |
void | xcm_cleanup (struct xcm_socket *socket) |
struct xcm_socket * | xcm_accept (struct xcm_socket *server_socket) |
int | xcm_send (struct xcm_socket *conn_socket, const void *buf, size_t len) |
int | xcm_receive (struct xcm_socket *conn_socket, void *buf, size_t capacity) |
int | xcm_want (struct xcm_socket *socket, int condition, int *fds, int *events, size_t capacity) |
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) |
This file contains the core Extensible Connection-oriented Messaging (XCM) API.
+#define XCM_NONBLOCK (1<<0) | +
Flag used in xcm_connect()
+ +#define XCM_FD_READABLE (1<<0) | +
Flag bit denoting a readable fd event in xcm_want().
+ +#define XCM_FD_WRITABLE (1<<1) | +
Flag bit denoting a writable fd event.
+ +#define XCM_FD_EXCEPTION (1<<2) | +
Flag bit denoting a exception fd event.
+ +#define XCM_SO_RECEIVABLE (1<<0) | +
Flag bit denoting a socket where the application likely can receive a message.
+ +#define XCM_SO_SENDABLE (1<<1) | +
Flag bit denoting a socket where the application likely can send a message.
+ +#define XCM_SO_ACCEPTABLE (1<<2) | +
Flag bit denoting a socket with a pending incoming connection.
+ +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_want() to retrieve the needed information to be able to wait 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).
+[in] | remote_addr | The remote address which to connect. |
[in] | flags | Either 0, or XCM_NONBLOCK for a non-blocking connect. |
errno | Description |
---|---|
EINVAL | Invalid address format. |
ENOPROTOOPT | Transport protocol not available. |
EMFILE | The limit on the total number of open fds has been reached. |
ENOENT | DNS domain name resolution failed. |
See xcm_finish() for other possible errno values.
+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), a xcm_server() call also includes a blocking name resolution (e.g. gethostbyname()).
+[in] | local_addr | The local address to which this socket should be bound. |
errno | Description |
---|---|
EACCESS | Permission to create the socket is denied. |
EADDRINUSE | Local socket address is already in use. |
ENOMEM | Insufficient memory. |
EINVAL | Invalid address format. |
ENOPROTOOPT | Transport protocol not available. |
EMFILE | The limit on the total number of open fds has been reached. |
EPROTO | A protocol error occured. |
ENOENT | DNS domain name resolution failed. |
int xcm_close | +( | +struct xcm_socket * | +socket | ) | ++ |
Close an endpoint.
+This function close a 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.
+[in] | socket | The socket to be closed, or NULL (in case xcm_close() is a no-operation). |
void xcm_cleanup | +( | +struct xcm_socket * | +socket | ) | ++ |
Cleans up any local resources tied to a 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().
+[in] | socket | The socket which local resources are to be freed, or NULL (in case xcm_cleanup() is a no-operation). |
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.
+[in] | server_socket | The server socket on which to attempt to accept one pending connection. |
errno | Description |
---|---|
EMFILE | The limit on the total number of open fds has been reached. |
See xcm_finish() for other possible errno values.
+ +int xcm_send | +( | +struct xcm_socket * | +conn_socket, | +
+ | + | const void * | +buf, | +
+ | + | size_t | +len | +
+ | ) | ++ |
Send message on a particular connection.
+The xcm_send() function is used to send a message out on a connection socket. A XCM connection goes from a client to a server, and this connection socket may represent either one of the two endpoints.
+[in] | conn_socket | The connection socket the message will be sent on. |
[in] | buf | A pointer to the message data buffer. |
[in] | len | The length of the message in bytes. Zero-length messages are not allowed. |
errno | Description |
---|---|
EMSGSIZE | Message is too large. See also Generic Attributes. |
See xcm_finish() for more errno values.
+ +int xcm_receive | +( | +struct xcm_socket * | +conn_socket, | +
+ | + | void * | +buf, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Receive message on a particular connection.
+The xcm_receive() function is used to receive message on a connection socket. A XCM connection goes from a client to a server, and this connection socket may represent either one of the two endpoints.
+If 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).
+[in] | conn_socket | The connection socket the message will receive be on. |
[out] | buf | The user-supplied buffer where the incoming message will be stored. |
[in] | capacity | The capacity in bytes of the buffer. |
See xcm_finish() for possible errno values.
+ +int xcm_want | +( | +struct xcm_socket * | +socket, | +
+ | + | int | +condition, | +
+ | + | int * | +fds, | +
+ | + | int * | +events, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Query the socket what events on which file descriptors it's waiting for.
+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.
+With xcm_want(), the application will inform the XCM socket what condition it's waiting for (i.e. what XCM operation it wants to perform), and in return the XCM socket will provide a set of file descriptors and, for each fd, information on what type of event on that fd it require to make progress. Progress can mean both progress toward the goal of reaching the application's desired socket condition, or finishing any outstanding task the XCM socket has.
+In case any of the conditions the application is asking for are believed to be already met, the xcm_want() call will return 0.
+In case the XCM socket has no outstanding tasks, and the application is not asking for any operation that the XCM socket believes it can't immediate fulfill, the call will return 0.
+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.
+Note that XCM may ask the application to wait for the connection's fd or fds to become writable, even if the application is waiting to receive a message. It may also ask the application to wait for the connection's fd to become readable, even if the application is attemting to send a messaging. For the quirks of xcm_want(), see Waiting for Read May Mean Waiting for Write.
+Even though the conditions for a particular connection socket are met (fd is becoming writable, for example), there's no guarantee that the xcm_send() or xcm_receive() won't block (or in case of non-blocking mode, won't fail and set EAGAIN).
+The XCM socket fds may only be used with select(). Supplying this fd to any other OS calls (such as setsockopt(2), read(2) etc) is prohibited.
+The information received on which fd to use, and what events on that fd are relevant for the connection socket in its current state, are only valid until more xcm_* calls are made on this socket. See Finishing Outstanding Tasks for more information.
+The fd is an positive integer, unique within this process.
+The condition parameter is a bitmask, with the bits being XCM_SO_RECEIVABLE, XCM_SO_SENDABLE, and/or XCM_SO_ACCEPTABLE. If no bits are set, the application is not interested in anything beyond this XCM socket to finish any outstanding task.
+Each element in the events array is an int used as a bitmask. The bitmask at position N in the events array represents the file descriptor events the XCM transport is waiting for, for fd at position N in the fds array. The bits are XCM_FD_READABLE, XCM_FD_WRITABLE and/or XCM_FD_EXCEPTION. At least one bit is always set.
+If a socket is waiting for multiple events (for example, both readable and writable on the same fd, or readable on one fd, and writeable on another), the condition is met whenever any of the events occur (as oppose to all events).
+[in] | socket | The XCM socket. |
[in] | condition | The condition the application is waiting for. |
[out] | fds | An user-supplied array to store the fds. |
[out] | events | An user-supplied array of int to store the bitmask of each of the fds in the fds array. |
[in] | capacity | The length of the fds and events arrays. |
errno | Description |
---|---|
EOVERFLOW | The user-supplied buffer was too small to fit the socket's fds. |
EINVAL | The socket is not in blocking mode, or the condition bits are invalid. |
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, xcm_accept() or xcm_send() call on a connection socket in non-blocking mode, wishing to finish outstanding processing related to that operation, to know if it succeeded or not.
+In addition, xcm_finish() must be called if the conditions set by xcm_want() are met (as signaled by select(), 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.
+[in] | socket | The connection or server socket. |
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. |
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.
+[in] | socket | The socket. |
[in] | should_block | Set to true for blocking operation, false for non-blocking mode. |
errno | Description |
---|---|
EAGAIN | The connection socket has unfinished work that needs to completed before mode can be switched. |
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.
+[in] | socket | The socket. |
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.
+[in] | conn_socket | The connection socket. |
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.
+[in] | socket | A server or connection socket. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses. +More...
+#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <errno.h>
#include <xcm_addr_compat.h>
Go to the source code of this file.
++Data Structures | |
struct | xcm_addr_ip |
struct | xcm_addr_host |
+Macros | |
#define | XCM_UTLS_PROTO "utls" |
#define | XCM_TLS_PROTO "tls" |
#define | XCM_TCP_PROTO "tcp" |
#define | XCM_SCTP_PROTO "sctp" |
#define | XCM_UX_PROTO "ux" |
#define | XCM_UXF_PROTO "uxf" |
+Enumerations | |
enum | xcm_addr_type { xcm_addr_type_name +, xcm_addr_type_ip + } |
+Functions | |
int | xcm_addr_parse_proto (const char *addr_s, char *proto, size_t capacity) |
int | xcm_addr_parse_utls (const char *utls_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_tls (const char *tls_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_tcp (const char *tcp_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_sctp (const char *sctp_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_ux (const char *ux_addr_s, char *ux_path, size_t capacity) |
int | xcm_addr_parse_uxf (const char *uxf_addr_s, char *uxf_path, size_t capacity) |
int | xcm_addr_make_utls (const struct xcm_addr_host *host, unsigned short port, char *utls_addr_s, size_t capacity) |
int | xcm_addr_make_tls (const struct xcm_addr_host *host, unsigned short port, char *tls_addr_s, size_t capacity) |
int | xcm_addr_make_tcp (const struct xcm_addr_host *host, unsigned short port, char *tcp_addr_s, size_t capacity) |
int | xcm_addr_make_sctp (const struct xcm_addr_host *host, unsigned short port, char *sctp_addr_s, size_t capacity) |
int | xcm_addr_make_ux (const char *ux_name, char *ux_addr_s, size_t capacity) |
int | xcm_addr_make_uxf (const char *uxf_name, char *uxf_addr_s, size_t capacity) |
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses.
+#define XCM_UTLS_PROTO "utls" | +
Protocol string for the combined TLS+UX transport.
+ +#define XCM_TLS_PROTO "tls" | +
Protocol string for the Transport Layer Security (TLS) transport.
+ +#define XCM_TCP_PROTO "tcp" | +
Protocol string for the TCP transport.
+ +#define XCM_SCTP_PROTO "sctp" | +
Protocol string for the SCTP transport.
+ +#define XCM_UX_PROTO "ux" | +
Protocol string for the UNIX Domain socket (AF_UNIX SEQPACKET) transport (using the abstract namespace).
+ +#define XCM_UXF_PROTO "uxf" | +
Protocol string for the UNIX Domain socket (AF_UNIX SEQPACKET) transport (using file system-based naming).
+ +int xcm_addr_parse_proto | +( | +const char * | +addr_s, | +
+ | + | char * | +proto, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses the protocol part of a XCM address.
+[in] | addr_s | The XCM address string. |
[out] | proto | The buffer where to store the protocol part of the address. |
[in] | capacity | The buffer length in bytes. |
errno | Description |
---|---|
EINVAL | Malformed address. |
ENAMETOOLONG | The user-supplied buffer is too small to fit the protocol. |
int xcm_addr_parse_utls | +( | +const char * | +utls_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a UTLS XCM address.
+[in] | utls_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TLS port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_tls | +( | +const char * | +tls_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a TLS XCM address.
+[in] | tls_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TLS port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_tcp | +( | +const char * | +tcp_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a TCP XCM address.
+[in] | tcp_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TCP port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_sctp | +( | +const char * | +sctp_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parse a SCTP XCM address.
+[in] | sctp_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The SCTP port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_ux | +( | +const char * | +ux_addr_s, | +
+ | + | char * | +ux_path, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses an UX (UNIX Domain Socket) XCM address.
+[in] | ux_addr_s | The string to sparse. |
[out] | ux_path | The UNIX (NUL-terminated) abstract name portion of the UX address. |
[in] | capacity | The length of the user-supplied path buffer. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_uxf | +( | +const char * | +uxf_addr_s, | +
+ | + | char * | +uxf_path, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses an UXF (UNIX Domain Socket) XCM address.
+[in] | uxf_addr_s | The string to sparse. |
[out] | uxf_path | The UNIX (NUL-terminated) path name portion of the UXF address. |
[in] | capacity | The length of the user-supplied path buffer. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_make_utls | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +utls_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a UTLS XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | utls_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_tls | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +tls_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a TLS XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | tls_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_tcp | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +tcp_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a TCP XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | tcp_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_sctp | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +sctp_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a SCTP XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | sctp_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_ux | +( | +const char * | +ux_name, | +
+ | + | char * | +ux_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds an UX XCM address string from the supplied UNIX Domain Socket name.
+[in] | ux_name | The UNIX Domain Socket name. |
[out] | ux_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid format of or too long UNIX Domain Socket address. |
int xcm_addr_make_uxf | +( | +const char * | +uxf_name, | +
+ | + | char * | +uxf_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds an UXF XCM address string from the supplied file system path.
+[in] | uxf_name | The UNIX Domain path. |
[out] | uxf_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid format of or too long UNIX Domain Socket address. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the XCM attribute access API. See Socket Attributes for an overview. +More...
+ +Go to the source code of this file.
++Typedefs | |
typedef void(* | xcm_attr_cb) (const char *attr_name, enum xcm_attr_type type, void *value, size_t value_len, void *cb_data) |
+Functions | |
int | xcm_attr_get (struct xcm_socket *socket, const char *name, enum xcm_attr_type *type, void *value, size_t capacity) |
void | xcm_attr_get_all (struct xcm_socket *socket, xcm_attr_cb cb, void *cb_data) |
This file contains the XCM attribute access API. See Socket Attributes for an overview.
+typedef void(* xcm_attr_cb) (const char *attr_name, enum xcm_attr_type type, void *value, size_t value_len, void *cb_data) | +
The signature of the user-supplied callback used in xcm_attr_get_all().
+ +int xcm_attr_get | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | enum xcm_attr_type * | +type, | +
+ | + | void * | +value, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Retrieves the value of a XCM socket attribute.
+For a list of available attributes for different socket and transport types, see Generic Attributes, TCP Socket Attributes and TLS Socket Attributes.
+For a description of the C types and buffer capacity requirements of the attribute types, see xcm_attr_types.h.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[out] | type | A pointer to a location where the type of the attribute will be stored. May be left to NULL, in case the type is known a priori. |
[out] | value | A user-supplied buffer where the value of the attribute will be stored. |
[in] | capacity | The length of the buffer (in bytes). |
errno | Description |
---|---|
ENOENT | The attribute does not exist. |
EOVERFLOW | The user-supplied buffer was too small to fit the value. |
void xcm_attr_get_all | +( | +struct xcm_socket * | +socket, | +
+ | + | xcm_attr_cb | +cb, | +
+ | + | void * | +cb_data | +
+ | ) | ++ |
Retrieves all XCM socket attributes.
+This function retrieves all available attribute names, types and their current values on a particular connection or server socket.
+The memory locations refered to by the attr_name and attr_value pointers is only guaranteed to be valid for the execution of the callback. If needed later, they need to be copied.
+[in] | socket | The connection or server socket. |
[in] | cb | The function to be called for every attribute on the socket. |
[in] | cb_data | An opaque (for XCM) pointer returned back to the application in the callback. cb_data may be NULL. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the XCM attribute map API. +More...
+ +Go to the source code of this file.
++Typedefs | |
typedef void(* | xcm_attr_map_foreach_cb) (const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len, void *user) |
+Functions | |
struct xcm_attr_map * | xcm_attr_map_create (void) |
struct xcm_attr_map * | xcm_attr_map_clone (const struct xcm_attr_map *original) |
void | xcm_attr_map_add (struct xcm_attr_map *attr_map, const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len) |
void | xcm_attr_map_add_bool (struct xcm_attr_map *attr_map, const char *attr_name, bool attr_value) |
void | xcm_attr_map_add_int64 (struct xcm_attr_map *attr_map, const char *attr_name, int64_t attr_value) |
void | xcm_attr_map_add_str (struct xcm_attr_map *attr_map, const char *attr_name, const char *attr_value) |
const void * | xcm_attr_map_get (const struct xcm_attr_map *attr_map, const char *attr_name, enum xcm_attr_type *attr_type, size_t *attr_value_len) |
const bool * | xcm_attr_map_get_bool (const struct xcm_attr_map *attr_map, const char *attr_name) |
const int64_t * | xcm_attr_map_get_int64 (const struct xcm_attr_map *attr_map, const char *attr_name) |
const char * | xcm_attr_map_get_str (const struct xcm_attr_map *attr_map, const char *attr_name) |
bool | xcm_attr_map_exists (const struct xcm_attr_map *attr_map, const char *attr_name) |
void | xcm_attr_map_del (struct xcm_attr_map *attr_map, const char *attr_name) |
size_t | xcm_attr_map_size (const struct xcm_attr_map *attr_map) |
void | xcm_attr_map_foreach (const struct xcm_attr_map *attr_map, xcm_attr_map_foreach_cb cb, void *user) |
bool | xcm_attr_map_equal (const struct xcm_attr_map *attr_map_a, const struct xcm_attr_map *attr_map_b) |
void | xcm_attr_map_destroy (struct xcm_attr_map *attr_map) |
This file contains the XCM attribute map API.
+A XCM attribute map is a set of key-value pairs. The key is an attribute name in the form of a string. One key maps to at most one value. The attribute value is either a boolean, a signed 64-bit integer, a string, or a variable-length binary object.
+typedef void(* xcm_attr_map_foreach_cb) (const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len, void *user) | +
Callback function prototype used for iteration.
+ +struct xcm_attr_map * xcm_attr_map_create | +( | +void | +) | ++ |
Create an attribute map instance.
+struct xcm_attr_map * xcm_attr_map_clone | +( | +const struct xcm_attr_map * | +original | ) | ++ |
Create a copy of an attribute map instance.
+[in] | attr_map | The original attribute map instance, to be copied. |
void xcm_attr_map_add | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | enum xcm_attr_type | +attr_type, | +
+ | + | const void * | +attr_value, | +
+ | + | size_t | +attr_value_len | +
+ | ) | ++ |
Associate a key with a value.
+This function associates the attribute key attr_name
to the attribute value attr_value
in the attribute map attr_map
. If the key attr_name
already exists, its value is replaced.
Both the key and the value will be copied, and thus attr_name
and attr_value
will still be owned by the caller at call completion.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_type | The type of the value to be added. |
[in] | attr_value | The value of the attribute to be added. |
[in] | attr_value_len | The length (in bytes) of the value. |
void xcm_attr_map_add_bool | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | bool | +attr_value | +
+ | ) | ++ |
Associate a key with a boolean value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The boolean value of the attribute to be added. |
void xcm_attr_map_add_int64 | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | int64_t | +attr_value | +
+ | ) | ++ |
Associate a key with a 64-bit signed integer value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The integer value of the attribute to be added. |
void xcm_attr_map_add_str | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | const char * | +attr_value | +
+ | ) | ++ |
Associate a key with a string value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The string value of the attribute to be added. |
const void * xcm_attr_map_get | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | enum xcm_attr_type * | +attr_type, | +
+ | + | size_t * | +attr_value_len | +
+ | ) | ++ |
Retrieve the value associated with a particular key.
+This function retrieves the attribute value, value type and value length of the attribute attr_name
, in case it exists.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
[out] | attr_type | A pointer to a buffer where the value type will be stored, or NULL. |
[out] | attr_value_len | A pointer to a buffer where the length (in bytes) of the value will be stored, or NULL. |
const bool * xcm_attr_map_get_bool | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the boolean value associated with a particular key.
+This function retrieves the boolean attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_bool.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
const int64_t * xcm_attr_map_get_int64 | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the integer value associated with a particular key.
+This function retrieves the 64-bit signed integer attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_int64.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
const char * xcm_attr_map_get_str | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the string value associated with a particular key.
+This function retrieves the NUL-terminated string attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_str.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
bool xcm_attr_map_exists | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Check if an attribute named attr_name
exists in the attribute map.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute. |
void xcm_attr_map_del | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Removes an attribute from the attribute map.
+This function deletes the attribute attr_name
, in case it exists.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be deleted. |
size_t xcm_attr_map_size | +( | +const struct xcm_attr_map * | +attr_map | ) | ++ |
Returns the number of attributes in the attribute map.
+[in] | attr_map | The attribute map instance. |
attr_map
. void xcm_attr_map_foreach | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | xcm_attr_map_foreach_cb | +cb, | +
+ | + | void * | +user | +
+ | ) | ++ |
Iterates over all attributes in a map.
+This function calls the supplied callback function cb
for each attribute in attr_map
.
The map may not be modified during iteration.
+[in] | attr_map | The attribute map instance. |
[in] | cb | The callback function. |
[in] | user | An opaque pointer, supplied back to the application in every cb call. |
bool xcm_attr_map_equal | +( | +const struct xcm_attr_map * | +attr_map_a, | +
+ | + | const struct xcm_attr_map * | +attr_map_b | +
+ | ) | ++ |
Compares two attribute maps for equality (by value).
+[in] | attr_map_a | An attribute map instance. |
[in] | attr_map_b | An attribute map instance. |
attr_map_a
and attr_map_a
are equal, false otherwise. void xcm_attr_map_destroy | +( | +struct xcm_attr_map * | +attr_map | ) | ++ |
Destroys an attribute map instance.
+This function destroys the attribute map instance and frees all the resources associated with it.
+[in] | attr_map | The attribute map instance, or NULL. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains type definitions for the XCM attribute access API. +More...
+ +Go to the source code of this file.
++Enumerations | |
enum | xcm_attr_type { xcm_attr_type_bool = 1 +, xcm_attr_type_int64 = 2 +, xcm_attr_type_str = 3 +, xcm_attr_type_bin = 4 + } |
This file contains type definitions for the XCM attribute access API.
+enum xcm_attr_type | +
Enumeration representing the different attribute value types.
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains obsolete parts of the XCM core API. +More...
+ +Go to the source code of this file.
++Macros | |
#define | XCM_FD_READABLE (1<<0) |
#define | XCM_FD_WRITABLE (1<<1) |
#define | XCM_FD_EXCEPTION (1<<2) |
+Functions | |
int | xcm_want (struct xcm_socket *socket, int condition, int *fds, int *events, size_t capacity) |
This file contains obsolete parts of the XCM core API.
+It should not be included directly, but rather only via <xcm.h>.
+#define XCM_FD_READABLE (1<<0) | +
Flag bit denoting a readable fd event in xcm_want().
+ +#define XCM_FD_WRITABLE (1<<1) | +
Flag bit denoting a writable fd event.
+ +#define XCM_FD_EXCEPTION (1<<2) | +
Flag bit denoting a exception fd event.
+ +int xcm_want | +( | +struct xcm_socket * | +socket, | +
+ | + | int | +condition, | +
+ | + | int * | +fds, | +
+ | + | int * | +events, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Query the socket what events on which file descriptors it's waiting for.
+Please note: this function is obsolete, replaced by xcm_fd() and xcm_await().
+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.
+With xcm_want(), the application will inform the XCM socket what condition it's waiting for (i.e. what XCM operation it wants to perform), and in return the XCM socket will provide a set of file descriptors and, for each fd, information on what type of event on that fd it require to make progress. Progress can mean both progress toward the goal of reaching the application's desired socket condition, or finishing any outstanding task the XCM socket has.
+In case any of the conditions the application is asking for are believed to be already met, the xcm_want() call will return 0.
+In case the XCM socket has no outstanding tasks, and the application is not asking for any operation that the XCM socket believes it can't immediate fulfill, the call will return 0.
+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.
+Note that XCM may ask the application to wait for the connection's fd or fds to become writable, even if the application is waiting to receive a message. It may also ask the application to wait for the connection's fd to become readable, even if the application is attemting to send a messaging. For the quirks of xcm_want(), see io_waiting.
+Even though the conditions for a particular connection socket are met (fd is becoming writable, for example), there's no guarantee that the xcm_send() or xcm_receive() won't block (or in case of non-blocking mode, won't fail and set EAGAIN).
+The XCM socket fds may only be used with select(). Supplying this fd to any other OS calls (such as setsockopt(2), read(2) etc) is prohibited.
+The information received on which fd to use, and what events on that fd are relevant for the connection socket in its current state, are only valid until more xcm_* calls are made on this socket. See Finishing Outstanding Tasks for more information.
+The fd is an positive integer, unique within this process.
+The condition parameter is a bitmask, with the bits being XCM_SO_RECEIVABLE, XCM_SO_SENDABLE, and/or XCM_SO_ACCEPTABLE. If no bits are set, the application is not interested in anything beyond this XCM socket to finish any outstanding task.
+Each element in the events array is an int used as a bitmask. The bitmask at position N in the events array represents the file descriptor events the XCM transport is waiting for, for fd at position N in the fds array. The bits are XCM_FD_READABLE, XCM_FD_WRITABLE and/or XCM_FD_EXCEPTION. At least one bit is always set.
+If a socket is waiting for multiple events (for example, both readable and writable on the same fd, or readable on one fd, and writeable on another), the condition is met whenever any of the events occur (as oppose to all events).
+[in] | socket | The XCM socket. |
[in] | condition | The condition the application is waiting for. |
[out] | fds | An user-supplied array to store the fds. |
[out] | events | An user-supplied array of int to store the bitmask of each of the fds in the fds array. |
[in] | capacity | The length of the fds and events arrays. |
errno | Description |
---|---|
EOVERFLOW | The user-supplied buffer was too small to fit the socket's fds. |
EINVAL | The socket is not in blocking mode, or the condition bits are invalid. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains functions and macros to retrieve XCM version information. The library (i.e., implementation) version uses the semver convention. +More...
+ +Go to the source code of this file.
++Macros | |
#define | XCM_VERSION_MAJOR 1 |
#define | XCM_VERSION_MINOR 5 |
#define | XCM_VERSION_PATCH 0 |
#define | XCM_VERSION "1.5.0" |
#define | XCM_VERSION_API_MAJOR 0 |
#define | XCM_VERSION_API_MINOR 20 |
#define | XCM_VERSION_API "0.20" |
+Functions | |
unsigned int | xcm_version_major (void) |
unsigned int | xcm_version_minor (void) |
unsigned int | xcm_version_patch (void) |
const char * | xcm_version (void) |
unsigned int | xcm_version_api_major (void) |
unsigned int | xcm_version_api_minor (void) |
const char * | xcm_version_api (void) |
This file contains functions and macros to retrieve XCM version information. The library (i.e., implementation) version uses the semver convention.
+#define XCM_VERSION_MAJOR 1 | +
The XCM library major version.
+ +#define XCM_VERSION_MINOR 5 | +
The XCM library minor version.
+ +#define XCM_VERSION_PATCH 0 | +
The XCM library patch version.
+ +#define XCM_VERSION "1.5.0" | +
The complete XCM library version in string format.
+ +#define XCM_VERSION_API_MAJOR 0 | +
The XCM API/ABI major version this library version implements.
+ +#define XCM_VERSION_API_MINOR 20 | +
The XCM API/ABI minor version this library version implements.
+ +#define XCM_VERSION_API "0.20" | +
The complete XCM API version in string format.
+ +unsigned int xcm_version_major | +( | +void | +) | ++ |
Retrieves the library major version.
+This function returns the implementation major version of the library used at run time.
+ +unsigned int xcm_version_minor | +( | +void | +) | ++ |
Retrieves the library minor version.
+This function returns the implementation minor version of the library used at run time.
+ +unsigned int xcm_version_patch | +( | +void | +) | ++ |
Retrieves the library patch version.
+This function returns the implementation patch version of the library used at run time.
+ +const char * xcm_version | +( | +void | +) | ++ |
Retrieves the library version as a string.
+This function returns the version of the library used at run time, in string format.
+The string returned is statically allocated, and thus must not be free'd by the caller.
+ +unsigned int xcm_version_api_major | +( | +void | +) | ++ |
Retrieves the XCM API major version.
+This function returns the API major version of the library used at run time adheres to.
+ +unsigned int xcm_version_api_minor | +( | +void | +) | ++ |
Retrieves the XCM API minor version.
+This function returns the API minor version of the library used at run time adheres to.
+ +const char * xcm_version_api | +( | +void | +) | ++ |
Retrieves the library API version as a string.
+This function returns the API version of the library used at run time adheres to.
+The string returned is statically allocated, and thus must not be free'd by the caller.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
Cxcm_addr_host | |
Cxcm_addr_ip |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Files | |
xcm.h | |
This file contains the core Extensible Connection-oriented Messaging (XCM) API. | |
xcm_addr.h | |
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses. | |
xcm_attr.h | |
This file contains the XCM attribute access API. See Socket Attributes for an overview. | |
xcm_attr_types.h | |
This file contains type definitions for the XCM attribute access API. | |
xcm_compat.h | |
This file contains obsolete parts of the XCM core API. | |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
▼ include | |
xcm.h | This file contains the core Extensible Connection-oriented Messaging (XCM) API |
xcm_addr.h | This is an API for building and parsing Connection-oriented Messaging (XCM) addresses |
xcm_attr.h | This file contains the XCM attribute access API. See Socket Attributes for an overview |
xcm_attr_types.h | This file contains type definitions for the XCM attribute access API |
xcm_compat.h | This file contains obsolete parts of the XCM core API |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Macros | |
#define | XCM_VERSION_API_MAJOR 0 |
#define | XCM_VERSION_API_MINOR 22 |
#define | XCM_VERSION_API "0.22" |
#define XCM_VERSION_API_MAJOR 0 | +
The XCM API/ABI major version this library version implements.
+ +#define XCM_VERSION_API_MINOR 22 | +
The XCM API/ABI minor version this library version implements.
+ +#define XCM_VERSION_API "0.22" | +
The complete XCM API version in string format.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Macros | |
#define | XCM_VERSION_MAJOR 1 |
#define | XCM_VERSION_MINOR 7 |
#define | XCM_VERSION_PATCH 0 |
#define | XCM_VERSION "1.7.0" |
#define XCM_VERSION_MAJOR 1 | +
The XCM library major version.
+ +#define XCM_VERSION_MINOR 7 | +
The XCM library minor version.
+ +#define XCM_VERSION_PATCH 0 | +
The XCM library patch version.
+ +#define XCM_VERSION "1.7.0" | +
The complete XCM library version in string format.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This is the documentation for the Extensible Connection-oriented Messaging (XCM) programming APIs.
+XCM consists of of three parts; the core API in xcm.h, an address helper library API in xcm_addr.h, and the attribute access API in xcm_attr.h. Obsolete, but still present, functions are available in xcm_compat.h
+The low API/ABI version number is purely a result of all XCM releases being backward compatible, and thus left the major version at 0. It's not to be taken as a sign of immaturity. The API and its implementation have been stable for years.
+XCM provides a connection-oriented, reliable messaging service with in-order delivery. The design goal is to allow for a straight forward mapping to TCP and TLS, but also supporting efficient inter-process commmunication (IPC) mechanisms for local communication.
+XCM reuses much of the terminology of the BSD Sockets API. Unlike the BSD Socket API, XCM has uniform semantics across all underlying transports.
+XCM has a client-server model. A server creates a server socket (with xcm_server()) bound to a specific address (in case of TCP or TLS, a TCP port on a particular IP interface), after which clients may initiate connections to the server. On a successful attempt, two connection sockets will be created; one on the server side (returned from xcm_accept()), and one of the client side (returned from xcm_connect()). Thus, a server serving multiple clients will have multiple sockets; one server socket and N connection sockets, one each for every client. A client will typically have one connection socket for each server it is connected to.
+Messages are always sent and received on a particular connection socket (and never on a server socket).
+In-order delivery - that messages arrive at the recipient in the same order they were sent by the sender side - is guaranteed, but only for messages sent on the same connection.
+XCM transports support flow control. Thus, if the sender message rate or bandwidth is higher than the network or the receiver can handle on a particular connection, xcm_send() in the sender process will eventually block (or return an error EAGAIN, if in non-blocking mode). Unless XCM is used for bulk data transfer (as oppose to signaling traffic), xcm_send() blocking because of slow network or a slow receiver should be rare indeed in practice. TCP, TLS, and UNIX domain socket transports all have large enough windows and socket buffers to allow a large amount of outstanding data.
+In XCM, the application is in control of which transport will be used, with the address supplied to xcm_connect() and xcm_server() including both the transport name and the transport address.
+However, there is nothing preventing a XCM transport to use a more an abstract addressing format, and internally include multiple "physical" IPC transport options. This model is used by the UTLS Transport.
+Addresses are represented as strings with the following general syntax: <transport-name>:<transport-address>
For the UX UNIX Domain Socket transport, the addresses has this more specific form:
+
The addresses of the UXF UNIX Domain Socket transport variant follow the following format:
+
For the TCP, TLS, UTLS and SCTP transports the syntax is:
+
'*' is a shorthand for '0.0.0.0' (i.e. bind to all IPv4 interfaces). '[*]' is the IPv6 equivalent, creating a server socket accepting connections on all IPv4 and IPv6 addresses.
+For example:
For TCP, TLS, UTLS and SCTP server socket addresses, the port can be set to 0, in which case XCM (or rather, the Linux kernel) will allocate a free TCP port.
+For transports allowing a DNS domain name as a part of the address, the transport will attempt resoĺv the name to an IP address. A DNS domain name may resolv to zero or more IPv4 addresses and/or zero or more IPv6 addresses. XCM relies on the operating system to prioritize between IPv4 and IPv6.
+XCM accepts IPv4 addresses in the dotted-decimal format
XCM allows only complete addresses with three '.', and not the archaic, classful, forms, where some bytes where left out, and thus the address contained fewer separators.
+XCM transports attempts to detect a number of conditions which can lead to lost connectivity, and does so even on idle connections.
+If the remote end closes the connection, the local xcm_receive() will return 0. If the process on the remote end crashed, xcm_receive() will return -1 and set errno ECONNRESET. If network connectivity to the remote end is lost, xcm_receive() will return -1 and errno will be set to ETIMEDOUT.
+In general, XCM follow the UNIX system API tradition when it comes to error handling. Where possible, errors are signaled to the application by using unused parts of the value range of the function return type. For functions returning signed integer types, this means the value of -1 (in case -1 is not a valid return value). For functions returning pointers, NULL is used to signal that an error has occurred. For functions where neither -1 or NULL can be used, or where the function does not return anything (side-effect only functions), an 'int' is used as the return type, and is used purely for the purpose to signal success (value 0), or an error (-1) to the application.
+The actual error code is stored in the thread-local errno variable. The error codes are those from the fixed set of errno values defined by POSIX, found in errno.h. Standard functions such as perror() and strerror() may be used to turn the code into a human-readable string.
+In non-blocking operation, given the fact the actual transmission might be defered (and the message buffered in the XCM layer), and that message receive processing might happen before the application has called receive, the error being signaled at the point of a certain XCM call might not be a direct result of the requested operation, but rather an error discovered previously.
+The documentation for xcm_finish() includes a list of generic error codes, applicable xcm_connect(), xcm_accept(), xcm_send() and xcm_receive().
+Also, for errors resulting in an unusable connection, repeated calls will produce the same errno.
+In UNIX-style event-driven programming, a single application thread handles multiple clients (and thus multiple XCM connection sockets) and the task of accepting new clients on the XCM server socket concurrently (although not in parallel). To wait for events from multiple sources, an I/O multiplexing facility such as select(2), poll(2) or epoll(2) is used.
+Each XCM socket is represented by a single fd, retrieved with xcm_fd(). The fd number and underlying file object is stable across the life-time of the socket.
+On BSD Sockets, the socket fd being readable means it's likely that the application can successfully read data from the socket. Similarily, a fd marked writable by, for example, poll() means that the application is likely to be able to write data to the BSD Sockets fd. For an application using XCM going into select(), it must always wait for all the fds its XCM sockets to become readable (e.g. being in the readfds
in the select() call), regardless what are their target conditions. Thus, even if the application is waiting for an opportunity to try to send a message on a XCM socket, or it doesn't want to do anything with the socket, it must wait for the socket fd to become readable. Not wanting to do nothing here means that the application has the xcm_await() condition
set to 0, and is neither interested in waiting to call xcm_send(), xcm_receive(), nor xcm_accept() on the socket. An application may never leave a XCM socket unattended in the sense its fd is not in the set of fds passed to select() and/or xcm_send(), xcm_receive(), xcm_accept() or xcm_finish() are not called.
XCM is oblivious to what I/O multiplexing mechanism employed by the application. It may call select(), poll() or epoll_wait() directly, or make use of any of the many available event loop libraries (such as libevent). For simplicity, select() is used in this documentation to denote the whole family of Linux I/O multiplexing facilities.
+An event-driven application needs to set the XCM sockets it handles into non-blocking mode, by calling xcm_set_blocking() or setting the XCM_NONBLOCK flag in xcm_connect().
+For XCM sockets in non-blocking mode, all potentially blocking API calls related to XCM connections - xcm_connect(), xcm_accept(), xcm_send(), and xcm_receive() - finish immediately.
+For xcm_send(), xcm_connect() and xcm_accept(), XCM signaling success means that the XCM layer has accepted the request. It may or may not have completed the operation.
+In case the XCM_NONBLOCK flag is set in the xcm_connect() call, or in case the a XCM server socket is in non-blocking mode at the time of a xcm_accept() call, the newly created XCM connection returned to the application may be in a semi-operational state, with some internal processing and/or signaling with the remote peer still required before actual message transmission and reception may occur.
+The application may attempt to send or receive messages on such semi-operational connections.
+There are ways for an application to determine when connection establishment or the task of accepting a new client have completed. See Finishing Outstanding Tasks for more information.
+To receive a message on a XCM connection socket in non-blocking mode, the application may need to wait for the right conditions to arise (i.e. a message being available). The application needs to inform the socket that it wants to receive by calling xcm_await() with the XCM_SO_RECEIVABLE
bit in the condition
bit mask set. It will pass the fd it received from xcm_fd() into select(), asking to get notified when the fd becomes readable. When select() marks the socket fd as readable, the application should issue xcm_receive() to attempt to retrieve a message.
xcm_receive() may also called on speculation, prior to any select() call, to poll the socket for incoming messages.
+A XCM connection socket may have a number of messages buffered, and applications should generally, for optimal performance, repeat xcm_receive() until it returns an error, and errno is set to EAGAIN.
+Similarly to receiving a message, an application may set the XCM_SO_SENDABLE
bit in the condition
bit mask, if it wants to wait for a socket state where it's likely it can successfully send a message. When select() marks the socket fd as readable, the application should attempt to send a message.
Just like with xcm_receive(), it may also choose to issue a xcm_send() call on speculation (i.e. without going into select()), which is often a good idea for performance reasons.
+For send operations on non-blocking connection sockets, XCM may buffer whole or part of the message before transmission to the lower layer. This may be due to socket output buffer underrun, or the need for some in-band signaling, like cryptographic key exchange, to happen before the transmission of the complete message may finish. The XCM layer will (re-)attempt to hand the message over to the lower layer at a future call to xcm_finish(), xcm_send(), or xcm_receive().
+For applications wishing to determine when all buffered messages have successfully be deliver to the lower layer, they may use xcm_finish() to do so. Normally, applications aren't expected to require this kind of control. Please also note that the fact a message has left the XCM layer doesn't necessarily mean it has successfully been delivered to the recipient.
+xcm_connect(), xcm_accept(), xcm_send() may all leave the socket in a state where work is initiated, but not completed. In addition, the socket may have pending internal tasks, such flushing the output buffer into the TCP/IP stack, processing XCM control interface messages, or finishing the TLS hand shake procedure.
+After waking up from a select() call, where a particular XCM non-blocking socket's fd is marked readable, the application must, if no xcm_send(), xcm_receive() or xcm_accept() calls are to be made, call xcm_finish(). This is to allow the socket to finish any outstanding tasks, even in the case the application has no immediate plans for the socket.
+Prior to changing a socket from non-blocking to blocking mode, any outstanding tasks should be finished, or otherwise the switch might cause xcm_set_blocking() to return -1 and set errno to EAGAIN.
+For example, if a server socket's desired condition has been set (with xcm_await()) to XCM_SO_ACCEPTABLE
, and the application wakes up from select() with the socket's fd marked readable, a call to xcm_accept() may still not produce a new connection socket.
The same holds true when reaching XCM_SO_RECEIVABLE
and a xcm_receive() call is made, and XCM_SO_SENDABLE
and calls to xcm_send().
In this example, the application connects and tries to send a message, before knowing if the connection is actually established. This may fail (for example, in case TCP and/or TLS-level connection establishement has not yet been completed), in which case the application will fall back and wait with the use of xcm_await(), xcm_fd() and select().
+In case the application wants to know when the connection establishment has finished, it may use xcm_finish() to do so, like in the below example sequence.
+While connecting to a server socket, the client's connection attempt may be refused immediately.
+In many cases, the application is handed a connection socket before the connection establishment is completed. Any errors occuring during this process is handed over to the application at the next XCM call; would it be xcm_finish(), xcm_send() or xcm_receive().
+In this example the application flushes any internal XCM buffers before shutting down the connection, to ensure that any buffered messages are delivered to the lower layer.
+In this sequence, a server accepts a new connection, and continues to attempt to receive a message on this connection, while still, concurrently, is ready to accept more clients on the server socket.
+Tied to an XCM server or connection socket is a set of read-only key-value pairs known as attributes. Which attributes are available varies across different transports, and different socket types.
+The attribute names are strings, and follows a hierarchical naming schema. For example, all generic XCM attributes, expected to be implemented by all transports, have the prefix "xcm.". Transport-specific attributes are prefixed with the transport or protocol name (e.g. "tcp." for TCP-specific attributes applicable to the TLS and TCP transports).
+The attribute value is coded in the native C data types and byte order. Strings are NUL-terminated, and the NUL character is included in the length of the attribute. There are three value types; a boolean type, a 64-bit signed integer type and a string type. See xcm_attr_types.h for details.
+The attribute access API is in xcm_attr.h.
+Retrieving an integer attribute may look like this (minus error handling):
Process-wide and/or read/write attributes may be supported in the future.
+These attributes are expected to be found on XCM sockets regardless of transport type.
+For TCP transport-specific attributes, see TCP Socket Attributes, and for TLS, see TLS Socket Attributes.
+Attribute Name | Socket Type | Value Type | Description |
---|---|---|---|
xcm.type | All | String | The socket type - "server" or "connection". |
xcm.transport | All | String | The transport type. |
xcm.local_addr | All | String | See xcm_local_addr(). |
xcm.remote_addr | Connection | String | See xcm_remote_addr(). |
xcm.max_msg_size | Connection | Integer | The maximum size of any message transported by this connection. |
XCM has a set of generic message counters, which keeps track of the number of messages crossing a certain boundary for a particular connection, and a sum of their size.
+Some of the message and byte counter attributes use the concept of a "lower layer". What this means depends on the transport. For the UX And TCP transports, it is the Linux kernel. For example, for TCP, if the xcm.to_lower_msgs is incremented, it means that XCM has successfully sent the complete message to the kernel's networking stack for further processing. It does not means it has reached the receiving process. It may have, but it also may be sitting on the local or remote socket buffer, on a NIC queue, or be in-transmit in the network. For TLS, the lower layer is OpenSSL.
+All the "xcm.*_bytes" counters count the length of the XCM message payload (as in the length field in xcm_send()), and thus does not include any underlying headers.
+The message counters only count messages succesfully sent and/or received.
+Attribute Name | Socket Type | Value Type | Description |
---|---|---|---|
xcm.from_app_msgs | Connection | Integer | Messages sent from the application and accepted into XCM. |
xcm.from_app_bytes | Connection | Integer | The sum of the size of all messages counted by xcm.from_app_msgs. |
xcm.to_app_msgs | Connection | Integer | Messages delivered from XCM to the application. |
xcm.to_app_bytes | Connection | Integer | The sum of the size of all messages counter by xcm.to_app_msgs. |
xcm.from_lower_msgs | Connection | Integer | Messages received by XCM from the lower layer. |
xcm.from_lower_bytes | Connection | Integer | The sum of the size of all messages counted by xcm.from_lower_msgs. |
xcm.to_lower_msgs | Connection | Integer | Messages successfully sent by XCM into the lower layer. |
xcm.to_lower_bytes | Connection | Integer | The sum of the size of all messages counted by xcm.to_lower_msgs. |
XCM includes a control interface, which allows iteration over the OS instance's XCM server and connection sockets (for processes with the appropriate permissions), and access to their attributes (see Socket Attributes).
+The control interface is optional by means of build-time configuration.
+For each XCM server or connection socket, there is a corresponding UNIX domain socket which is used for control signaling (i.e. state retrieval).
+By default, the control interface's UNIX domain sockets are stored in the /run/xcm/ctl
directory.
This directory needs to be created prior to running any XCM applications (for the control interface to worker properly) and should be writable for all XCM users.
+A particular process using XCM may be configured to use a non-default directory for storing the UNIX domain sockets used for the control interface by means of setting the XCM_CTL
variable. Please note that using this setting will cause the XCM connections to be not visible globally on the OS instance (unless all other XCM-using processes also are using this non-default directory).
Generally, since the application is left unaware (from an API perspective) from the existence of the control interface, errors are not reported up to the application. They are however logged.
+Application threads owning XCM sockets, but which are busy with non-XCM processing for a long duration of time, or otherwise are leaving their XCM sockets unattended to (in violation of XCM API contract), will not respond on the control interface's UNIX domain sockets (corresponding to their XCM sockets). Only the prescence of these sockets may be detected, but their state cannot be retrieved.
+Internally, the XCM implementation has control interface client library, but this library's API is not public at this point.
+XCM includes a command-line program xcmctl
which uses the Control API to iterate of the system's current XCM sockets, and allow access (primarily for debugging purposes) to the sockets' attributes.
Unlike BSD sockets, a XCM socket may not be shared among different threads without synchronization external to XCM. With proper external serialization, a socket may be shared by different threads in the same process, although it might provide difficult in practice since a thread in a blocking XCM function will continue to hold the lock, and thus preventing other threads from accessing the socket at all.
+For non-blocking sockets, threads sharing a socket need to agree on what is the appropriate socket condition
to wait for. When this condition is met, all threads are woken up, returning from select().
It is safe to "give away" a XCM socket from one thread to another, provided the appropriate memory fences are used.
+These limitations (compared to BSD Sockets) are in place to allow socket state outside the kernel (which is required for TCP framing and TLS).
+Sharing a XCM socket between threads in different processes is not possible.
+After a fork() call, either of the two process (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 not call any other XCM API call than xcm_cleanup(), which frees local memory tied to this socket in the non-owner's process address space, without impacting the connection state in the owner process.
+The core XCM API functions are oblivious to the transports used. However, the support for building, and parsing addresses are available only for a set of pre-defined set of transports. There is nothing preventing xcm_addr.h from being extended, and also nothing prevents an alternative XCM implementation to include more transports without extending the address helper API.
+The UX transport uses UNIX Domain (AF_UNIX, also known as AF_LOCAL) Sockets.
+UX sockets may only be used with the same OS instance (or, more specifically, between processes in the same Linux kernel network namespace).
+UNIX Domain Sockets comes in a number of flavors, and XCM uses the SOCK_SEQPACKET variety. SOCK_SEQPACKET sockets are connection-oriented, preserves message boundaries and delivers messages in the same order they were sent; perfectly matching XCM semantics and provides for an near-trivial mapping.
+UX is the most efficient of the XCM transports.
+The standard UNIX Domain Sockets as defined by POSIX uses the file system as its namespace, with the sockets also being files. However, for simplicity and to avoid situations where stale socket files (originating from crashed processes) causing problems, the UX transport uses a Linux-specific extension, allowing a private UNIX Domain Socket namespace. This is known as the abstract namespace (see the unix(7) man page for details). With the abstract namespace, server socket address allocation has the same life time as TCP ports (i.e. if the process dies, the address is free'd).
+The UX transport enables the SO_PASSCRED BSD socket option, to give the remote peer a name (which UNIX domain connection socket doesn't have by default). This is for debugging and observability purposes. Without a remote peer name, in server processes with multiple incoming connections to the same server socket, it's difficult to say which of the server-side connection sockets goes to which remote peer. The kernel-generated, unique, name is an integer in the form "%05x" (printf format). Applications using hardcoded UX addresses should avoid such names by, for example, using a prefix.
+The UTLS Transport also indirectly uses the UX namespace, so care should be taken to avoid any clashes between UX and UTLS sockets in the same network namespace.
+The UXF transport is identical to the UX transport, only it uses the standard POSIX naming mechanism. The name of a server socket is a file system path, and the socket is also a file.
+The UXF sockets resides in a file system namespace, as opposed to UX sockets, which live in a network namespace.
+Upon xcm_close(), the socket will be closed and the file removed. If an application crashes or otherwise fails to run xcm_close(), it will leave a file in the file system pointing toward a non-existing socket. This file will prevent the creation another server socket with the same name.
+The TCP transport uses the Transmission Control Protocol (TCP), by means of the BSD Sockets API.
+TCP is a byte-stream service, but the XCM TCP transport adds framing on top of the stream. A single-field 32-bit header containing the message length in network byte order is added to every message.
+TCP uses TCP Keepalive to detect lost network connectivity between the peers.
+The TCP transport supports IPv4 and IPv6.
+Since XCM is designed for signaling traffic, the TCP transport disables the Nagle algorithm of TCP to avoid its excessive latency.
+The TCP attributes are retrieved from the kernel (struct tcp_info in linux/tcp.h). See the tcp(7) manual page, and its section on the TCP_INFO socket option.
+Attribute Name | Socket Type | Value Type | Description |
---|---|---|---|
tcp.rtt | Connection | Integer | The current TCP round-trip estimate (in us). |
tcp.total_retrans | Connection | Integer | The total number of retransmitted TCP segments. |
tcp.segs_in | Connection | Integer | The total number of segments received. |
tcp.segs_out | Connection | Integer | The total number of segments sent. |
tcp.segs_in
and tcp.segs_out
are only present when running XCM on Linux kernel 4.2 or later.The TLS transport uses TLS to provide a secure, private, two-way authenticated transport.
+TLS is a byte-stream service, but the XCM TLS transport adds framing in the same manner as does the XCM TCP transport.
+The TLS transport supports IPv4 and IPv6.
+The TLS transport disables the Nagle algorithm of TCP.
+The TLS transport expect the certificate, trust chain and private key files to be found in a file system directory - the certificate directory. The default path are configured at build-time, but can be overriden on a per-process basis by means of a UNIX environment variable. The current value of XCM_TLS_CERT
(at the time of xcm_connect() or xcm_accept()) determines the certificate directory used for that connection.
In case the files in the certificate directory are modified, the new versions of the files will be used by new connections. The TLS transports works with differences between set of files, and thus the new generation of files need not nesserarily be newer (i.e. higher mtime).
+The certificate directory must be updated in an atomic manner, or XCM may end up using the certificate file from one generation of files and the key file from another. One way of achieving an atomic update is to have the certificate directory being a symbolic link to the directory where the actual files are located. Upon update, a new directory is created and populated, and the old symbolic link is replace with a new one in an atomic manner (i.e. with rename(2)). It's legal to switch back-and-forth between two sets of files, but the time between the back and the forth switch (assuming the atomicity-by-symlink method is used) must be enough to result in different file system modification times on the symbolic link (usually ~10 ms).
+The TLS transport will, at the time of XCM socket creation (xcm_connect() or xcm_server()), look up the process' current network namespace. In case the namespace is given a name per the iproute2 methods and conventions, XCM will retrieve this name and use it in the certificate and key lookup.
+In the certificate directory, the TLS transport expects the certificate to follow the below naming convention (where <ns> is the namespace):
The private key is stored in:
The trust chain is stored in:
For the default namespace (or any other network namespace not named according to iproute2 standards), the certificate need to be stored in a file "cert.pem", the private key in "key.pem" and the trust chain in "tc.pem".
+In case the certificate, key or trust chain files are not in place (for a particular namespace), a xcm_server() call will return an error and set errno to EPROTO. The application may choose to retry at a later time.
+TLS has all the TCP-level attributes of the TCP transport; see TCP Socket Attributes.
+Attribute Name | Socket Type | Value Type | Description |
---|---|---|---|
tls.peer_subject_key_id | Connection | String | The X509v3 Subject Key Identifier of the remote peer, or a zero-length string in case the TLS connection is not established. |
The UTLS transport provides a hybrid transport, utilizing both the TLS and UX transports internally for actual connection establishment and message delivery.
+On the client side, at the time of xcm_connect(), the UTLS transport determines if the server socket can be reached by using the UX transport (i.e. if the server socket is located on the same OS instance, in the same network namespace). If not, UTLS will attempt to reach the server by means of the TLS transport.
+For a particular UTLS connection, either TLS or UX is used (never both). XCM connections to a particular UTLS server socket may be a mix of the two different types.
+For an UTLS server socket with the address utls:<ip>:<port>
, two underlying addresses will be allocated; tls:<ip>:<port>
and ux:<ip>:<port>
.
Or, in the case DNS is used: tls:<hostname>:<port>
and ux:<hostname>:<port>
.
A wildcard should never be used when creating a UTLS server socket.
+If a DNS hostname is used in place of the IP address, both the client and server need employ DNS, and also agree upon which hostname to use (in case there are several pointing at the same IP address).
+Failure to adhere to the above two rules will prevent a client from finding a local server. Such a client will instead establish a TLS connection to the server.
+The SCTP transport uses the Stream Control Transmission Protocol (SCTP). SCTP provides a reliable, message-oriented service. In-order delivery is optional, and to adhere to XCM semantics (and for other reasons) XCM leaves SCTP in-order delivery enabled.
+The SCTP transport utilizes the native Linux kernel's implementation of SCTP, via the BSD Socket API. The operating mode is such that there is a 1:1-mapping between an association and a socket (fd).
+The SCTP transport supports IPv4 and IPv6.
+To minimize latency, the SCTP transport disables the Nagle algorithm.
+Namespaces is a Linux kernel facility concept for creating multiple, independent namespaces for kernel resources of a certain kind.
+Linux Network Namespaces will affect all transports, including the UX transport.
+XCM has no explicit namespace support, but the application is rather expected to use the Linux kernel facilities for this functionality (i.e. switch to the right namespace before xcm_server() och xcm_connect()).
+In case the system follows the iproute2 conventions in regards to network namespace naming, the TLS and UTLS transports support per-network namespace TLS certificates and private keys.
+XCM, in its current form, does not support binding to a local socket before doing connect() - something that is possible with BSD Sockets, but very rarely makes sense.
+XCM also doesn't have a sendmmsg() or recvmmsg() equivalent. Those could easily be added, and would provide some major performance improvements for applications that are sending or receiving multiple messages on the same connection on the same time. *mmsg() equivalents have been left out because there are strong doubts there are such applications.
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
#include <xcm_addr.h>
+Data Fields | ||
enum xcm_addr_type | type | |
union { | ||
+ struct xcm_addr_ip ip | ||
+ char name [254] | ||
}; | ||
Hostname or IPv4/IPv6 address data type.
+enum xcm_addr_type xcm_addr_host::type | +
Type tag
+ +union { ... } xcm_addr_host | +
Union containing the actual hostname, IPv4 or IPv6 address bytes
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
#include <xcm_addr.h>
+Data Fields | ||
sa_family_t | family | |
union { | ||
in_addr_t ip4 | ||
uint8_t ip6 [16] | ||
} | addr | |
IPv4 or IPv6 address data type.
+sa_family_t xcm_addr_ip::family | +
Type tag; AF_INET or AF_INET6
+ +in_addr_t xcm_addr_ip::ip4 | +
Contains the IPv4 address in network byte order (in case family is set to AF_INET).
+ +uint8_t xcm_addr_ip::ip6[16] | +
Contains the IPv6 address (in case family is set to AF_INET6).
+ +union { ... } xcm_addr_ip::addr | +
Union containing the actual IPv4 or a IPv6 address bytes
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
Library Version | |
API Version |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the core Extensible Connection-oriented Messaging (XCM) API. +More...
+ +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_server (const char *local_addr) |
int | xcm_close (struct xcm_socket *socket) |
void | xcm_cleanup (struct xcm_socket *socket) |
struct xcm_socket * | xcm_accept (struct xcm_socket *server_socket) |
int | xcm_send (struct xcm_socket *conn_socket, const void *buf, size_t len) |
int | xcm_receive (struct xcm_socket *conn_socket, void *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) |
This file contains the core Extensible Connection-oriented Messaging (XCM) API.
+#define XCM_NONBLOCK (1<<0) | +
Flag used in xcm_connect()
+ +#define XCM_SO_RECEIVABLE (1<<0) | +
Flag bit denoting a socket where the application likely can receive a message.
+ +#define XCM_SO_SENDABLE (1<<1) | +
Flag bit denoting a socket where the application likely can send a message.
+ +#define XCM_SO_ACCEPTABLE (1<<2) | +
Flag bit denoting a socket with a pending incoming connection.
+ +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).
+[in] | remote_addr | The remote address which to connect. |
[in] | flags | Either 0, or XCM_NONBLOCK for a non-blocking connect. |
errno | Description |
---|---|
EINVAL | Invalid address format. |
ENOPROTOOPT | Transport protocol not available. |
EMFILE | The limit on the total number of open fds has been reached. |
ENOENT | DNS domain name resolution failed. |
See xcm_finish() for other possible errno values.
+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), a xcm_server() call also includes a blocking name resolution (e.g. gethostbyname()).
+[in] | local_addr | The local address to which this socket should be bound. |
errno | Description |
---|---|
EACCESS | Permission to create the socket is denied. |
EADDRINUSE | Local socket address is already in use. |
ENOMEM | Insufficient memory. |
EINVAL | Invalid address format. |
ENOPROTOOPT | Transport protocol not available. |
EMFILE | The limit on the total number of open fds has been reached. |
EPROTO | A protocol error occured. |
ENOENT | DNS domain name resolution failed. |
int xcm_close | +( | +struct xcm_socket * | +socket | ) | ++ |
Close an endpoint.
+This function close a 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.
+[in] | socket | The socket to be closed, or NULL (in case xcm_close() is a no-operation). |
void xcm_cleanup | +( | +struct xcm_socket * | +socket | ) | ++ |
Cleans up any local resources tied to a 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().
+[in] | socket | The socket which local resources are to be freed, or NULL (in case xcm_cleanup() is a no-operation). |
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.
+[in] | server_socket | The server socket on which to attempt to accept one pending connection. |
errno | Description |
---|---|
EMFILE | The limit on the total number of open fds has been reached. |
See xcm_finish() for other possible errno values.
+ +int xcm_send | +( | +struct xcm_socket * | +conn_socket, | +
+ | + | const void * | +buf, | +
+ | + | size_t | +len | +
+ | ) | ++ |
Send message on a particular connection.
+The xcm_send() function is used to send a message out on a connection socket. A XCM connection goes from a client to a server, and this connection socket may represent either one of the two endpoints.
+[in] | conn_socket | The connection socket the message will be sent on. |
[in] | buf | A pointer to the message data buffer. |
[in] | len | The length of the message in bytes. Zero-length messages are not allowed. |
errno | Description |
---|---|
EMSGSIZE | Message is too large. See also Generic Attributes. |
See xcm_finish() for more errno values.
+ +int xcm_receive | +( | +struct xcm_socket * | +conn_socket, | +
+ | + | void * | +buf, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Receive message on a particular connection.
+The xcm_receive() function is used to receive message on a connection socket. A XCM connection goes from a client to a server, and this connection socket may represent either one of the two endpoints.
+If 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).
+[in] | conn_socket | The connection socket the message will receive be on. |
[out] | buf | The user-supplied buffer where the incoming message will be stored. |
[in] | capacity | The capacity in bytes of the buffer. |
See xcm_finish() for possible errno values.
+ +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.
+[in] | socket | The XCM socket. |
[in] | condition | The condition the application is waiting for. |
errno | Description |
---|---|
EINVAL | The socket is not in non-blocking mode, or the condition bits are invalid. |
int xcm_fd | +( | +struct xcm_socket * | +socket | ) | ++ |
Returns XCM socket fd.
+This call retrieves the XCM socket fd for a XCM socket 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.
+Please 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.
[in] | socket | The connection or server socket. |
errno | Description |
---|---|
EINVAL | The socket is not in non-blocking mode. |
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, xcm_accept() or xcm_send() call on a connection socket in non-blocking mode, wishing to finish outstanding processing related to that operation, 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.
+[in] | socket | The connection or server socket. |
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. |
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.
+[in] | socket | The socket. |
[in] | should_block | Set to true for blocking operation, false for non-blocking mode. |
errno | Description |
---|---|
EAGAIN | The connection socket has unfinished work that needs to completed before mode can be switched. |
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.
+[in] | socket | The socket. |
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.
+[in] | conn_socket | The connection socket. |
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.
+[in] | socket | A server or connection socket. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses. +More...
+#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <errno.h>
#include <xcm_addr_compat.h>
Go to the source code of this file.
++Data Structures | |
struct | xcm_addr_ip |
struct | xcm_addr_host |
+Macros | |
#define | XCM_UTLS_PROTO "utls" |
#define | XCM_TLS_PROTO "tls" |
#define | XCM_TCP_PROTO "tcp" |
#define | XCM_SCTP_PROTO "sctp" |
#define | XCM_UX_PROTO "ux" |
#define | XCM_UXF_PROTO "uxf" |
+Enumerations | |
enum | xcm_addr_type { xcm_addr_type_name +, xcm_addr_type_ip + } |
+Functions | |
int | xcm_addr_parse_proto (const char *addr_s, char *proto, size_t capacity) |
int | xcm_addr_parse_utls (const char *utls_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_tls (const char *tls_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_tcp (const char *tcp_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_sctp (const char *sctp_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_ux (const char *ux_addr_s, char *ux_path, size_t capacity) |
int | xcm_addr_parse_uxf (const char *uxf_addr_s, char *uxf_path, size_t capacity) |
int | xcm_addr_make_utls (const struct xcm_addr_host *host, unsigned short port, char *utls_addr_s, size_t capacity) |
int | xcm_addr_make_tls (const struct xcm_addr_host *host, unsigned short port, char *tls_addr_s, size_t capacity) |
int | xcm_addr_make_tcp (const struct xcm_addr_host *host, unsigned short port, char *tcp_addr_s, size_t capacity) |
int | xcm_addr_make_sctp (const struct xcm_addr_host *host, unsigned short port, char *sctp_addr_s, size_t capacity) |
int | xcm_addr_make_ux (const char *ux_name, char *ux_addr_s, size_t capacity) |
int | xcm_addr_make_uxf (const char *uxf_name, char *uxf_addr_s, size_t capacity) |
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses.
+#define XCM_UTLS_PROTO "utls" | +
Protocol string for the combined TLS+UX transport.
+ +#define XCM_TLS_PROTO "tls" | +
Protocol string for the Transport Layer Security (TLS) transport.
+ +#define XCM_TCP_PROTO "tcp" | +
Protocol string for the TCP transport.
+ +#define XCM_SCTP_PROTO "sctp" | +
Protocol string for the SCTP transport.
+ +#define XCM_UX_PROTO "ux" | +
Protocol string for the UNIX Domain socket (AF_UNIX SEQPACKET) transport (using the abstract namespace).
+ +#define XCM_UXF_PROTO "uxf" | +
Protocol string for the UNIX Domain socket (AF_UNIX SEQPACKET) transport (using file system-based naming).
+ +int xcm_addr_parse_proto | +( | +const char * | +addr_s, | +
+ | + | char * | +proto, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses the protocol part of a XCM address.
+[in] | addr_s | The XCM address string. |
[out] | proto | The buffer where to store the protocol part of the address. |
[in] | capacity | The buffer length in bytes. |
errno | Description |
---|---|
EINVAL | Malformed address. |
ENAMETOOLONG | The user-supplied buffer is too small to fit the protocol. |
int xcm_addr_parse_utls | +( | +const char * | +utls_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a UTLS XCM address.
+[in] | utls_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TLS port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_tls | +( | +const char * | +tls_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a TLS XCM address.
+[in] | tls_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TLS port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_tcp | +( | +const char * | +tcp_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a TCP XCM address.
+[in] | tcp_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TCP port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_sctp | +( | +const char * | +sctp_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parse a SCTP XCM address.
+[in] | sctp_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The SCTP port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_ux | +( | +const char * | +ux_addr_s, | +
+ | + | char * | +ux_path, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses an UX (UNIX Domain Socket) XCM address.
+[in] | ux_addr_s | The string to sparse. |
[out] | ux_path | The UNIX (NUL-terminated) abstract name portion of the UX address. |
[in] | capacity | The length of the user-supplied path buffer. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_uxf | +( | +const char * | +uxf_addr_s, | +
+ | + | char * | +uxf_path, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses an UXF (UNIX Domain Socket) XCM address.
+[in] | uxf_addr_s | The string to sparse. |
[out] | uxf_path | The UNIX (NUL-terminated) path name portion of the UXF address. |
[in] | capacity | The length of the user-supplied path buffer. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_make_utls | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +utls_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a UTLS XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | utls_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_tls | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +tls_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a TLS XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | tls_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_tcp | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +tcp_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a TCP XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | tcp_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_sctp | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +sctp_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a SCTP XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | sctp_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_ux | +( | +const char * | +ux_name, | +
+ | + | char * | +ux_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds an UX XCM address string from the supplied UNIX Domain Socket name.
+[in] | ux_name | The UNIX Domain Socket name. |
[out] | ux_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid format of or too long UNIX Domain Socket address. |
int xcm_addr_make_uxf | +( | +const char * | +uxf_name, | +
+ | + | char * | +uxf_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds an UXF XCM address string from the supplied file system path.
+[in] | uxf_name | The UNIX Domain path. |
[out] | uxf_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid format of or too long UNIX Domain Socket address. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the XCM attribute access API. See Socket Attributes for an overview. +More...
+ +Go to the source code of this file.
++Typedefs | |
typedef void(* | xcm_attr_cb) (const char *attr_name, enum xcm_attr_type type, void *value, size_t value_len, void *cb_data) |
+Functions | |
int | xcm_attr_get (struct xcm_socket *socket, const char *name, enum xcm_attr_type *type, void *value, size_t capacity) |
void | xcm_attr_get_all (struct xcm_socket *socket, xcm_attr_cb cb, void *cb_data) |
This file contains the XCM attribute access API. See Socket Attributes for an overview.
+typedef void(* xcm_attr_cb) (const char *attr_name, enum xcm_attr_type type, void *value, size_t value_len, void *cb_data) | +
The signature of the user-supplied callback used in xcm_attr_get_all().
+ +int xcm_attr_get | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | enum xcm_attr_type * | +type, | +
+ | + | void * | +value, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Retrieves the value of a XCM socket attribute.
+For a list of available attributes for different socket and transport types, see Generic Attributes, TCP Socket Attributes and TLS Socket Attributes.
+For a description of the C types and buffer capacity requirements of the attribute types, see xcm_attr_types.h.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[out] | type | A pointer to a location where the type of the attribute will be stored. May be left to NULL, in case the type is known a priori. |
[out] | value | A user-supplied buffer where the value of the attribute will be stored. |
[in] | capacity | The length of the buffer (in bytes). |
errno | Description |
---|---|
ENOENT | The attribute does not exist. |
EOVERFLOW | The user-supplied buffer was too small to fit the value. |
void xcm_attr_get_all | +( | +struct xcm_socket * | +socket, | +
+ | + | xcm_attr_cb | +cb, | +
+ | + | void * | +cb_data | +
+ | ) | ++ |
Retrieves all XCM socket attributes.
+This function retrieves all available attribute names, types and their current values on a particular connection or server socket.
+The memory locations refered to by the attr_name and attr_value pointers is only guaranteed to be valid for the execution of the callback. If needed later, they need to be copied.
+[in] | socket | The connection or server socket. |
[in] | cb | The function to be called for every attribute on the socket. |
[in] | cb_data | An opaque (for XCM) pointer returned back to the application in the callback. cb_data may be NULL. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the XCM attribute map API. +More...
+ +Go to the source code of this file.
++Typedefs | |
typedef void(* | xcm_attr_map_foreach_cb) (const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len, void *user) |
+Functions | |
struct xcm_attr_map * | xcm_attr_map_create (void) |
struct xcm_attr_map * | xcm_attr_map_clone (const struct xcm_attr_map *original) |
void | xcm_attr_map_add (struct xcm_attr_map *attr_map, const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len) |
void | xcm_attr_map_add_bool (struct xcm_attr_map *attr_map, const char *attr_name, bool attr_value) |
void | xcm_attr_map_add_int64 (struct xcm_attr_map *attr_map, const char *attr_name, int64_t attr_value) |
void | xcm_attr_map_add_str (struct xcm_attr_map *attr_map, const char *attr_name, const char *attr_value) |
const void * | xcm_attr_map_get (const struct xcm_attr_map *attr_map, const char *attr_name, enum xcm_attr_type *attr_type, size_t *attr_value_len) |
const bool * | xcm_attr_map_get_bool (const struct xcm_attr_map *attr_map, const char *attr_name) |
const int64_t * | xcm_attr_map_get_int64 (const struct xcm_attr_map *attr_map, const char *attr_name) |
const char * | xcm_attr_map_get_str (const struct xcm_attr_map *attr_map, const char *attr_name) |
bool | xcm_attr_map_exists (const struct xcm_attr_map *attr_map, const char *attr_name) |
void | xcm_attr_map_del (struct xcm_attr_map *attr_map, const char *attr_name) |
size_t | xcm_attr_map_size (const struct xcm_attr_map *attr_map) |
void | xcm_attr_map_foreach (const struct xcm_attr_map *attr_map, xcm_attr_map_foreach_cb cb, void *user) |
bool | xcm_attr_map_equal (const struct xcm_attr_map *attr_map_a, const struct xcm_attr_map *attr_map_b) |
void | xcm_attr_map_destroy (struct xcm_attr_map *attr_map) |
This file contains the XCM attribute map API.
+A XCM attribute map is a set of key-value pairs. The key is an attribute name in the form of a string. One key maps to at most one value. The attribute value is either a boolean, a signed 64-bit integer, a string, or a variable-length binary object.
+typedef void(* xcm_attr_map_foreach_cb) (const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len, void *user) | +
Callback function prototype used for iteration.
+ +struct xcm_attr_map * xcm_attr_map_create | +( | +void | +) | ++ |
Create an attribute map instance.
+struct xcm_attr_map * xcm_attr_map_clone | +( | +const struct xcm_attr_map * | +original | ) | ++ |
Create a copy of an attribute map instance.
+[in] | attr_map | The original attribute map instance, to be copied. |
void xcm_attr_map_add | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | enum xcm_attr_type | +attr_type, | +
+ | + | const void * | +attr_value, | +
+ | + | size_t | +attr_value_len | +
+ | ) | ++ |
Associate a key with a value.
+This function associates the attribute key attr_name
to the attribute value attr_value
in the attribute map attr_map
. If the key attr_name
already exists, its value is replaced.
Both the key and the value will be copied, and thus attr_name
and attr_value
will still be owned by the caller at call completion.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_type | The type of the value to be added. |
[in] | attr_value | The value of the attribute to be added. |
[in] | attr_value_len | The length (in bytes) of the value. |
void xcm_attr_map_add_bool | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | bool | +attr_value | +
+ | ) | ++ |
Associate a key with a boolean value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The boolean value of the attribute to be added. |
void xcm_attr_map_add_int64 | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | int64_t | +attr_value | +
+ | ) | ++ |
Associate a key with a 64-bit signed integer value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The integer value of the attribute to be added. |
void xcm_attr_map_add_str | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | const char * | +attr_value | +
+ | ) | ++ |
Associate a key with a string value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The string value of the attribute to be added. |
const void * xcm_attr_map_get | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | enum xcm_attr_type * | +attr_type, | +
+ | + | size_t * | +attr_value_len | +
+ | ) | ++ |
Retrieve the value associated with a particular key.
+This function retrieves the attribute value, value type and value length of the attribute attr_name
, in case it exists.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
[out] | attr_type | A pointer to a buffer where the value type will be stored, or NULL. |
[out] | attr_value_len | A pointer to a buffer where the length (in bytes) of the value will be stored, or NULL. |
const bool * xcm_attr_map_get_bool | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the boolean value associated with a particular key.
+This function retrieves the boolean attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_bool.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
const int64_t * xcm_attr_map_get_int64 | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the integer value associated with a particular key.
+This function retrieves the 64-bit signed integer attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_int64.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
const char * xcm_attr_map_get_str | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the string value associated with a particular key.
+This function retrieves the NUL-terminated string attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_str.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
bool xcm_attr_map_exists | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Check if an attribute named attr_name
exists in the attribute map.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute. |
void xcm_attr_map_del | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Removes an attribute from the attribute map.
+This function deletes the attribute attr_name
, in case it exists.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be deleted. |
size_t xcm_attr_map_size | +( | +const struct xcm_attr_map * | +attr_map | ) | ++ |
Returns the number of attributes in the attribute map.
+[in] | attr_map | The attribute map instance. |
attr_map
. void xcm_attr_map_foreach | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | xcm_attr_map_foreach_cb | +cb, | +
+ | + | void * | +user | +
+ | ) | ++ |
Iterates over all attributes in a map.
+This function calls the supplied callback function cb
for each attribute in attr_map
.
The map may not be modified during iteration.
+[in] | attr_map | The attribute map instance. |
[in] | cb | The callback function. |
[in] | user | An opaque pointer, supplied back to the application in every cb call. |
bool xcm_attr_map_equal | +( | +const struct xcm_attr_map * | +attr_map_a, | +
+ | + | const struct xcm_attr_map * | +attr_map_b | +
+ | ) | ++ |
Compares two attribute maps for equality (by value).
+[in] | attr_map_a | An attribute map instance. |
[in] | attr_map_b | An attribute map instance. |
attr_map_a
and attr_map_a
are equal, false otherwise. void xcm_attr_map_destroy | +( | +struct xcm_attr_map * | +attr_map | ) | ++ |
Destroys an attribute map instance.
+This function destroys the attribute map instance and frees all the resources associated with it.
+[in] | attr_map | The attribute map instance, or NULL. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains type definitions for the XCM attribute access API. +More...
+ +Go to the source code of this file.
++Enumerations | |
enum | xcm_attr_type { xcm_attr_type_bool = 1 +, xcm_attr_type_int64 = 2 +, xcm_attr_type_str = 3 +, xcm_attr_type_bin = 4 + } |
This file contains type definitions for the XCM attribute access API.
+enum xcm_attr_type | +
Enumeration representing the different attribute value types.
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains obsolete parts of the XCM core API. +More...
+ +Go to the source code of this file.
++Macros | |
#define | XCM_FD_READABLE (1<<0) |
#define | XCM_FD_WRITABLE (1<<1) |
#define | XCM_FD_EXCEPTION (1<<2) |
+Functions | |
int | xcm_want (struct xcm_socket *socket, int condition, int *fds, int *events, size_t capacity) |
This file contains obsolete parts of the XCM core API.
+It should not be included directly, but rather only via <xcm.h>.
+#define XCM_FD_READABLE (1<<0) | +
Flag bit denoting a readable fd event in xcm_want().
+ +#define XCM_FD_WRITABLE (1<<1) | +
Flag bit denoting a writable fd event.
+ +#define XCM_FD_EXCEPTION (1<<2) | +
Flag bit denoting a exception fd event.
+ +int xcm_want | +( | +struct xcm_socket * | +socket, | +
+ | + | int | +condition, | +
+ | + | int * | +fds, | +
+ | + | int * | +events, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Query the socket what events on which file descriptors it's waiting for.
+Please note: this function is obsolete, replaced by xcm_fd() and xcm_await().
+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.
+With xcm_want(), the application will inform the XCM socket what condition it's waiting for (i.e. what XCM operation it wants to perform), and in return the XCM socket will provide a set of file descriptors and, for each fd, information on what type of event on that fd it require to make progress. Progress can mean both progress toward the goal of reaching the application's desired socket condition, or finishing any outstanding task the XCM socket has.
+In case any of the conditions the application is asking for are believed to be already met, the xcm_want() call will return 0.
+In case the XCM socket has no outstanding tasks, and the application is not asking for any operation that the XCM socket believes it can't immediate fulfill, the call will return 0.
+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.
+Note that XCM may ask the application to wait for the connection's fd or fds to become writable, even if the application is waiting to receive a message. It may also ask the application to wait for the connection's fd to become readable, even if the application is attemting to send a messaging. For the quirks of xcm_want(), see io_waiting.
+Even though the conditions for a particular connection socket are met (fd is becoming writable, for example), there's no guarantee that the xcm_send() or xcm_receive() won't block (or in case of non-blocking mode, won't fail and set EAGAIN).
+The XCM socket fds may only be used with select(). Supplying this fd to any other OS calls (such as setsockopt(2), read(2) etc) is prohibited.
+The information received on which fd to use, and what events on that fd are relevant for the connection socket in its current state, are only valid until more xcm_* calls are made on this socket. See Finishing Outstanding Tasks for more information.
+The fd is an positive integer, unique within this process.
+The condition parameter is a bitmask, with the bits being XCM_SO_RECEIVABLE, XCM_SO_SENDABLE, and/or XCM_SO_ACCEPTABLE. If no bits are set, the application is not interested in anything beyond this XCM socket to finish any outstanding task.
+Each element in the events array is an int used as a bitmask. The bitmask at position N in the events array represents the file descriptor events the XCM transport is waiting for, for fd at position N in the fds array. The bits are XCM_FD_READABLE, XCM_FD_WRITABLE and/or XCM_FD_EXCEPTION. At least one bit is always set.
+If a socket is waiting for multiple events (for example, both readable and writable on the same fd, or readable on one fd, and writeable on another), the condition is met whenever any of the events occur (as oppose to all events).
+[in] | socket | The XCM socket. |
[in] | condition | The condition the application is waiting for. |
[out] | fds | An user-supplied array to store the fds. |
[out] | events | An user-supplied array of int to store the bitmask of each of the fds in the fds array. |
[in] | capacity | The length of the fds and events arrays. |
errno | Description |
---|---|
EOVERFLOW | The user-supplied buffer was too small to fit the socket's fds. |
EINVAL | The socket is not in blocking mode, or the condition bits are invalid. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains functions and macros to retrieve XCM version information. The library (i.e., implementation) version uses the semver convention. +More...
+ +Go to the source code of this file.
++Macros | |
#define | XCM_VERSION_MAJOR 1 |
#define | XCM_VERSION_MINOR 5 |
#define | XCM_VERSION_PATCH 0 |
#define | XCM_VERSION "1.5.0" |
#define | XCM_VERSION_API_MAJOR 0 |
#define | XCM_VERSION_API_MINOR 20 |
#define | XCM_VERSION_API "0.20" |
+Functions | |
unsigned int | xcm_version_major (void) |
unsigned int | xcm_version_minor (void) |
unsigned int | xcm_version_patch (void) |
const char * | xcm_version (void) |
unsigned int | xcm_version_api_major (void) |
unsigned int | xcm_version_api_minor (void) |
const char * | xcm_version_api (void) |
This file contains functions and macros to retrieve XCM version information. The library (i.e., implementation) version uses the semver convention.
+#define XCM_VERSION_MAJOR 1 | +
The XCM library major version.
+ +#define XCM_VERSION_MINOR 5 | +
The XCM library minor version.
+ +#define XCM_VERSION_PATCH 0 | +
The XCM library patch version.
+ +#define XCM_VERSION "1.5.0" | +
The complete XCM library version in string format.
+ +#define XCM_VERSION_API_MAJOR 0 | +
The XCM API/ABI major version this library version implements.
+ +#define XCM_VERSION_API_MINOR 20 | +
The XCM API/ABI minor version this library version implements.
+ +#define XCM_VERSION_API "0.20" | +
The complete XCM API version in string format.
+ +unsigned int xcm_version_major | +( | +void | +) | ++ |
Retrieves the library major version.
+This function returns the implementation major version of the library used at run time.
+ +unsigned int xcm_version_minor | +( | +void | +) | ++ |
Retrieves the library minor version.
+This function returns the implementation minor version of the library used at run time.
+ +unsigned int xcm_version_patch | +( | +void | +) | ++ |
Retrieves the library patch version.
+This function returns the implementation patch version of the library used at run time.
+ +const char * xcm_version | +( | +void | +) | ++ |
Retrieves the library version as a string.
+This function returns the version of the library used at run time, in string format.
+The string returned is statically allocated, and thus must not be free'd by the caller.
+ +unsigned int xcm_version_api_major | +( | +void | +) | ++ |
Retrieves the XCM API major version.
+This function returns the API major version of the library used at run time adheres to.
+ +unsigned int xcm_version_api_minor | +( | +void | +) | ++ |
Retrieves the XCM API minor version.
+This function returns the API minor version of the library used at run time adheres to.
+ +const char * xcm_version_api | +( | +void | +) | ++ |
Retrieves the library API version as a string.
+This function returns the API version of the library used at run time adheres to.
+The string returned is statically allocated, and thus must not be free'd by the caller.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
Cxcm_addr_host | |
Cxcm_addr_ip |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Files | |
xcm.h | |
This file contains the core Extensible Connection-oriented Messaging (XCM) API. | |
xcm_addr.h | |
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses. | |
xcm_attr.h | |
This file contains the XCM attribute access API. See Socket Attributes for an overview. | |
xcm_attr_map.h | |
This file contains the XCM attribute map API. | |
xcm_attr_types.h | |
This file contains type definitions for the XCM attribute access API. | |
xcm_compat.h | |
This file contains obsolete parts of the XCM core API. | |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
▼ include | |
xcm.h | This file contains the core Extensible Connection-oriented Messaging (XCM) API |
xcm_addr.h | This is an API for building and parsing Connection-oriented Messaging (XCM) addresses |
xcm_attr.h | This file contains the XCM attribute access API. See Socket Attributes for an overview |
xcm_attr_map.h | This file contains the XCM attribute map API |
xcm_attr_types.h | This file contains type definitions for the XCM attribute access API |
xcm_compat.h | This file contains obsolete parts of the XCM core API |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Macros | |
#define | XCM_VERSION_API_MAJOR 0 |
#define | XCM_VERSION_API_MINOR 22 |
#define | XCM_VERSION_API "0.22" |
#define XCM_VERSION_API_MAJOR 0 | +
The XCM API/ABI major version this library version implements.
+ +#define XCM_VERSION_API_MINOR 22 | +
The XCM API/ABI minor version this library version implements.
+ +#define XCM_VERSION_API "0.22" | +
The complete XCM API version in string format.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Macros | |
#define | XCM_VERSION_MAJOR 1 |
#define | XCM_VERSION_MINOR 7 |
#define | XCM_VERSION_PATCH 0 |
#define | XCM_VERSION "1.7.0" |
#define XCM_VERSION_MAJOR 1 | +
The XCM library major version.
+ +#define XCM_VERSION_MINOR 7 | +
The XCM library minor version.
+ +#define XCM_VERSION_PATCH 0 | +
The XCM library patch version.
+ +#define XCM_VERSION "1.7.0" | +
The complete XCM library version in string format.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This is the documentation for the Extensible Connection-oriented Messaging (XCM) programming APIs.
+XCM consists the core API in xcm.h, an address helper library API in xcm_addr.h, and the attribute APIs in xcm_attr.h and xcm_attr_map.h. Obsolete, but still present, functions are available in xcm_compat.h
+The low API/ABI version number is purely a result of all XCM releases being backward compatible, and thus left the major version at 0. It's not to be taken as a sign of immaturity. The API and its implementation have been stable for years.
+XCM provides a connection-oriented, reliable messaging service with in-order delivery. The design goal is to allow for a straight forward mapping to TCP and TLS, but also supporting efficient inter-process commmunication (IPC) mechanisms for local communication.
+XCM reuses much of the terminology of the BSD Sockets API. Unlike the BSD Socket API, XCM has uniform semantics across all underlying transports.
+XCM has a client-server model. A server creates a server socket (with xcm_server()) bound to a specific address (in case of TCP or TLS, a TCP port on a particular IP interface), after which clients may initiate connections to the server. On a successful attempt, two connection sockets will be created; one on the server side (returned from xcm_accept()), and one of the client side (returned from xcm_connect()). Thus, a server serving multiple clients will have multiple sockets; one server socket and N connection sockets, one each for every client. A client will typically have one connection socket for each server it is connected to.
+Messages are always sent and received on a particular connection socket (and never on a server socket).
+In-order delivery - that messages arrive at the recipient in the same order they were sent by the sender side - is guaranteed, but only for messages sent on the same connection.
+XCM transports support flow control. Thus, if the sender message rate or bandwidth is higher than the network or the receiver can handle on a particular connection, xcm_send() in the sender process will eventually block (or return an error EAGAIN, if in non-blocking mode). Unless XCM is used for bulk data transfer (as oppose to signaling traffic), xcm_send() blocking because of slow network or a slow receiver should be rare indeed in practice. TCP, TLS, and UNIX domain socket transports all have large enough windows and socket buffers to allow a large amount of outstanding data.
+In XCM, the application is in control of which transport will be used, with the address supplied to xcm_connect() and xcm_server() including both the transport name and the transport address.
+However, there is nothing preventing a XCM transport to use a more an abstract addressing format, and internally include multiple "physical" IPC transport options. This model is used by the UTLS Transport.
+Addresses are represented as strings with the following general syntax: <transport-name>:<transport-address>
For the UX UNIX Domain Socket transport, the addresses has this more specific form:
+
The addresses of the UXF UNIX Domain Socket transport variant have the following format:
+
For the TCP, TLS, UTLS and SCTP transports the syntax is:
+
'*' is a shorthand for '0.0.0.0' (i.e. bind to all IPv4 interfaces). '[*]' is the IPv6 equivalent, creating a server socket accepting connections on all IPv4 and IPv6 addresses.
+Some examples addresses:
For TCP, TLS, UTLS and SCTP server socket addresses, the port can be set to 0, in which case XCM (or rather, the Linux kernel) will allocate a free TCP port from the local port range.
+For transports allowing a DNS domain name as a part of the address, the transport will attempt resoĺv the name to an IP address. A DNS domain name may resolv to zero or more IPv4 addresses and/or zero or more IPv6 addresses. XCM relies on the operating system to prioritize between IPv4 and IPv6.
+XCM accepts IPv4 addresses in the dotted-decimal format
XCM allows only complete addresses with three '.', and not the archaic, classful, forms, where some bytes where left out, and thus the address contained fewer separators.
+XCM transports attempt to detect a number of conditions which can lead to lost connectivity, and does so even on idle connections.
+If the remote end closes the connection, the local xcm_receive() will return 0. If the process on the remote end crashed, xcm_receive() will return -1 and set errno ECONNRESET. If network connectivity to the remote end is lost, xcm_receive() will return -1 and errno will be set to ETIMEDOUT.
+In general, XCM follow the UNIX system API tradition when it comes to error handling. Where possible, errors are signaled to the application by using unused parts of the value range of the function return type. For functions returning signed integer types, this means the value of -1 (in case -1 is not a valid return value). For functions returning pointers, NULL is used to signal that an error has occurred. For functions where neither -1 or NULL can be used, or where the function does not return anything (side-effect only functions), an 'int' is used as the return type, and is used purely for the purpose to signal success (value 0), or an error (-1) to the application.
+The actual error code is stored in the thread-local errno variable. The error codes are those from the fixed set of errno values defined by POSIX, found in errno.h. Standard functions such as perror() and strerror() may be used to turn the code into a human-readable string.
+In non-blocking operation, given the fact the actual transmission might be defered (and the message buffered in the XCM layer), and that message receive processing might happen before the application has called receive, the error being signaled at the point of a certain XCM call might not be a direct result of the requested operation, but rather an error discovered previously.
+The documentation for xcm_finish() includes a list of generic error codes, applicable xcm_connect(), xcm_accept(), xcm_send() and xcm_receive().
+Also, for errors resulting in an unusable connection, repeated calls will produce the same errno.
+In UNIX-style event-driven programming, a single application thread handles multiple clients (and thus multiple XCM connection sockets) and the task of accepting new clients on the XCM server socket concurrently (although not in parallel). To wait for events from multiple sources, an I/O multiplexing facility such as select(2), poll(2) or epoll(2) is used.
+Each XCM socket is represented by a single fd, retrieved with xcm_fd(). The fd number and underlying file object is stable across the life-time of the socket.
+On BSD Sockets, the socket fd being readable means it's likely that the application can successfully read data from the socket. Similarily, a fd marked writable by, for example, poll() means that the application is likely to be able to write data to the BSD Sockets fd. For an application using XCM going into select(), it must always wait for all the fds its XCM sockets to become readable (e.g. being in the readfds
in the select() call), regardless what are their target conditions. Thus, even if the application is waiting for an opportunity to try to send a message on a XCM socket, or it doesn't want to do anything with the socket, it must wait for the socket fd to become readable. Not wanting to do nothing here means that the application has the xcm_await() condition
set to 0, and is neither interested in waiting to call xcm_send(), xcm_receive(), nor xcm_accept() on the socket. An application may never leave a XCM socket unattended in the sense its fd is not in the set of fds passed to select() and/or xcm_send(), xcm_receive(), xcm_accept() or xcm_finish() are not called.
XCM is oblivious to what I/O multiplexing mechanism employed by the application. It may call select(), poll() or epoll_wait() directly, or make use of any of the many available event loop libraries (such as libevent). For simplicity, select() is used in this documentation to denote the whole family of Linux I/O multiplexing facilities.
+An event-driven application needs to set the XCM sockets it handles into non-blocking mode, by calling xcm_set_blocking(), setting the "xcm.blocking" socket attribute, or using the XCM_NONBLOCK flag in xcm_connect().
+For XCM sockets in non-blocking mode, all potentially blocking API calls related to XCM connections - xcm_connect(), xcm_accept(), xcm_send(), and xcm_receive() - finish immediately.
+For xcm_send(), xcm_connect() and xcm_accept(), XCM signaling success means that the XCM layer has accepted the request. It may or may not have completed the operation.
+In case the XCM_NONBLOCK flag is set in the xcm_connect() call, or in case the a XCM server socket is in non-blocking mode at the time of a xcm_accept() call, the newly created XCM connection returned to the application may be in a semi-operational state, with some internal processing and/or signaling with the remote peer still required before actual message transmission and reception may occur.
+The application may attempt to send or receive messages on such semi-operational connections.
+There are ways for an application to determine when connection establishment or the task of accepting a new client have completed. See Finishing Outstanding Tasks for more information.
+To receive a message on a XCM connection socket in non-blocking mode, the application may need to wait for the right conditions to arise (i.e. a message being available). The application needs to inform the socket that it wants to receive by calling xcm_await() with the XCM_SO_RECEIVABLE
bit in the condition
bit mask set. It will pass the fd it received from xcm_fd() into select(), asking to get notified when the fd becomes readable. When select() marks the socket fd as readable, the application should issue xcm_receive() to attempt to retrieve a message.
xcm_receive() may also called on speculation, prior to any select() call, to poll the socket for incoming messages.
+A XCM connection socket may have a number of messages buffered, and applications should generally, for optimal performance, repeat xcm_receive() until it returns an error, and errno is set to EAGAIN.
+Similarly to receiving a message, an application may set the XCM_SO_SENDABLE
bit in the condition
bit mask, if it wants to wait for a socket state where it's likely it can successfully send a message. When select() marks the socket fd as readable, the application should attempt to send a message.
Just like with xcm_receive(), it may also choose to issue a xcm_send() call on speculation (i.e. without going into select()), which is often a good idea for performance reasons.
+For send operations on non-blocking connection sockets, XCM may buffer whole or part of the message before transmission to the lower layer. This may be due to socket output buffer underrun, or the need for some in-band signaling, like cryptographic key exchange, to happen before the transmission of the complete message may finish. The XCM layer will (re-)attempt to hand the message over to the lower layer at a future call to xcm_finish(), xcm_send(), or xcm_receive().
+For applications wishing to determine when all buffered messages have successfully be deliver to the lower layer, they may use xcm_finish() to do so. Normally, applications aren't expected to require this kind of control. Please also note that the fact a message has left the XCM layer doesn't necessarily mean it has successfully been delivered to the recipient.
+xcm_connect(), xcm_accept(), xcm_send() may all leave the socket in a state where work is initiated, but not completed. In addition, the socket may have pending internal tasks, such flushing the output buffer into the TCP/IP stack, processing XCM control interface messages, or finishing the TLS hand shake procedure.
+After waking up from a select() call, where a particular XCM non-blocking socket's fd is marked readable, the application must, if no xcm_send(), xcm_receive() or xcm_accept() calls are to be made, call xcm_finish(). This is to allow the socket to finish any outstanding tasks, even in the case the application has no immediate plans for the socket.
+Prior to changing a socket from non-blocking to blocking mode, any outstanding tasks should be finished, or otherwise the switch might cause xcm_set_blocking() to return -1 and set errno to EAGAIN.
+For example, if a server socket's desired condition has been set (with xcm_await()) to XCM_SO_ACCEPTABLE
, and the application wakes up from select() with the socket's fd marked readable, a call to xcm_accept() may still not produce a new connection socket.
The same holds true when reaching XCM_SO_RECEIVABLE
and a xcm_receive() call is made, and XCM_SO_SENDABLE
and calls to xcm_send().
In this example, the application connects and tries to send a message, before knowing if the connection is actually established. This may fail (for example, in case TCP and/or TLS-level connection establishement has not yet been completed), in which case the application will fall back and wait with the use of xcm_await(), xcm_fd() and select().
+In case the application wants to know when the connection establishment has finished, it may use xcm_finish() to do so, like in the below example sequence.
+While connecting to a server socket, the client's connection attempt may be refused immediately.
+In many cases, the application is handed a connection socket before the connection establishment is completed. Any errors occuring during this process is handed over to the application at the next XCM call; would it be xcm_finish(), xcm_send() or xcm_receive().
+In this example the application flushes any internal XCM buffers before shutting down the connection, to ensure that any buffered messages are delivered to the lower layer.
+In this sequence, a server accepts a new connection, and continues to attempt to receive a message on this connection, while still, concurrently, is ready to accept more clients on the server socket.
+Tied to an XCM server or connection socket is a set of key-value pairs known as attributes. Which attributes are available varies across different transports, and different socket types.
+An attribute's name is a string, and follows a hierarchical naming schema. For example, all generic XCM attributes, available in all transports, have the prefix "xcm.". Transport-specific attributes are prefixed with the transport or protocol name (e.g. "tcp." for TCP-specific attributes applicable to the TLS and TCP transports).
+An attribute may be read-only, write-only or available both for reading and writing. This is referred to as the attribute's mode. The mode may vary across the lifetime of the socket. For example, an attribute may be writable at the time of the xcm_connect() call, and read-only thereafter.
+The attribute value is coded in the native C data type and byte order. Strings are NUL-terminated, and the NUL character is included in the length of the attribute. There are four value types; a boolean type, a 64-bit signed integer type, a string type and a type for arbitrary binary data. See xcm_attr_types.h for details.
+The attribute access API is in xcm_attr.h.
+Retrieving an integer attribute's value may look like this:
Changing an integer attribyte value may be done in the following manner:
Both of these examples are missing error handling.
+XCM allows supplying a set of writable attributes at the time of socket creation, by using the xcm_connect_a(), xcm_server_a(), or xcm_accept_a() functions.
+The attribute sets are represented by the xcm_attr_map type in xcm_attr_map.h.
+An example:
These attributes are expected to be found on XCM sockets regardless of transport type.
+For TCP transport-specific attributes, see TCP Socket Attributes, and for TLS, see TLS Socket Attributes.
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
xcm.type | All | String | R | The socket type: "server" or "connection". |
xcm.transport | All | String | R | The transport type. |
xcm.local_addr | All | String | RW | The local address of a socket. Writable only if supplied to xcm_connect_a(). |
xcm.blocking | All | Boolean | RW | See xcm_set_blocking() and xcm_is_blocking(). |
xcm.remote_addr | Connection | String | R | See xcm_remote_addr(). |
xcm.max_msg_size | Connection | Integer | R | The maximum size of any message transported by this connection. |
XCM has a set of generic message counters, which keeps track of the number of messages crossing a certain boundary for a particular connection, and a sum of their size.
+Some of the message and byte counter attributes use the concept of a "lower layer". What this means depends on the transport. For the UX And TCP transports, it is the Linux kernel. For example, for TCP, if the xcm.to_lower_msgs is incremented, it means that XCM has successfully sent the complete message to the kernel's networking stack for further processing. It does not means it has reached the receiving process. It may have, but it also may be sitting on the local or remote socket buffer, on a NIC queue, or be in-transmit in the network. For TLS, the lower layer is OpenSSL.
+All the "xcm.*_bytes" counters count the length of the XCM message payload (as in the length field in xcm_send()), and thus does not include any underlying headers.
+The message counters only count messages succesfully sent and/or received.
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
xcm.from_app_msgs | Connection | Integer | R | Messages sent from the application and accepted into XCM. |
xcm.from_app_bytes | Connection | Integer | R | The sum of the size of all messages counted by xcm.from_app_msgs. |
xcm.to_app_msgs | Connection | Integer | R | Messages delivered from XCM to the application. |
xcm.to_app_bytes | Connection | Integer | R | The sum of the size of all messages counter by xcm.to_app_msgs. |
xcm.from_lower_msgs | Connection | Integer | R | Messages received by XCM from the lower layer. |
xcm.from_lower_bytes | Connection | Integer | R | The sum of the size of all messages counted by xcm.from_lower_msgs. |
xcm.to_lower_msgs | Connection | Integer | R | Messages successfully sent by XCM into the lower layer. |
xcm.to_lower_bytes | Connection | Integer | R | The sum of the size of all messages counted by xcm.to_lower_msgs. |
XCM includes a control interface, which allows iteration over the OS instance's XCM server and connection sockets (for processes with the appropriate permissions), and access to their attributes (see Socket Attributes).
+The control interface is optional by means of build-time configuration.
+For each XCM server or connection socket, there is a corresponding UNIX domain socket which is used for control signaling (i.e. state retrieval).
+By default, the control interface's UNIX domain sockets are stored in the /run/xcm/ctl
directory.
This directory needs to be created prior to running any XCM applications (for the control interface to worker properly) and should be writable for all XCM users.
+A particular process using XCM may be configured to use a non-default directory for storing the UNIX domain sockets used for the control interface by means of setting the XCM_CTL
variable. Please note that using this setting will cause the XCM connections to be not visible globally on the OS instance (unless all other XCM-using processes also are using this non-default directory).
Generally, since the application is left unaware (from an API perspective) of the existence of the control interface, errors are not reported up to the application. They are however logged.
+Application threads owning XCM sockets, but which are busy with non-XCM processing for a long duration of time, or otherwise are leaving their XCM sockets unattended to (in violation of XCM API contract), will not respond on the control interface's UNIX domain sockets (corresponding to their XCM sockets). Only the presence of these sockets may be detected, but their state cannot be retrieved.
+Internally, the XCM implementation has control interface client library, but this library's API is not public at this point.
+XCM includes a command-line program xcmctl
which uses the Control API to iterate of the system's current XCM sockets, and allow access (primarily for debugging purposes) to the sockets' attributes.
Unlike BSD sockets, a XCM socket may not be shared among different threads without synchronization external to XCM. With proper external serialization, a socket may be shared by different threads in the same process, although it might provide difficult in practice since a thread in a blocking XCM function will continue to hold the lock, and thus preventing other threads from accessing the socket at all.
+For non-blocking sockets, threads sharing a socket need to agree on what is the appropriate socket condition
to wait for. When this condition is met, all threads are woken up, returning from select().
It is safe to "give away" a XCM socket from one thread to another, provided the appropriate memory fences are used.
+These limitations (compared to BSD Sockets) are in place to allow socket state outside the kernel (which is required for TCP framing and TLS).
+Sharing a XCM socket between threads in different processes is not possible.
+After a fork() call, either of the two process (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 not call any other XCM API call than xcm_cleanup(), which frees local memory tied to this socket in the non-owner's process address space, without impacting the connection state in the owner process.
+The core XCM API functions are oblivious to the transports used. However, the support for building, and parsing addresses are available only for a set of pre-defined set of transports. There is nothing preventing xcm_addr.h from being extended, and also nothing prevents an alternative XCM implementation to include more transports without extending the address helper API.
+The UX transport uses UNIX Domain (AF_UNIX, also known as AF_LOCAL) Sockets.
+UX sockets may only be used with the same OS instance (or, more specifically, between processes in the same Linux kernel network namespace).
+UNIX Domain Sockets comes in a number of flavors, and XCM uses the SOCK_SEQPACKET variety. SOCK_SEQPACKET sockets are connection-oriented, preserves message boundaries and delivers messages in the same order they were sent; perfectly matching XCM semantics and provides for an near-trivial mapping.
+UX is the most efficient of the XCM transports.
+The standard UNIX Domain Sockets as defined by POSIX uses the file system as its namespace, with the sockets also being files. However, for simplicity and to avoid situations where stale socket files (originating from crashed processes) causing problems, the UX transport uses a Linux-specific extension, allowing a private UNIX Domain Socket namespace. This is known as the abstract namespace (see the unix(7) man page for details). With the abstract namespace, server socket address allocation has the same life time as TCP ports (i.e. if the process dies, the address is free'd).
+The UX transport enables the SO_PASSCRED BSD socket option, to give the remote peer a name (which UNIX domain connection socket doesn't have by default). This is for debugging and observability purposes. Without a remote peer name, in server processes with multiple incoming connections to the same server socket, it's difficult to say which of the server-side connection sockets goes to which remote peer. The kernel-generated, unique, name is an integer in the form "%05x" (printf format). Applications using hardcoded UX addresses should avoid such names by, for example, using a prefix.
+The UTLS Transport also indirectly uses the UX namespace, so care should be taken to avoid any clashes between UX and UTLS sockets in the same network namespace.
+The UXF transport is identical to the UX transport, only it uses the standard POSIX naming mechanism. The name of a server socket is a file system path, and the socket is also a file.
+The UXF sockets resides in a file system namespace, as opposed to UX sockets, which live in a network namespace.
+Upon xcm_close(), the socket will be closed and the file removed. If an application crashes or otherwise fails to run xcm_close(), it will leave a file in the file system pointing toward a non-existing socket. This file will prevent the creation another server socket with the same name.
+The TCP transport uses the Transmission Control Protocol (TCP), by means of the BSD Sockets API.
+TCP is a byte-stream service, but the XCM TCP transport adds framing on top of the stream. A single-field 32-bit header containing the message length in network byte order is added to every message.
+TCP uses TCP Keepalive to detect lost network connectivity between the peers.
+The TCP transport supports IPv4 and IPv6.
+Since XCM is designed for signaling traffic, the TCP transport disables the Nagle algorithm of TCP to avoid its excessive latency.
+The TCP attributes are retrieved from the kernel (struct tcp_info in linux/tcp.h). See the tcp(7) manual page, and its section on the TCP_INFO socket option.
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
tcp.rtt | Connection | Integer | R | The current TCP round-trip estimate (in us). |
tcp.total_retrans | Connection | Integer | R | The total number of retransmitted TCP segments. |
tcp.segs_in | Connection | Integer | R | The total number of segments received. |
tcp.segs_out | Connection | Integer | R | The total number of segments sent. |
tcp.segs_in
and tcp.segs_out
are only present when running XCM on Linux kernel 4.2 or later.The TLS transport uses TLS to provide a secure, private, two-way authenticated transport.
+TLS is a byte-stream service, but the XCM TLS transport adds framing in the same manner as does the XCM TCP transport.
+The TLS transport supports IPv4 and IPv6.
+The TLS transport disables the Nagle algorithm of TCP.
+The TLS transport expect the certificate, trust chain and private key files to be found in a file system directory - the certificate directory. The default path are configured at build-time, but can be overriden on a per-process basis by means of a UNIX environment variable. The current value of XCM_TLS_CERT
(at the time of xcm_connect() or xcm_accept()) determines the certificate directory used for that connection.
In case the files in the certificate directory are modified, the new versions of the files will be used by new connections. The TLS transports works with differences between set of files, and thus the new generation of files need not nesserarily be newer (i.e. higher mtime).
+The certificate directory must be updated in an atomic manner, or XCM may end up using the certificate file from one generation of files and the key file from another. One way of achieving an atomic update is to have the certificate directory being a symbolic link to the directory where the actual files are located. Upon update, a new directory is created and populated, and the old symbolic link is replace with a new one in an atomic manner (i.e. with rename(2)). It's legal to switch back-and-forth between two sets of files, but the time between the back and the forth switch (assuming the atomicity-by-symlink method is used) must be enough to result in different file system modification times on the symbolic link (usually ~10 ms).
+The TLS transport will, at the time of XCM socket creation (xcm_connect() or xcm_server()), look up the process' current network namespace. In case the namespace is given a name per the iproute2 methods and conventions, XCM will retrieve this name and use it in the certificate and key lookup.
+In the certificate directory, the TLS transport expects the certificate to follow the below naming convention (where <ns> is the namespace):
The private key is stored in:
The trust chain is stored in:
For the default namespace (or any other network namespace not named according to iproute2 standards), the certificate need to be stored in a file "cert.pem", the private key in "key.pem" and the trust chain in "tc.pem".
+In case the certificate, key or trust chain files are not in place (for a particular namespace), a xcm_server() call will return an error and set errno to EPROTO. The application may choose to retry at a later time.
+TLS has all the TCP-level attributes of the TCP transport; see TCP Socket Attributes.
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
tls.peer_subject_key_id | Connection | String | R | The X509v3 Subject Key Identifier of the remote peer, or a zero-length string in case the TLS connection is not established. |
The UTLS transport provides a hybrid transport, utilizing both the TLS and UX transports internally for actual connection establishment and message delivery.
+On the client side, at the time of xcm_connect(), the UTLS transport determines if the server socket can be reached by using the UX transport (i.e. if the server socket is located on the same OS instance, in the same network namespace). If not, UTLS will attempt to reach the server by means of the TLS transport.
+For a particular UTLS connection, either TLS or UX is used (never both). XCM connections to a particular UTLS server socket may be a mix of the two different types.
+For an UTLS server socket with the address utls:<ip>:<port>
, two underlying addresses will be allocated; tls:<ip>:<port>
and ux:<ip>:<port>
.
Or, in the case DNS is used: tls:<hostname>:<port>
and ux:<hostname>:<port>
.
A wildcard should never be used when creating a UTLS server socket.
+If a DNS hostname is used in place of the IP address, both the client and server need employ DNS, and also agree upon which hostname to use (in case there are several pointing at the same IP address).
+Failure to adhere to the above two rules will prevent a client from finding a local server. Such a client will instead establish a TLS connection to the server.
+The SCTP transport uses the Stream Control Transmission Protocol (SCTP). SCTP provides a reliable, message-oriented service. In-order delivery is optional, but to adhere to XCM semantics (and for other reasons) XCM leaves SCTP in-order delivery enabled.
+The SCTP transport utilizes the native Linux kernel's implementation of SCTP, via the BSD Socket API. The operating mode is such that there is a 1:1-mapping between an association and a socket (fd).
+The SCTP transport supports IPv4 and IPv6.
+To minimize latency, the SCTP transport disables the Nagle algorithm.
+Namespaces is a Linux kernel facility concept for creating multiple, independent namespaces for kernel resources of a certain kind.
+Linux Network Namespaces will affect all transports, including the UX transport.
+XCM has no explicit namespace support. Rather, the application is expected to use the Linux kernel facilities for this functionality (i.e. switch to the right namespace before xcm_server() och xcm_connect()).
+In case the system follows the iproute2 conventions in regards to network namespace naming, the TLS and UTLS transports support per-network namespace TLS certificates and private keys.
+XCM, in its current form, does not support binding to a local socket before doing connect() - something that is possible with BSD Sockets, but very rarely makes sense.
+XCM also doesn't have a sendmmsg() or recvmmsg() equivalent. Those could easily be added, and would provide some major performance improvements for applications that are sending or receiving multiple messages on the same connection on the same time. *mmsg() equivalents have been left out because there are strong doubts there are such applications.
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
#include <xcm_addr.h>
+Data Fields | ||
enum xcm_addr_type | type | |
union { | ||
+ struct xcm_addr_ip ip | ||
+ char name [254] | ||
}; | ||
Hostname or IPv4/IPv6 address data type.
+enum xcm_addr_type xcm_addr_host::type | +
Type tag
+ +union { ... } xcm_addr_host | +
Union containing the actual hostname, IPv4 or IPv6 address bytes
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
#include <xcm_addr.h>
+Data Fields | ||
sa_family_t | family | |
union { | ||
in_addr_t ip4 | ||
uint8_t ip6 [16] | ||
} | addr | |
IPv4 or IPv6 address data type.
+sa_family_t xcm_addr_ip::family | +
Type tag; AF_INET or AF_INET6
+ +in_addr_t xcm_addr_ip::ip4 | +
Contains the IPv4 address in network byte order (in case family is set to AF_INET).
+ +uint8_t xcm_addr_ip::ip6[16] | +
Contains the IPv6 address (in case family is set to AF_INET6).
+ +union { ... } xcm_addr_ip::addr | +
Union containing the actual IPv4 or a IPv6 address bytes
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
Library Version | |
API Version |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the core Extensible Connection-oriented Messaging (XCM) API. +More...
+#include <errno.h>
#include <stdbool.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 *conn_socket, const void *buf, size_t len) |
int | xcm_receive (struct xcm_socket *conn_socket, void *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) |
This file contains the core Extensible Connection-oriented Messaging (XCM) API.
+#define XCM_NONBLOCK (1<<0) | +
Flag used in xcm_connect()
+ +#define XCM_SO_RECEIVABLE (1<<0) | +
Flag bit denoting a socket where the application likely can receive a message.
+ +#define XCM_SO_SENDABLE (1<<1) | +
Flag bit denoting a socket where the application likely can send a message.
+ +#define XCM_SO_ACCEPTABLE (1<<2) | +
Flag bit denoting a socket with a pending incoming connection.
+ +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).
+[in] | remote_addr | The remote address which to connect. |
[in] | flags | Either 0, or XCM_NONBLOCK for a non-blocking connect. |
errno | Description |
---|---|
EINVAL | Invalid address format. |
ENOPROTOOPT | Transport protocol not available. |
EMFILE | The limit on the total number of open fds has been reached. |
ENOENT | DNS domain name resolution failed. |
See xcm_finish() for other possible errno values.
+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.
+[in] | remote_addr | The remote address which to connect. |
[in] | attrs | A set of attributes to be applied to the connection socket, or NULL. |
See xcm_connect() and xcm_attr_set() for possible errno values.
+ +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), a xcm_server() call also includes a blocking name resolution (e.g. gethostbyname()).
+[in] | local_addr | The local address to which this socket should be bound. |
errno | Description |
---|---|
EACCESS | Permission to create the socket is denied. |
EADDRINUSE | Local socket address is already in use. |
ENOMEM | Insufficient memory. |
EINVAL | Invalid address format. |
ENOPROTOOPT | Transport protocol not available. |
EMFILE | The limit on the total number of open fds has been reached. |
EPROTO | A protocol error occured. |
ENOENT | DNS domain name resolution failed. |
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.
+[in] | local_addr | The local address to which this socket should be bound. |
[in] | attrs | A set of attributes to be applied to the socket, or NULL. |
See xcm_server() and xcm_attr_set() for possible errno values.
+ +int xcm_close | +( | +struct xcm_socket * | +socket | ) | ++ |
Close an endpoint.
+This function close a 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.
+[in] | socket | The socket to be closed, or NULL (in case xcm_close() is a no-operation). |
void xcm_cleanup | +( | +struct xcm_socket * | +socket | ) | ++ |
Cleans up any local resources tied to a 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().
+[in] | socket | The socket which local resources are to be freed, or NULL (in case xcm_cleanup() is a no-operation). |
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.
+[in] | server_socket | The server socket on which to attempt to accept one pending connection. |
errno | Description |
---|---|
EMFILE | The limit on the total number of open fds has been reached. |
See xcm_finish() for other possible errno values.
+ +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.
+[in] | server_socket | The server socket on which to attempt to accept one pending connection. |
[in] | attrs | A set of attributes to be applied to the socket, or NULL. |
See xcm_accept() and xcm_attr_set() for possible errno values.
+ +int xcm_send | +( | +struct xcm_socket * | +conn_socket, | +
+ | + | const void * | +buf, | +
+ | + | size_t | +len | +
+ | ) | ++ |
Send message on a particular connection.
+The xcm_send() function is used to send a message out on a connection socket. A XCM connection goes from a client to a server, and this connection socket may represent either one of the two endpoints.
+[in] | conn_socket | The connection socket the message will be sent on. |
[in] | buf | A pointer to the message data buffer. |
[in] | len | The length of the message in bytes. Zero-length messages are not allowed. |
errno | Description |
---|---|
EMSGSIZE | Message is too large. See also Generic Attributes. |
See xcm_finish() for more errno values.
+ +int xcm_receive | +( | +struct xcm_socket * | +conn_socket, | +
+ | + | void * | +buf, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Receive message on a particular connection.
+The xcm_receive() function is used to receive message on a connection socket. A XCM connection goes from a client to a server, and this connection socket may represent either one of the two endpoints.
+If 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).
+[in] | conn_socket | The connection socket the message will receive be on. |
[out] | buf | The user-supplied buffer where the incoming message will be stored. |
[in] | capacity | The capacity in bytes of the buffer. |
See xcm_finish() for possible errno values.
+ +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.
+[in] | socket | The XCM socket. |
[in] | condition | The condition the application is waiting for. |
errno | Description |
---|---|
EINVAL | The socket is not in non-blocking mode, or the condition bits are invalid. |
int xcm_fd | +( | +struct xcm_socket * | +socket | ) | ++ |
Returns XCM socket fd.
+This call retrieves the XCM socket fd for a XCM socket 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.
+Please 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.
[in] | socket | The connection or server socket. |
errno | Description |
---|---|
EINVAL | The socket is not in non-blocking mode. |
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, xcm_accept() or xcm_send() call on a connection socket in non-blocking mode, wishing to finish outstanding processing related to that operation, 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.
+[in] | socket | The connection or server socket. |
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. |
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.
+[in] | socket | The socket. |
[in] | should_block | Set to true for blocking operation, false for non-blocking mode. |
errno | Description |
---|---|
EAGAIN | The connection socket has unfinished work that needs to completed before mode can be switched. |
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.
+[in] | socket | The socket. |
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.
+[in] | conn_socket | The connection socket. |
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.
+[in] | socket | A server or connection socket. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses. +More...
+#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <errno.h>
#include <xcm_addr_compat.h>
Go to the source code of this file.
++Data Structures | |
struct | xcm_addr_ip |
struct | xcm_addr_host |
+Macros | |
#define | XCM_UTLS_PROTO "utls" |
#define | XCM_TLS_PROTO "tls" |
#define | XCM_TCP_PROTO "tcp" |
#define | XCM_SCTP_PROTO "sctp" |
#define | XCM_UX_PROTO "ux" |
#define | XCM_UXF_PROTO "uxf" |
+Enumerations | |
enum | xcm_addr_type { xcm_addr_type_name +, xcm_addr_type_ip + } |
+Functions | |
int | xcm_addr_parse_proto (const char *addr_s, char *proto, size_t capacity) |
int | xcm_addr_parse_utls (const char *utls_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_tls (const char *tls_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_tcp (const char *tcp_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_sctp (const char *sctp_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_ux (const char *ux_addr_s, char *ux_path, size_t capacity) |
int | xcm_addr_parse_uxf (const char *uxf_addr_s, char *uxf_path, size_t capacity) |
int | xcm_addr_make_utls (const struct xcm_addr_host *host, unsigned short port, char *utls_addr_s, size_t capacity) |
int | xcm_addr_make_tls (const struct xcm_addr_host *host, unsigned short port, char *tls_addr_s, size_t capacity) |
int | xcm_addr_make_tcp (const struct xcm_addr_host *host, unsigned short port, char *tcp_addr_s, size_t capacity) |
int | xcm_addr_make_sctp (const struct xcm_addr_host *host, unsigned short port, char *sctp_addr_s, size_t capacity) |
int | xcm_addr_make_ux (const char *ux_name, char *ux_addr_s, size_t capacity) |
int | xcm_addr_make_uxf (const char *uxf_name, char *uxf_addr_s, size_t capacity) |
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses.
+#define XCM_UTLS_PROTO "utls" | +
Protocol string for the combined TLS+UX transport.
+ +#define XCM_TLS_PROTO "tls" | +
Protocol string for the Transport Layer Security (TLS) transport.
+ +#define XCM_TCP_PROTO "tcp" | +
Protocol string for the TCP transport.
+ +#define XCM_SCTP_PROTO "sctp" | +
Protocol string for the SCTP transport.
+ +#define XCM_UX_PROTO "ux" | +
Protocol string for the UNIX Domain socket (AF_UNIX SEQPACKET) transport (using the abstract namespace).
+ +#define XCM_UXF_PROTO "uxf" | +
Protocol string for the UNIX Domain socket (AF_UNIX SEQPACKET) transport (using file system-based naming).
+ +int xcm_addr_parse_proto | +( | +const char * | +addr_s, | +
+ | + | char * | +proto, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses the protocol part of a XCM address.
+[in] | addr_s | The XCM address string. |
[out] | proto | The buffer where to store the protocol part of the address. |
[in] | capacity | The buffer length in bytes. |
errno | Description |
---|---|
EINVAL | Malformed address. |
ENAMETOOLONG | The user-supplied buffer is too small to fit the protocol. |
int xcm_addr_parse_utls | +( | +const char * | +utls_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a UTLS XCM address.
+[in] | utls_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TLS port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_tls | +( | +const char * | +tls_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a TLS XCM address.
+[in] | tls_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TLS port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_tcp | +( | +const char * | +tcp_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a TCP XCM address.
+[in] | tcp_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TCP port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_sctp | +( | +const char * | +sctp_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parse a SCTP XCM address.
+[in] | sctp_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The SCTP port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_ux | +( | +const char * | +ux_addr_s, | +
+ | + | char * | +ux_path, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses an UX (UNIX Domain Socket) XCM address.
+[in] | ux_addr_s | The string to sparse. |
[out] | ux_path | The UNIX (NUL-terminated) abstract name portion of the UX address. |
[in] | capacity | The length of the user-supplied path buffer. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_uxf | +( | +const char * | +uxf_addr_s, | +
+ | + | char * | +uxf_path, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses an UXF (UNIX Domain Socket) XCM address.
+[in] | uxf_addr_s | The string to sparse. |
[out] | uxf_path | The UNIX (NUL-terminated) path name portion of the UXF address. |
[in] | capacity | The length of the user-supplied path buffer. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_make_utls | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +utls_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a UTLS XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | utls_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_tls | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +tls_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a TLS XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | tls_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_tcp | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +tcp_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a TCP XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | tcp_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_sctp | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +sctp_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a SCTP XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | sctp_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_ux | +( | +const char * | +ux_name, | +
+ | + | char * | +ux_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds an UX XCM address string from the supplied UNIX Domain Socket name.
+[in] | ux_name | The UNIX Domain Socket name. |
[out] | ux_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid format of or too long UNIX Domain Socket address. |
int xcm_addr_make_uxf | +( | +const char * | +uxf_name, | +
+ | + | char * | +uxf_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds an UXF XCM address string from the supplied file system path.
+[in] | uxf_name | The UNIX Domain path. |
[out] | uxf_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid format of or too long UNIX Domain Socket address. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the XCM attribute access API. See Socket Attributes for an overview. +More...
+ +Go to the source code of this file.
++Typedefs | |
typedef void(* | xcm_attr_cb) (const char *attr_name, enum xcm_attr_type type, void *value, size_t value_len, void *cb_data) |
+Functions | |
int | xcm_attr_set (struct xcm_socket *s, const char *name, enum xcm_attr_type type, const void *value, size_t len) |
int | xcm_attr_get (struct xcm_socket *s, const char *name, enum xcm_attr_type *type, void *value, size_t capacity) |
void | xcm_attr_get_all (struct xcm_socket *socket, xcm_attr_cb cb, void *cb_data) |
This file contains the XCM attribute access API. See Socket Attributes for an overview.
+typedef void(* xcm_attr_cb) (const char *attr_name, enum xcm_attr_type type, void *value, size_t value_len, void *cb_data) | +
The signature of the user-supplied callback used in xcm_attr_get_all().
+ +int xcm_attr_set | +( | +struct xcm_socket * | +s, | +
+ | + | const char * | +name, | +
+ | + | enum xcm_attr_type | +type, | +
+ | + | const void * | +value, | +
+ | + | size_t | +len | +
+ | ) | ++ |
Sets the value of a XCM socket attribute.
+Only attributes marked as writable may be set. For a list of available attributes for different socket and transport types, see Generic Attributes, TCP Socket Attributes and TLS Socket Attributes.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[in] | type | The value type of the new value. |
[in] | value | The new value. |
[in] | value_len | The length of the value. |
errno | Description |
---|---|
ENOENT | The attribute does not exist. |
EACCES | The attribute exists, but is read-only. |
EINVAL | The attribute name is too long, the attribute value type, value or value length is not valid for the specified attribute. |
int xcm_attr_get | +( | +struct xcm_socket * | +s, | +
+ | + | const char * | +name, | +
+ | + | enum xcm_attr_type * | +type, | +
+ | + | void * | +value, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Retrieves the value of a XCM socket attribute.
+For a list of available attributes for different socket and transport types, see Generic Attributes, TCP Socket Attributes and TLS Socket Attributes.
+For a description of the C types and buffer capacity requirements of the attribute types, see xcm_attr_types.h.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[out] | type | A pointer to a location where the type of the attribute will be stored. May be left to NULL, in case the type is known a priori. |
[out] | value | A user-supplied buffer where the value of the attribute will be stored. |
[in] | capacity | The length of the buffer (in bytes). |
errno | Description |
---|---|
ENOENT | The attribute does not exist. |
EACCES | The attribute exists, but is write-only. |
EOVERFLOW | The user-supplied buffer was too small to fit the value. |
void xcm_attr_get_all | +( | +struct xcm_socket * | +socket, | +
+ | + | xcm_attr_cb | +cb, | +
+ | + | void * | +cb_data | +
+ | ) | ++ |
Retrieves all XCM socket attributes.
+This function retrieves all available attribute names, types and their current values on a particular connection or server socket.
+The memory locations refered to by the attr_name and attr_value pointers is only guaranteed to be valid for the execution of the callback. If needed later, they need to be copied.
+[in] | socket | The connection or server socket. |
[in] | cb | The function to be called for every attribute on the socket. |
[in] | cb_data | An opaque (for XCM) pointer returned back to the application in the callback. cb_data may be NULL. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the XCM attribute map API. +More...
+ +Go to the source code of this file.
++Typedefs | |
typedef void(* | xcm_attr_map_foreach_cb) (const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len, void *user) |
+Functions | |
struct xcm_attr_map * | xcm_attr_map_create (void) |
struct xcm_attr_map * | xcm_attr_map_clone (const struct xcm_attr_map *original) |
void | xcm_attr_map_add (struct xcm_attr_map *attr_map, const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len) |
void | xcm_attr_map_add_bool (struct xcm_attr_map *attr_map, const char *attr_name, bool attr_value) |
void | xcm_attr_map_add_int64 (struct xcm_attr_map *attr_map, const char *attr_name, int64_t attr_value) |
void | xcm_attr_map_add_str (struct xcm_attr_map *attr_map, const char *attr_name, const char *attr_value) |
const void * | xcm_attr_map_get (const struct xcm_attr_map *attr_map, const char *attr_name, enum xcm_attr_type *attr_type, size_t *attr_value_len) |
const bool * | xcm_attr_map_get_bool (const struct xcm_attr_map *attr_map, const char *attr_name) |
const int64_t * | xcm_attr_map_get_int64 (const struct xcm_attr_map *attr_map, const char *attr_name) |
const char * | xcm_attr_map_get_str (const struct xcm_attr_map *attr_map, const char *attr_name) |
bool | xcm_attr_map_exists (const struct xcm_attr_map *attr_map, const char *attr_name) |
void | xcm_attr_map_del (struct xcm_attr_map *attr_map, const char *attr_name) |
size_t | xcm_attr_map_size (const struct xcm_attr_map *attr_map) |
void | xcm_attr_map_foreach (const struct xcm_attr_map *attr_map, xcm_attr_map_foreach_cb cb, void *user) |
bool | xcm_attr_map_equal (const struct xcm_attr_map *attr_map_a, const struct xcm_attr_map *attr_map_b) |
void | xcm_attr_map_destroy (struct xcm_attr_map *attr_map) |
This file contains the XCM attribute map API.
+A XCM attribute map is a set of key-value pairs. The key is an attribute name in the form of a string. One key maps to at most one value. The attribute value is either a boolean, a signed 64-bit integer, a string, or a variable-length binary object.
+typedef void(* xcm_attr_map_foreach_cb) (const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len, void *user) | +
Callback function prototype used for iteration.
+ +struct xcm_attr_map * xcm_attr_map_create | +( | +void | +) | ++ |
Create an attribute map instance.
+struct xcm_attr_map * xcm_attr_map_clone | +( | +const struct xcm_attr_map * | +original | ) | ++ |
Create a copy of an attribute map instance.
+[in] | attr_map | The original attribute map instance, to be copied. |
void xcm_attr_map_add | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | enum xcm_attr_type | +attr_type, | +
+ | + | const void * | +attr_value, | +
+ | + | size_t | +attr_value_len | +
+ | ) | ++ |
Associate a key with a value.
+This function associates the attribute key attr_name
to the attribute value attr_value
in the attribute map attr_map
. If the key attr_name
already exists, its value is replaced.
Both the key and the value will be copied, and thus attr_name
and attr_value
will still be owned by the caller at call completion.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_type | The type of the value to be added. |
[in] | attr_value | The value of the attribute to be added. |
[in] | attr_value_len | The length (in bytes) of the value. |
void xcm_attr_map_add_bool | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | bool | +attr_value | +
+ | ) | ++ |
Associate a key with a boolean value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The boolean value of the attribute to be added. |
void xcm_attr_map_add_int64 | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | int64_t | +attr_value | +
+ | ) | ++ |
Associate a key with a 64-bit signed integer value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The integer value of the attribute to be added. |
void xcm_attr_map_add_str | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | const char * | +attr_value | +
+ | ) | ++ |
Associate a key with a string value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The string value of the attribute to be added. |
const void * xcm_attr_map_get | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | enum xcm_attr_type * | +attr_type, | +
+ | + | size_t * | +attr_value_len | +
+ | ) | ++ |
Retrieve the value associated with a particular key.
+This function retrieves the attribute value, value type and value length of the attribute attr_name
, in case it exists.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
[out] | attr_type | A pointer to a buffer where the value type will be stored, or NULL. |
[out] | attr_value_len | A pointer to a buffer where the length (in bytes) of the value will be stored, or NULL. |
const bool * xcm_attr_map_get_bool | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the boolean value associated with a particular key.
+This function retrieves the boolean attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_bool.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
const int64_t * xcm_attr_map_get_int64 | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the integer value associated with a particular key.
+This function retrieves the 64-bit signed integer attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_int64.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
const char * xcm_attr_map_get_str | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the string value associated with a particular key.
+This function retrieves the NUL-terminated string attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_str.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
bool xcm_attr_map_exists | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Check if an attribute named attr_name
exists in the attribute map.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute. |
void xcm_attr_map_del | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Removes an attribute from the attribute map.
+This function deletes the attribute attr_name
, in case it exists.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be deleted. |
size_t xcm_attr_map_size | +( | +const struct xcm_attr_map * | +attr_map | ) | ++ |
Returns the number of attributes in the attribute map.
+[in] | attr_map | The attribute map instance. |
attr_map
. void xcm_attr_map_foreach | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | xcm_attr_map_foreach_cb | +cb, | +
+ | + | void * | +user | +
+ | ) | ++ |
Iterates over all attributes in a map.
+This function calls the supplied callback function cb
for each attribute in attr_map
.
The map may not be modified during iteration.
+[in] | attr_map | The attribute map instance. |
[in] | cb | The callback function. |
[in] | user | An opaque pointer, supplied back to the application in every cb call. |
bool xcm_attr_map_equal | +( | +const struct xcm_attr_map * | +attr_map_a, | +
+ | + | const struct xcm_attr_map * | +attr_map_b | +
+ | ) | ++ |
Compares two attribute maps for equality (by value).
+[in] | attr_map_a | An attribute map instance. |
[in] | attr_map_b | An attribute map instance. |
attr_map_a
and attr_map_a
are equal, false otherwise. void xcm_attr_map_destroy | +( | +struct xcm_attr_map * | +attr_map | ) | ++ |
Destroys an attribute map instance.
+This function destroys the attribute map instance and frees all the resources associated with it.
+[in] | attr_map | The attribute map instance, or NULL. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains type definitions for the XCM attribute access API. +More...
+ +Go to the source code of this file.
++Enumerations | |
enum | xcm_attr_type { xcm_attr_type_bool = 1 +, xcm_attr_type_int64 = 2 +, xcm_attr_type_str = 3 +, xcm_attr_type_bin = 4 + } |
This file contains type definitions for the XCM attribute access API.
+enum xcm_attr_type | +
Enumeration representing the different attribute value types.
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains obsolete parts of the XCM core API. +More...
+ +Go to the source code of this file.
++Macros | |
#define | XCM_FD_READABLE (1<<0) |
#define | XCM_FD_WRITABLE (1<<1) |
#define | XCM_FD_EXCEPTION (1<<2) |
+Functions | |
int | xcm_want (struct xcm_socket *socket, int condition, int *fds, int *events, size_t capacity) |
This file contains obsolete parts of the XCM core API.
+It should not be included directly, but rather only via <xcm.h>.
+#define XCM_FD_READABLE (1<<0) | +
Flag bit denoting a readable fd event in xcm_want().
+ +#define XCM_FD_WRITABLE (1<<1) | +
Flag bit denoting a writable fd event.
+ +#define XCM_FD_EXCEPTION (1<<2) | +
Flag bit denoting a exception fd event.
+ +int xcm_want | +( | +struct xcm_socket * | +socket, | +
+ | + | int | +condition, | +
+ | + | int * | +fds, | +
+ | + | int * | +events, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Query the socket what events on which file descriptors it's waiting for.
+Please note: this function is obsolete, replaced by xcm_fd() and xcm_await().
+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.
+With xcm_want(), the application will inform the XCM socket what condition it's waiting for (i.e. what XCM operation it wants to perform), and in return the XCM socket will provide a set of file descriptors and, for each fd, information on what type of event on that fd it require to make progress. Progress can mean both progress toward the goal of reaching the application's desired socket condition, or finishing any outstanding task the XCM socket has.
+In case any of the conditions the application is asking for are believed to be already met, the xcm_want() call will return 0.
+In case the XCM socket has no outstanding tasks, and the application is not asking for any operation that the XCM socket believes it can't immediate fulfill, the call will return 0.
+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.
+Note that XCM may ask the application to wait for the connection's fd or fds to become writable, even if the application is waiting to receive a message. It may also ask the application to wait for the connection's fd to become readable, even if the application is attemting to send a messaging. For the quirks of xcm_want(), see io_waiting.
+Even though the conditions for a particular connection socket are met (fd is becoming writable, for example), there's no guarantee that the xcm_send() or xcm_receive() won't block (or in case of non-blocking mode, won't fail and set EAGAIN).
+The XCM socket fds may only be used with select(). Supplying this fd to any other OS calls (such as setsockopt(2), read(2) etc) is prohibited.
+The information received on which fd to use, and what events on that fd are relevant for the connection socket in its current state, are only valid until more xcm_* calls are made on this socket. See Finishing Outstanding Tasks for more information.
+The fd is an positive integer, unique within this process.
+The condition parameter is a bitmask, with the bits being XCM_SO_RECEIVABLE, XCM_SO_SENDABLE, and/or XCM_SO_ACCEPTABLE. If no bits are set, the application is not interested in anything beyond this XCM socket to finish any outstanding task.
+Each element in the events array is an int used as a bitmask. The bitmask at position N in the events array represents the file descriptor events the XCM transport is waiting for, for fd at position N in the fds array. The bits are XCM_FD_READABLE, XCM_FD_WRITABLE and/or XCM_FD_EXCEPTION. At least one bit is always set.
+If a socket is waiting for multiple events (for example, both readable and writable on the same fd, or readable on one fd, and writeable on another), the condition is met whenever any of the events occur (as oppose to all events).
+[in] | socket | The XCM socket. |
[in] | condition | The condition the application is waiting for. |
[out] | fds | An user-supplied array to store the fds. |
[out] | events | An user-supplied array of int to store the bitmask of each of the fds in the fds array. |
[in] | capacity | The length of the fds and events arrays. |
errno | Description |
---|---|
EOVERFLOW | The user-supplied buffer was too small to fit the socket's fds. |
EINVAL | The socket is not in blocking mode, or the condition bits are invalid. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains functions and macros to retrieve XCM version information. The library (i.e., implementation) version uses the semver convention. +More...
+ +Go to the source code of this file.
++Macros | |
#define | XCM_VERSION_MAJOR 1 |
#define | XCM_VERSION_MINOR 5 |
#define | XCM_VERSION_PATCH 0 |
#define | XCM_VERSION "1.5.0" |
#define | XCM_VERSION_API_MAJOR 0 |
#define | XCM_VERSION_API_MINOR 20 |
#define | XCM_VERSION_API "0.20" |
+Functions | |
unsigned int | xcm_version_major (void) |
unsigned int | xcm_version_minor (void) |
unsigned int | xcm_version_patch (void) |
const char * | xcm_version (void) |
unsigned int | xcm_version_api_major (void) |
unsigned int | xcm_version_api_minor (void) |
const char * | xcm_version_api (void) |
This file contains functions and macros to retrieve XCM version information. The library (i.e., implementation) version uses the semver convention.
+#define XCM_VERSION_MAJOR 1 | +
The XCM library major version.
+ +#define XCM_VERSION_MINOR 5 | +
The XCM library minor version.
+ +#define XCM_VERSION_PATCH 0 | +
The XCM library patch version.
+ +#define XCM_VERSION "1.5.0" | +
The complete XCM library version in string format.
+ +#define XCM_VERSION_API_MAJOR 0 | +
The XCM API/ABI major version this library version implements.
+ +#define XCM_VERSION_API_MINOR 20 | +
The XCM API/ABI minor version this library version implements.
+ +#define XCM_VERSION_API "0.20" | +
The complete XCM API version in string format.
+ +unsigned int xcm_version_major | +( | +void | +) | ++ |
Retrieves the library major version.
+This function returns the implementation major version of the library used at run time.
+ +unsigned int xcm_version_minor | +( | +void | +) | ++ |
Retrieves the library minor version.
+This function returns the implementation minor version of the library used at run time.
+ +unsigned int xcm_version_patch | +( | +void | +) | ++ |
Retrieves the library patch version.
+This function returns the implementation patch version of the library used at run time.
+ +const char * xcm_version | +( | +void | +) | ++ |
Retrieves the library version as a string.
+This function returns the version of the library used at run time, in string format.
+The string returned is statically allocated, and thus must not be free'd by the caller.
+ +unsigned int xcm_version_api_major | +( | +void | +) | ++ |
Retrieves the XCM API major version.
+This function returns the API major version of the library used at run time adheres to.
+ +unsigned int xcm_version_api_minor | +( | +void | +) | ++ |
Retrieves the XCM API minor version.
+This function returns the API minor version of the library used at run time adheres to.
+ +const char * xcm_version_api | +( | +void | +) | ++ |
Retrieves the library API version as a string.
+This function returns the API version of the library used at run time adheres to.
+The string returned is statically allocated, and thus must not be free'd by the caller.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
Cxcm_addr_host | |
Cxcm_addr_ip |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Files | |
xcm.h | |
This file contains the core Extensible Connection-oriented Messaging (XCM) API. | |
xcm_addr.h | |
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses. | |
xcm_attr.h | |
This file contains the XCM attribute access API. See Socket Attributes for an overview. | |
xcm_attr_map.h | |
This file contains the XCM attribute map API. | |
xcm_attr_types.h | |
This file contains type definitions for the XCM attribute access API. | |
xcm_compat.h | |
This file contains obsolete parts of the XCM core API. | |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
▼ include | |
xcm.h | This file contains the core Extensible Connection-oriented Messaging (XCM) API |
xcm_addr.h | This is an API for building and parsing Connection-oriented Messaging (XCM) addresses |
xcm_attr.h | This file contains the XCM attribute access API. See Socket Attributes for an overview |
xcm_attr_map.h | This file contains the XCM attribute map API |
xcm_attr_types.h | This file contains type definitions for the XCM attribute access API |
xcm_compat.h | This file contains obsolete parts of the XCM core API |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Macros | |
#define | XCM_VERSION_API_MAJOR 0 |
#define | XCM_VERSION_API_MINOR 22 |
#define | XCM_VERSION_API "0.22" |
#define XCM_VERSION_API_MAJOR 0 | +
The XCM API/ABI major version this library version implements.
+ +#define XCM_VERSION_API_MINOR 22 | +
The XCM API/ABI minor version this library version implements.
+ +#define XCM_VERSION_API "0.22" | +
The complete XCM API version in string format.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Macros | |
#define | XCM_VERSION_MAJOR 1 |
#define | XCM_VERSION_MINOR 7 |
#define | XCM_VERSION_PATCH 0 |
#define | XCM_VERSION "1.7.0" |
#define XCM_VERSION_MAJOR 1 | +
The XCM library major version.
+ +#define XCM_VERSION_MINOR 7 | +
The XCM library minor version.
+ +#define XCM_VERSION_PATCH 0 | +
The XCM library patch version.
+ +#define XCM_VERSION "1.7.0" | +
The complete XCM library version in string format.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This is the documentation for the Extensible Connection-oriented Messaging (XCM) programming APIs.
+XCM consists the core API in xcm.h, an address helper library API in xcm_addr.h, and the attribute APIs in xcm_attr.h and xcm_attr_map.h. Obsolete, but still present, functions are available in xcm_compat.h
+The low API/ABI version number is purely a result of all XCM releases being backward compatible, and thus left the major version at 0. It's not to be taken as a sign of immaturity. The API and its implementation have been stable for years.
+XCM provides a connection-oriented, reliable messaging service with in-order delivery. The design goal is to allow for a straight forward mapping to TCP and TLS, but also supporting efficient inter-process commmunication (IPC) mechanisms for local communication.
+XCM reuses much of the terminology of the BSD Sockets API. Unlike the BSD Socket API, XCM has uniform semantics across all underlying transports.
+XCM has a client-server model. A server creates a server socket (with xcm_server()) bound to a specific address (in case of TCP or TLS, a TCP port on a particular IP interface), after which clients may initiate connections to the server. On a successful attempt, two connection sockets will be created; one on the server side (returned from xcm_accept()), and one of the client side (returned from xcm_connect()). Thus, a server serving multiple clients will have multiple sockets; one server socket and N connection sockets, one each for every client. A client will typically have one connection socket for each server it is connected to.
+Messages are always sent and received on a particular connection socket (and never on a server socket).
+In-order delivery - that messages arrive at the recipient in the same order they were sent by the sender side - is guaranteed, but only for messages sent on the same connection.
+XCM transports support flow control. Thus, if the sender message rate or bandwidth is higher than the network or the receiver can handle on a particular connection, xcm_send() in the sender process will eventually block (or return an error EAGAIN, if in non-blocking mode). Unless XCM is used for bulk data transfer (as oppose to signaling traffic), xcm_send() blocking because of slow network or a slow receiver should be rare indeed in practice. TCP, TLS, and UNIX domain socket transports all have large enough windows and socket buffers to allow a large amount of outstanding data.
+In XCM, the application is in control of which transport will be used, with the address supplied to xcm_connect() and xcm_server() including both the transport name and the transport address.
+However, there is nothing preventing a XCM transport to use a more an abstract addressing format, and internally include multiple "physical" IPC transport options. This model is used by the UTLS Transport.
+Addresses are represented as strings with the following general syntax: <transport-name>:<transport-address>
For the UX UNIX Domain Socket transport, the addresses has this more specific form:
+
The addresses of the UXF UNIX Domain Socket transport variant have the following format:
+
For the TCP, TLS, UTLS and SCTP transports the syntax is:
+
'*' is a shorthand for '0.0.0.0' (i.e. bind to all IPv4 interfaces). '[*]' is the IPv6 equivalent, creating a server socket accepting connections on all IPv4 and IPv6 addresses.
+Some examples addresses:
For TCP, TLS, UTLS and SCTP server socket addresses, the port can be set to 0, in which case XCM (or rather, the Linux kernel) will allocate a free TCP port from the local port range.
+For transports allowing a DNS domain name as a part of the address, the transport will attempt resoĺv the name to an IP address. A DNS domain name may resolv to zero or more IPv4 addresses and/or zero or more IPv6 addresses. XCM relies on the operating system to prioritize between IPv4 and IPv6.
+XCM accepts IPv4 addresses in the dotted-decimal format
XCM allows only complete addresses with three '.', and not the archaic, classful, forms, where some bytes where left out, and thus the address contained fewer separators.
+XCM transports attempt to detect a number of conditions which can lead to lost connectivity, and does so even on idle connections.
+If the remote end closes the connection, the local xcm_receive() will return 0. If the process on the remote end crashed, xcm_receive() will return -1 and set errno ECONNRESET. If network connectivity to the remote end is lost, xcm_receive() will return -1 and errno will be set to ETIMEDOUT.
+In general, XCM follow the UNIX system API tradition when it comes to error handling. Where possible, errors are signaled to the application by using unused parts of the value range of the function return type. For functions returning signed integer types, this means the value of -1 (in case -1 is not a valid return value). For functions returning pointers, NULL is used to signal that an error has occurred. For functions where neither -1 or NULL can be used, or where the function does not return anything (side-effect only functions), an 'int' is used as the return type, and is used purely for the purpose to signal success (value 0), or an error (-1) to the application.
+The actual error code is stored in the thread-local errno variable. The error codes are those from the fixed set of errno values defined by POSIX, found in errno.h. Standard functions such as perror() and strerror() may be used to turn the code into a human-readable string.
+In non-blocking operation, given the fact the actual transmission might be defered (and the message buffered in the XCM layer), and that message receive processing might happen before the application has called receive, the error being signaled at the point of a certain XCM call might not be a direct result of the requested operation, but rather an error discovered previously.
+The documentation for xcm_finish() includes a list of generic error codes, applicable xcm_connect(), xcm_accept(), xcm_send() and xcm_receive().
+Also, for errors resulting in an unusable connection, repeated calls will produce the same errno.
+In UNIX-style event-driven programming, a single application thread handles multiple clients (and thus multiple XCM connection sockets) and the task of accepting new clients on the XCM server socket concurrently (although not in parallel). To wait for events from multiple sources, an I/O multiplexing facility such as select(2), poll(2) or epoll(2) is used.
+Each XCM socket is represented by a single fd, retrieved with xcm_fd(). The fd number and underlying file object is stable across the life-time of the socket.
+On BSD Sockets, the socket fd being readable means it's likely that the application can successfully read data from the socket. Similarily, a fd marked writable by, for example, poll() means that the application is likely to be able to write data to the BSD Sockets fd. For an application using XCM going into select(), it must always wait for all the fds its XCM sockets to become readable (e.g. being in the readfds
in the select() call), regardless what are their target conditions. Thus, even if the application is waiting for an opportunity to try to send a message on a XCM socket, or it doesn't want to do anything with the socket, it must wait for the socket fd to become readable. Not wanting to do nothing here means that the application has the xcm_await() condition
set to 0, and is neither interested in waiting to call xcm_send(), xcm_receive(), nor xcm_accept() on the socket. An application may never leave a XCM socket unattended in the sense its fd is not in the set of fds passed to select() and/or xcm_send(), xcm_receive(), xcm_accept() or xcm_finish() are not called.
XCM is oblivious to what I/O multiplexing mechanism employed by the application. It may call select(), poll() or epoll_wait() directly, or make use of any of the many available event loop libraries (such as libevent). For simplicity, select() is used in this documentation to denote the whole family of Linux I/O multiplexing facilities.
+An event-driven application needs to set the XCM sockets it handles into non-blocking mode, by calling xcm_set_blocking(), setting the "xcm.blocking" socket attribute, or using the XCM_NONBLOCK flag in xcm_connect().
+For XCM sockets in non-blocking mode, all potentially blocking API calls related to XCM connections - xcm_connect(), xcm_accept(), xcm_send(), and xcm_receive() - finish immediately.
+For xcm_send(), xcm_connect() and xcm_accept(), XCM signaling success means that the XCM layer has accepted the request. It may or may not have completed the operation.
+In case the XCM_NONBLOCK flag is set in the xcm_connect() call, or in case the a XCM server socket is in non-blocking mode at the time of a xcm_accept() call, the newly created XCM connection returned to the application may be in a semi-operational state, with some internal processing and/or signaling with the remote peer still required before actual message transmission and reception may occur.
+The application may attempt to send or receive messages on such semi-operational connections.
+There are ways for an application to determine when connection establishment or the task of accepting a new client have completed. See Finishing Outstanding Tasks for more information.
+To receive a message on a XCM connection socket in non-blocking mode, the application may need to wait for the right conditions to arise (i.e. a message being available). The application needs to inform the socket that it wants to receive by calling xcm_await() with the XCM_SO_RECEIVABLE
bit in the condition
bit mask set. It will pass the fd it received from xcm_fd() into select(), asking to get notified when the fd becomes readable. When select() marks the socket fd as readable, the application should issue xcm_receive() to attempt to retrieve a message.
xcm_receive() may also called on speculation, prior to any select() call, to poll the socket for incoming messages.
+A XCM connection socket may have a number of messages buffered, and applications should generally, for optimal performance, repeat xcm_receive() until it returns an error, and errno is set to EAGAIN.
+Similarly to receiving a message, an application may set the XCM_SO_SENDABLE
bit in the condition
bit mask, if it wants to wait for a socket state where it's likely it can successfully send a message. When select() marks the socket fd as readable, the application should attempt to send a message.
Just like with xcm_receive(), it may also choose to issue a xcm_send() call on speculation (i.e. without going into select()), which is often a good idea for performance reasons.
+For send operations on non-blocking connection sockets, XCM may buffer whole or part of the message before transmission to the lower layer. This may be due to socket output buffer underrun, or the need for some in-band signaling, like cryptographic key exchange, to happen before the transmission of the complete message may finish. The XCM layer will (re-)attempt to hand the message over to the lower layer at a future call to xcm_finish(), xcm_send(), or xcm_receive().
+For applications wishing to determine when all buffered messages have successfully be deliver to the lower layer, they may use xcm_finish() to do so. Normally, applications aren't expected to require this kind of control. Please also note that the fact a message has left the XCM layer doesn't necessarily mean it has successfully been delivered to the recipient.
+xcm_connect(), xcm_accept(), xcm_send() may all leave the socket in a state where work is initiated, but not completed. In addition, the socket may have pending internal tasks, such flushing the output buffer into the TCP/IP stack, processing XCM control interface messages, or finishing the TLS hand shake procedure.
+After waking up from a select() call, where a particular XCM non-blocking socket's fd is marked readable, the application must, if no xcm_send(), xcm_receive() or xcm_accept() calls are to be made, call xcm_finish(). This is to allow the socket to finish any outstanding tasks, even in the case the application has no immediate plans for the socket.
+Prior to changing a socket from non-blocking to blocking mode, any outstanding tasks should be finished, or otherwise the switch might cause xcm_set_blocking() to return -1 and set errno to EAGAIN.
+For example, if a server socket's desired condition has been set (with xcm_await()) to XCM_SO_ACCEPTABLE
, and the application wakes up from select() with the socket's fd marked readable, a call to xcm_accept() may still not produce a new connection socket.
The same holds true when reaching XCM_SO_RECEIVABLE
and a xcm_receive() call is made, and XCM_SO_SENDABLE
and calls to xcm_send().
In this example, the application connects and tries to send a message, before knowing if the connection is actually established. This may fail (for example, in case TCP and/or TLS-level connection establishement has not yet been completed), in which case the application will fall back and wait with the use of xcm_await(), xcm_fd() and select().
+In case the application wants to know when the connection establishment has finished, it may use xcm_finish() to do so, like in the below example sequence.
+While connecting to a server socket, the client's connection attempt may be refused immediately.
+In many cases, the application is handed a connection socket before the connection establishment is completed. Any errors occuring during this process is handed over to the application at the next XCM call; would it be xcm_finish(), xcm_send() or xcm_receive().
+In this example the application flushes any internal XCM buffers before shutting down the connection, to ensure that any buffered messages are delivered to the lower layer.
+In this sequence, a server accepts a new connection, and continues to attempt to receive a message on this connection, while still, concurrently, is ready to accept more clients on the server socket.
+Tied to an XCM server or connection socket is a set of key-value pairs known as attributes. Which attributes are available varies across different transports, and different socket types.
+An attribute's name is a string, and follows a hierarchical naming schema. For example, all generic XCM attributes, available in all transports, have the prefix "xcm.". Transport-specific attributes are prefixed with the transport or protocol name (e.g. "tcp." for TCP-specific attributes applicable to the TLS and TCP transports).
+An attribute may be read-only, write-only or available both for reading and writing. This is referred to as the attribute's mode. The mode may vary across the lifetime of the socket. For example, an attribute may be writable at the time of the xcm_connect() call, and read-only thereafter.
+The attribute value is coded in the native C data type and byte order. Strings are NUL-terminated, and the NUL character is included in the length of the attribute. There are four value types; a boolean type, a 64-bit signed integer type, a string type and a type for arbitrary binary data. See xcm_attr_types.h for details.
+The attribute access API is in xcm_attr.h.
+Retrieving an integer attribute's value may look like this:
Changing an integer attribyte value may be done in the following manner:
Both of these examples are missing error handling.
+XCM allows supplying a set of writable attributes at the time of socket creation, by using the xcm_connect_a(), xcm_server_a(), or xcm_accept_a() functions.
+The attribute sets are represented by the xcm_attr_map type in xcm_attr_map.h.
+An example:
These attributes are expected to be found on XCM sockets regardless of transport type.
+For TCP transport-specific attributes, see TCP Socket Attributes, and for TLS, see TLS Socket Attributes.
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
xcm.type | All | String | R | The socket type: "server" or "connection". |
xcm.transport | All | String | R | The transport type. |
xcm.local_addr | All | String | RW | The local address of a socket. Writable only if supplied to xcm_connect_a(). |
xcm.blocking | All | Boolean | RW | See xcm_set_blocking() and xcm_is_blocking(). |
xcm.remote_addr | Connection | String | R | See xcm_remote_addr(). |
xcm.max_msg_size | Connection | Integer | R | The maximum size of any message transported by this connection. |
XCM has a set of generic message counters, which keeps track of the number of messages crossing a certain boundary for a particular connection, and a sum of their size.
+Some of the message and byte counter attributes use the concept of a "lower layer". What this means depends on the transport. For the UX And TCP transports, it is the Linux kernel. For example, for TCP, if the xcm.to_lower_msgs is incremented, it means that XCM has successfully sent the complete message to the kernel's networking stack for further processing. It does not means it has reached the receiving process. It may have, but it also may be sitting on the local or remote socket buffer, on a NIC queue, or be in-transmit in the network. For TLS, the lower layer is OpenSSL.
+All the "xcm.*_bytes" counters count the length of the XCM message payload (as in the length field in xcm_send()), and thus does not include any underlying headers.
+The message counters only count messages succesfully sent and/or received.
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
xcm.from_app_msgs | Connection | Integer | R | Messages sent from the application and accepted into XCM. |
xcm.from_app_bytes | Connection | Integer | R | The sum of the size of all messages counted by xcm.from_app_msgs. |
xcm.to_app_msgs | Connection | Integer | R | Messages delivered from XCM to the application. |
xcm.to_app_bytes | Connection | Integer | R | The sum of the size of all messages counter by xcm.to_app_msgs. |
xcm.from_lower_msgs | Connection | Integer | R | Messages received by XCM from the lower layer. |
xcm.from_lower_bytes | Connection | Integer | R | The sum of the size of all messages counted by xcm.from_lower_msgs. |
xcm.to_lower_msgs | Connection | Integer | R | Messages successfully sent by XCM into the lower layer. |
xcm.to_lower_bytes | Connection | Integer | R | The sum of the size of all messages counted by xcm.to_lower_msgs. |
XCM includes a control interface, which allows iteration over the OS instance's XCM server and connection sockets (for processes with the appropriate permissions), and access to their attributes (see Socket Attributes).
+The control interface is optional by means of build-time configuration.
+For each XCM server or connection socket, there is a corresponding UNIX domain socket which is used for control signaling (i.e. state retrieval).
+By default, the control interface's UNIX domain sockets are stored in the /run/xcm/ctl
directory.
This directory needs to be created prior to running any XCM applications (for the control interface to worker properly) and should be writable for all XCM users.
+A particular process using XCM may be configured to use a non-default directory for storing the UNIX domain sockets used for the control interface by means of setting the XCM_CTL
variable. Please note that using this setting will cause the XCM connections to be not visible globally on the OS instance (unless all other XCM-using processes also are using this non-default directory).
Generally, since the application is left unaware (from an API perspective) of the existence of the control interface, errors are not reported up to the application. They are however logged.
+Application threads owning XCM sockets, but which are busy with non-XCM processing for a long duration of time, or otherwise are leaving their XCM sockets unattended to (in violation of XCM API contract), will not respond on the control interface's UNIX domain sockets (corresponding to their XCM sockets). Only the presence of these sockets may be detected, but their state cannot be retrieved.
+Internally, the XCM implementation has control interface client library, but this library's API is not public at this point.
+XCM includes a command-line program xcmctl
which uses the Control API to iterate of the system's current XCM sockets, and allow access (primarily for debugging purposes) to the sockets' attributes.
Unlike BSD sockets, a XCM socket may not be shared among different threads without synchronization external to XCM. With proper external serialization, a socket may be shared by different threads in the same process, although it might provide difficult in practice since a thread in a blocking XCM function will continue to hold the lock, and thus preventing other threads from accessing the socket at all.
+For non-blocking sockets, threads sharing a socket need to agree on what is the appropriate socket condition
to wait for. When this condition is met, all threads are woken up, returning from select().
It is safe to "give away" a XCM socket from one thread to another, provided the appropriate memory fences are used.
+These limitations (compared to BSD Sockets) are in place to allow socket state outside the kernel (which is required for TCP framing and TLS).
+Sharing a XCM socket between threads in different processes is not possible.
+After a fork() call, either of the two process (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 not call any other XCM API call than xcm_cleanup(), which frees local memory tied to this socket in the non-owner's process address space, without impacting the connection state in the owner process.
+The core XCM API functions are oblivious to the transports used. However, the support for building, and parsing addresses are available only for a set of pre-defined set of transports. There is nothing preventing xcm_addr.h from being extended, and also nothing prevents an alternative XCM implementation to include more transports without extending the address helper API.
+The UX transport uses UNIX Domain (AF_UNIX, also known as AF_LOCAL) Sockets.
+UX sockets may only be used with the same OS instance (or, more specifically, between processes in the same Linux kernel network namespace).
+UNIX Domain Sockets comes in a number of flavors, and XCM uses the SOCK_SEQPACKET variety. SOCK_SEQPACKET sockets are connection-oriented, preserves message boundaries and delivers messages in the same order they were sent; perfectly matching XCM semantics and provides for an near-trivial mapping.
+UX is the most efficient of the XCM transports.
+The standard UNIX Domain Sockets as defined by POSIX uses the file system as its namespace, with the sockets also being files. However, for simplicity and to avoid situations where stale socket files (originating from crashed processes) causing problems, the UX transport uses a Linux-specific extension, allowing a private UNIX Domain Socket namespace. This is known as the abstract namespace (see the unix(7) man page for details). With the abstract namespace, server socket address allocation has the same life time as TCP ports (i.e. if the process dies, the address is free'd).
+The UX transport enables the SO_PASSCRED BSD socket option, to give the remote peer a name (which UNIX domain connection socket doesn't have by default). This is for debugging and observability purposes. Without a remote peer name, in server processes with multiple incoming connections to the same server socket, it's difficult to say which of the server-side connection sockets goes to which remote peer. The kernel-generated, unique, name is an integer in the form "%05x" (printf format). Applications using hardcoded UX addresses should avoid such names by, for example, using a prefix.
+The UTLS Transport also indirectly uses the UX namespace, so care should be taken to avoid any clashes between UX and UTLS sockets in the same network namespace.
+The UXF transport is identical to the UX transport, only it uses the standard POSIX naming mechanism. The name of a server socket is a file system path, and the socket is also a file.
+The UXF sockets resides in a file system namespace, as opposed to UX sockets, which live in a network namespace.
+Upon xcm_close(), the socket will be closed and the file removed. If an application crashes or otherwise fails to run xcm_close(), it will leave a file in the file system pointing toward a non-existing socket. This file will prevent the creation another server socket with the same name.
+The TCP transport uses the Transmission Control Protocol (TCP), by means of the BSD Sockets API.
+TCP is a byte-stream service, but the XCM TCP transport adds framing on top of the stream. A single-field 32-bit header containing the message length in network byte order is added to every message.
+TCP uses TCP Keepalive to detect lost network connectivity between the peers.
+The TCP transport supports IPv4 and IPv6.
+Since XCM is designed for signaling traffic, the TCP transport disables the Nagle algorithm of TCP to avoid its excessive latency.
+The read-only TCP attributes are retrieved from the kernel (struct tcp_info in linux/tcp.h).
+The read-write attributes are mapped directly to setsockopt() calls.
+See the tcp(7) manual page for a more detailed description of these attributes. The struct retrieved with TCP_INFO
is the basis for the read-only attributes. The read-write attributes are mapped to TCP_KEEP*
and TCP_USER_TIMEOUT
.
Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
tcp.rtt | Connection | Integer | R | The current TCP round-trip estimate (in us). |
tcp.total_retrans | Connection | Integer | R | The total number of retransmitted TCP segments. |
tcp.segs_in | Connection | Integer | R | The total number of segments received. |
tcp.segs_out | Connection | Integer | R | The total number of segments sent. |
tcp.keepalive | Connection | Boolean | RW | Controls if TCP keepalive is enabled. |
tcp.keepalive_time | Connection | Integer | RW | The time (in s) before the first keepalive probe is sent on an idle connection. |
tcp.keepalive_interval | Connection | Integer | RW | The time (in s) between keepalive probes. |
tcp.keepalive_count | Connection | Integer | RW | The number of keepalive probes sent before the connection is dropped. |
tcp.user_timeout | Connection | Integer | RW | The time (in s) before a connection is dropped due to unacknowledged data. |
tcp.segs_in
and tcp.segs_out
are only present when running XCM on Linux kernel 4.2 or later.The TLS transport uses TLS to provide a secure, private, two-way authenticated transport.
+TLS is a byte-stream service, but the XCM TLS transport adds framing in the same manner as does the XCM TCP transport.
+The TLS transport supports IPv4 and IPv6.
+The TLS transport disables the Nagle algorithm of TCP.
+The TLS transport expect the certificate, trust chain and private key files to be found in a file system directory - the certificate directory. The default path are configured at build-time, but can be overriden on a per-process basis by means of a UNIX environment variable. The current value of XCM_TLS_CERT
(at the time of xcm_connect() or xcm_accept()) determines the certificate directory used for that connection.
In case the files in the certificate directory are modified, the new versions of the files will be used by new connections. The TLS transports works with differences between set of files, and thus the new generation of files need not nesserarily be newer (i.e. higher mtime).
+The certificate directory must be updated in an atomic manner, or XCM may end up using the certificate file from one generation of files and the key file from another. One way of achieving an atomic update is to have the certificate directory being a symbolic link to the directory where the actual files are located. Upon update, a new directory is created and populated, and the old symbolic link is replace with a new one in an atomic manner (i.e. with rename(2)). It's legal to switch back-and-forth between two sets of files, but the time between the back and the forth switch (assuming the atomicity-by-symlink method is used) must be enough to result in different file system modification times on the symbolic link (usually ~10 ms).
+The TLS transport will, at the time of XCM socket creation (xcm_connect() or xcm_server()), look up the process' current network namespace. In case the namespace is given a name per the iproute2 methods and conventions, XCM will retrieve this name and use it in the certificate and key lookup.
+In the certificate directory, the TLS transport expects the certificate to follow the below naming convention (where <ns> is the namespace):
The private key is stored in:
The trust chain is stored in:
For the default namespace (or any other network namespace not named according to iproute2 standards), the certificate need to be stored in a file "cert.pem", the private key in "key.pem" and the trust chain in "tc.pem".
+In case the certificate, key or trust chain files are not in place (for a particular namespace), a xcm_server() call will return an error and set errno to EPROTO. The application may choose to retry at a later time.
+TLS has all the TCP-level attributes of the TCP transport; see TCP Socket Attributes.
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
tls.peer_subject_key_id | Connection | String | R | The X509v3 Subject Key Identifier of the remote peer, or a zero-length string in case the TLS connection is not established. |
The UTLS transport provides a hybrid transport, utilizing both the TLS and UX transports internally for actual connection establishment and message delivery.
+On the client side, at the time of xcm_connect(), the UTLS transport determines if the server socket can be reached by using the UX transport (i.e. if the server socket is located on the same OS instance, in the same network namespace). If not, UTLS will attempt to reach the server by means of the TLS transport.
+For a particular UTLS connection, either TLS or UX is used (never both). XCM connections to a particular UTLS server socket may be a mix of the two different types.
+For an UTLS server socket with the address utls:<ip>:<port>
, two underlying addresses will be allocated; tls:<ip>:<port>
and ux:<ip>:<port>
.
Or, in the case DNS is used: tls:<hostname>:<port>
and ux:<hostname>:<port>
.
A wildcard should never be used when creating a UTLS server socket.
+If a DNS hostname is used in place of the IP address, both the client and server need employ DNS, and also agree upon which hostname to use (in case there are several pointing at the same IP address).
+Failure to adhere to the above two rules will prevent a client from finding a local server. Such a client will instead establish a TLS connection to the server.
+The SCTP transport uses the Stream Control Transmission Protocol (SCTP). SCTP provides a reliable, message-oriented service. In-order delivery is optional, but to adhere to XCM semantics (and for other reasons) XCM leaves SCTP in-order delivery enabled.
+The SCTP transport utilizes the native Linux kernel's implementation of SCTP, via the BSD Socket API. The operating mode is such that there is a 1:1-mapping between an association and a socket (fd).
+The SCTP transport supports IPv4 and IPv6.
+To minimize latency, the SCTP transport disables the Nagle algorithm.
+Namespaces is a Linux kernel facility concept for creating multiple, independent namespaces for kernel resources of a certain kind.
+Linux Network Namespaces will affect all transports, including the UX transport.
+XCM has no explicit namespace support. Rather, the application is expected to use the Linux kernel facilities for this functionality (i.e. switch to the right namespace before xcm_server() och xcm_connect()).
+In case the system follows the iproute2 conventions in regards to network namespace naming, the TLS and UTLS transports support per-network namespace TLS certificates and private keys.
+XCM, in its current form, does not support binding to a local socket before doing connect() - something that is possible with BSD Sockets, but very rarely makes sense.
+XCM also doesn't have a sendmmsg() or recvmmsg() equivalent. Those could easily be added, and would provide some major performance improvements for applications that are sending or receiving multiple messages on the same connection on the same time. *mmsg() equivalents have been left out because there are strong doubts there are such applications.
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
#include <xcm_addr.h>
+Data Fields | ||
enum xcm_addr_type | type | |
union { | ||
+ struct xcm_addr_ip ip | ||
+ char name [254] | ||
}; | ||
Hostname or IPv4/IPv6 address data type.
+enum xcm_addr_type xcm_addr_host::type | +
Type tag
+ +union { ... } xcm_addr_host | +
Union containing the actual hostname, IPv4 or IPv6 address bytes
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
#include <xcm_addr.h>
+Data Fields | ||
sa_family_t | family | |
union { | ||
in_addr_t ip4 | ||
uint8_t ip6 [16] | ||
} | addr | |
IPv4 or IPv6 address data type.
+sa_family_t xcm_addr_ip::family | +
Type tag; AF_INET or AF_INET6
+ +in_addr_t xcm_addr_ip::ip4 | +
Contains the IPv4 address in network byte order (in case family is set to AF_INET).
+ +uint8_t xcm_addr_ip::ip6[16] | +
Contains the IPv6 address (in case family is set to AF_INET6).
+ +union { ... } xcm_addr_ip::addr | +
Union containing the actual IPv4 or a IPv6 address bytes
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
Library Version | |
API Version |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the core Extensible Connection-oriented Messaging (XCM) API. +More...
+#include <errno.h>
#include <stdbool.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 *conn_socket, const void *buf, size_t len) |
int | xcm_receive (struct xcm_socket *conn_socket, void *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) |
This file contains the core Extensible Connection-oriented Messaging (XCM) API.
+#define XCM_NONBLOCK (1<<0) | +
Flag used in xcm_connect()
+ +#define XCM_SO_RECEIVABLE (1<<0) | +
Flag bit denoting a socket where the application likely can receive a message.
+ +#define XCM_SO_SENDABLE (1<<1) | +
Flag bit denoting a socket where the application likely can send a message.
+ +#define XCM_SO_ACCEPTABLE (1<<2) | +
Flag bit denoting a socket with a pending incoming connection.
+ +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).
+[in] | remote_addr | The remote address which to connect. |
[in] | flags | Either 0, or XCM_NONBLOCK for a non-blocking connect. |
errno | Description |
---|---|
EINVAL | Invalid address format. |
ENOPROTOOPT | Transport protocol not available. |
EMFILE | The limit on the total number of open fds has been reached. |
ENOENT | DNS domain name resolution failed. |
See xcm_finish() for other possible errno values.
+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.
+[in] | remote_addr | The remote address which to connect. |
[in] | attrs | A set of attributes to be applied to the connection socket, or NULL. |
See xcm_connect() and xcm_attr_set() for possible errno values.
+ +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), a xcm_server() call also includes a blocking name resolution (e.g. gethostbyname()).
+[in] | local_addr | The local address to which this socket should be bound. |
errno | Description |
---|---|
EACCESS | Permission to create the socket is denied. |
EADDRINUSE | Local socket address is already in use. |
ENOMEM | Insufficient memory. |
EINVAL | Invalid address format. |
ENOPROTOOPT | Transport protocol not available. |
EMFILE | The limit on the total number of open fds has been reached. |
EPROTO | A protocol error occured. |
ENOENT | DNS domain name resolution failed. |
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.
+[in] | local_addr | The local address to which this socket should be bound. |
[in] | attrs | A set of attributes to be applied to the socket, or NULL. |
See xcm_server() and xcm_attr_set() for possible errno values.
+ +int xcm_close | +( | +struct xcm_socket * | +socket | ) | ++ |
Close an endpoint.
+This function close a 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.
+[in] | socket | The socket to be closed, or NULL (in case xcm_close() is a no-operation). |
void xcm_cleanup | +( | +struct xcm_socket * | +socket | ) | ++ |
Cleans up any local resources tied to a 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().
+[in] | socket | The socket which local resources are to be freed, or NULL (in case xcm_cleanup() is a no-operation). |
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.
+[in] | server_socket | The server socket on which to attempt to accept one pending connection. |
errno | Description |
---|---|
EMFILE | The limit on the total number of open fds has been reached. |
See xcm_finish() for other possible errno values.
+ +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.
+[in] | server_socket | The server socket on which to attempt to accept one pending connection. |
[in] | attrs | A set of attributes to be applied to the socket, or NULL. |
See xcm_accept() and xcm_attr_set() for possible errno values.
+ +int xcm_send | +( | +struct xcm_socket * | +conn_socket, | +
+ | + | const void * | +buf, | +
+ | + | size_t | +len | +
+ | ) | ++ |
Send message on a particular connection.
+The xcm_send() function is used to send a message out on a connection socket. A XCM connection goes from a client to a server, and this connection socket may represent either one of the two endpoints.
+[in] | conn_socket | The connection socket the message will be sent on. |
[in] | buf | A pointer to the message data buffer. |
[in] | len | The length of the message in bytes. Zero-length messages are not allowed. |
errno | Description |
---|---|
EMSGSIZE | Message is too large. See also Generic Attributes. |
See xcm_finish() for more errno values.
+ +int xcm_receive | +( | +struct xcm_socket * | +conn_socket, | +
+ | + | void * | +buf, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Receive message on a particular connection.
+The xcm_receive() function is used to receive message on a connection socket. A XCM connection goes from a client to a server, and this connection socket may represent either one of the two endpoints.
+If 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).
+[in] | conn_socket | The connection socket the message will receive be on. |
[out] | buf | The user-supplied buffer where the incoming message will be stored. |
[in] | capacity | The capacity in bytes of the buffer. |
See xcm_finish() for possible errno values.
+ +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.
+[in] | socket | The XCM socket. |
[in] | condition | The condition the application is waiting for. |
errno | Description |
---|---|
EINVAL | The socket is not in non-blocking mode, or the condition bits are invalid. |
int xcm_fd | +( | +struct xcm_socket * | +socket | ) | ++ |
Returns XCM socket fd.
+This call retrieves the XCM socket fd for a XCM socket 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.
+Please 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.
[in] | socket | The connection or server socket. |
errno | Description |
---|---|
EINVAL | The socket is not in non-blocking mode. |
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, xcm_accept() or xcm_send() call on a connection socket in non-blocking mode, wishing to finish outstanding processing related to that operation, 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.
+[in] | socket | The connection or server socket. |
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. |
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.
+[in] | socket | The socket. |
[in] | should_block | Set to true for blocking operation, false for non-blocking mode. |
errno | Description |
---|---|
EAGAIN | The connection socket has unfinished work that needs to completed before mode can be switched. |
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.
+[in] | socket | The socket. |
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.
+[in] | conn_socket | The connection socket. |
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.
+[in] | socket | A server or connection socket. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses. +More...
+#include <errno.h>
#include <inttypes.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <xcm_addr_compat.h>
Go to the source code of this file.
++Data Structures | |
struct | xcm_addr_ip |
struct | xcm_addr_host |
+Macros | |
#define | XCM_UTLS_PROTO "utls" |
#define | XCM_TLS_PROTO "tls" |
#define | XCM_TCP_PROTO "tcp" |
#define | XCM_SCTP_PROTO "sctp" |
#define | XCM_UX_PROTO "ux" |
#define | XCM_UXF_PROTO "uxf" |
+Enumerations | |
enum | xcm_addr_type { xcm_addr_type_name +, xcm_addr_type_ip + } |
+Functions | |
int | xcm_addr_parse_proto (const char *addr_s, char *proto, size_t capacity) |
int | xcm_addr_parse_utls (const char *utls_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_tls (const char *tls_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_tcp (const char *tcp_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_sctp (const char *sctp_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_ux (const char *ux_addr_s, char *ux_path, size_t capacity) |
int | xcm_addr_parse_uxf (const char *uxf_addr_s, char *uxf_path, size_t capacity) |
int | xcm_addr_make_utls (const struct xcm_addr_host *host, unsigned short port, char *utls_addr_s, size_t capacity) |
int | xcm_addr_make_tls (const struct xcm_addr_host *host, unsigned short port, char *tls_addr_s, size_t capacity) |
int | xcm_addr_make_tcp (const struct xcm_addr_host *host, unsigned short port, char *tcp_addr_s, size_t capacity) |
int | xcm_addr_make_sctp (const struct xcm_addr_host *host, unsigned short port, char *sctp_addr_s, size_t capacity) |
int | xcm_addr_make_ux (const char *ux_name, char *ux_addr_s, size_t capacity) |
int | xcm_addr_make_uxf (const char *uxf_name, char *uxf_addr_s, size_t capacity) |
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses.
+#define XCM_UTLS_PROTO "utls" | +
Protocol string for the combined TLS+UX transport.
+ +#define XCM_TLS_PROTO "tls" | +
Protocol string for the Transport Layer Security (TLS) transport.
+ +#define XCM_TCP_PROTO "tcp" | +
Protocol string for the TCP transport.
+ +#define XCM_SCTP_PROTO "sctp" | +
Protocol string for the SCTP transport.
+ +#define XCM_UX_PROTO "ux" | +
Protocol string for the UNIX Domain socket (AF_UNIX SEQPACKET) transport (using the abstract namespace).
+ +#define XCM_UXF_PROTO "uxf" | +
Protocol string for the UNIX Domain socket (AF_UNIX SEQPACKET) transport (using file system-based naming).
+ +int xcm_addr_parse_proto | +( | +const char * | +addr_s, | +
+ | + | char * | +proto, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses the protocol part of a XCM address.
+[in] | addr_s | The XCM address string. |
[out] | proto | The buffer where to store the protocol part of the address. |
[in] | capacity | The buffer length in bytes. |
errno | Description |
---|---|
EINVAL | Malformed address. |
ENAMETOOLONG | The user-supplied buffer is too small to fit the protocol. |
int xcm_addr_parse_utls | +( | +const char * | +utls_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a UTLS XCM address.
+[in] | utls_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TLS port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_tls | +( | +const char * | +tls_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a TLS XCM address.
+[in] | tls_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TLS port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_tcp | +( | +const char * | +tcp_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a TCP XCM address.
+[in] | tcp_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TCP port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_sctp | +( | +const char * | +sctp_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parse a SCTP XCM address.
+[in] | sctp_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The SCTP port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_ux | +( | +const char * | +ux_addr_s, | +
+ | + | char * | +ux_path, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses an UX (UNIX Domain Socket) XCM address.
+[in] | ux_addr_s | The string to sparse. |
[out] | ux_path | The UNIX (NUL-terminated) abstract name portion of the UX address. |
[in] | capacity | The length of the user-supplied path buffer. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_uxf | +( | +const char * | +uxf_addr_s, | +
+ | + | char * | +uxf_path, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses an UXF (UNIX Domain Socket) XCM address.
+[in] | uxf_addr_s | The string to sparse. |
[out] | uxf_path | The UNIX (NUL-terminated) path name portion of the UXF address. |
[in] | capacity | The length of the user-supplied path buffer. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_make_utls | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +utls_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a UTLS XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | utls_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_tls | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +tls_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a TLS XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | tls_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_tcp | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +tcp_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a TCP XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | tcp_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_sctp | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +sctp_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a SCTP XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | sctp_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_ux | +( | +const char * | +ux_name, | +
+ | + | char * | +ux_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds an UX XCM address string from the supplied UNIX Domain Socket name.
+[in] | ux_name | The UNIX Domain Socket name. |
[out] | ux_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid format of or too long UNIX Domain Socket address. |
int xcm_addr_make_uxf | +( | +const char * | +uxf_name, | +
+ | + | char * | +uxf_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds an UXF XCM address string from the supplied file system path.
+[in] | uxf_name | The UNIX Domain path. |
[out] | uxf_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid format of or too long UNIX Domain Socket address. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the XCM attribute access API. See Socket Attributes for an overview. +More...
+ +Go to the source code of this file.
++Typedefs | |
typedef void(* | xcm_attr_cb) (const char *attr_name, enum xcm_attr_type type, void *value, size_t value_len, void *cb_data) |
+Functions | |
int | xcm_attr_set (struct xcm_socket *s, const char *name, enum xcm_attr_type type, const void *value, size_t len) |
int | xcm_attr_set_bool (struct xcm_socket *s, const char *name, bool value) |
int | xcm_attr_set_int64 (struct xcm_socket *s, const char *name, int64_t value) |
int | xcm_attr_set_str (struct xcm_socket *s, const char *name, const char *value) |
int | xcm_attr_get (struct xcm_socket *s, const char *name, enum xcm_attr_type *type, void *value, size_t capacity) |
int | xcm_attr_get_bool (struct xcm_socket *s, const char *name, bool *value) |
int | xcm_attr_get_int64 (struct xcm_socket *s, const char *name, int64_t *value) |
int | xcm_attr_get_str (struct xcm_socket *s, const char *name, char *value, size_t capacity) |
void | xcm_attr_get_all (struct xcm_socket *socket, xcm_attr_cb cb, void *cb_data) |
This file contains the XCM attribute access API. See Socket Attributes for an overview.
+typedef void(* xcm_attr_cb) (const char *attr_name, enum xcm_attr_type type, void *value, size_t value_len, void *cb_data) | +
The signature of the user-supplied callback used in xcm_attr_get_all().
+ +int xcm_attr_set | +( | +struct xcm_socket * | +s, | +
+ | + | const char * | +name, | +
+ | + | enum xcm_attr_type | +type, | +
+ | + | const void * | +value, | +
+ | + | size_t | +len | +
+ | ) | ++ |
Sets the value of a socket attribute.
+Only attributes marked as writable may be set. For a list of available attributes for different socket and transport types, see Generic Attributes, TCP Socket Attributes and TLS Socket Attributes.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[in] | type | The value type of the new value. |
[in] | value | The new value. |
[in] | value_len | The length of the value. |
errno | Description |
---|---|
ENOENT | The attribute does not exist. |
EACCES | The attribute exists, but is read-only. |
EINVAL | The attribute name is too long, the attribute value type, value or value length is not valid for the specified attribute. |
int xcm_attr_set_bool | +( | +struct xcm_socket * | +s, | +
+ | + | const char * | +name, | +
+ | + | bool | +value | +
+ | ) | ++ |
Sets the value of a boolean socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[in] | value | The new boolean value. |
See xcm_attr_set() for possible errno values.
+ +int xcm_attr_set_int64 | +( | +struct xcm_socket * | +s, | +
+ | + | const char * | +name, | +
+ | + | int64_t | +value | +
+ | ) | ++ |
Sets the value of an integer socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[in] | value | The new integer value. |
See xcm_attr_set() for possible errno values.
+ +int xcm_attr_set_str | +( | +struct xcm_socket * | +s, | +
+ | + | const char * | +name, | +
+ | + | const char * | +value | +
+ | ) | ++ |
Sets the value of a string socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[in] | value | The new string value. |
See xcm_attr_set() for possible errno values.
+ +int xcm_attr_get | +( | +struct xcm_socket * | +s, | +
+ | + | const char * | +name, | +
+ | + | enum xcm_attr_type * | +type, | +
+ | + | void * | +value, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Retrieves the value of a socket attribute.
+For a list of available attributes for different socket and transport types, see Generic Attributes, TCP Socket Attributes and TLS Socket Attributes.
+For a description of the C types and buffer capacity requirements of the attribute types, see xcm_attr_types.h.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[out] | type | A pointer to a location where the type of the attribute will be stored. May be left to NULL, in case the type is known a priori. |
[out] | value | A user-supplied buffer where the value of the attribute will be stored. |
[in] | capacity | The length of the buffer (in bytes). |
errno | Description |
---|---|
ENOENT | The attribute does not exist. |
EACCES | The attribute exists, but is write-only. |
EOVERFLOW | The user-supplied buffer was too small to fit the value. |
int xcm_attr_get_bool | +( | +struct xcm_socket * | +s, | +
+ | + | const char * | +name, | +
+ | + | bool * | +value | +
+ | ) | ++ |
Retrieves the value of a boolean socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[out] | value | A user-supplied buffer where the value of the attribute will be stored. |
errno | Description |
---|---|
ENOENT | The attribute does not exist, or is not boolean. |
See xcm_attr_get() for other possible errno values.
+ +int xcm_attr_get_int64 | +( | +struct xcm_socket * | +s, | +
+ | + | const char * | +name, | +
+ | + | int64_t * | +value | +
+ | ) | ++ |
Retrieves the value of an integer socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[out] | value | A user-supplied buffer where the value of the attribute will be stored. |
errno | Description |
---|---|
ENOENT | The attribute does not exist, or is not an integer. |
See xcm_attr_get() for other possible errno values.
+ +int xcm_attr_get_str | +( | +struct xcm_socket * | +s, | +
+ | + | const char * | +name, | +
+ | + | char * | +value, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Retrieves the value of a string socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[out] | value | A user-supplied buffer where the string value of the attribute will be stored. |
[in] | capacity | The length of the buffer (in bytes). |
errno | Description |
---|---|
ENOENT | The attribute does not exist, or is not a string. |
See xcm_attr_get() for other possible errno values.
+ +void xcm_attr_get_all | +( | +struct xcm_socket * | +socket, | +
+ | + | xcm_attr_cb | +cb, | +
+ | + | void * | +cb_data | +
+ | ) | ++ |
Retrieves all XCM socket attributes.
+This function retrieves all available attribute names, types and their current values on a particular connection or server socket.
+The memory locations refered to by the attr_name and attr_value pointers is only guaranteed to be valid for the execution of the callback. If needed later, they need to be copied.
+[in] | socket | The connection or server socket. |
[in] | cb | The function to be called for every attribute on the socket. |
[in] | cb_data | An opaque (for XCM) pointer returned back to the application in the callback. cb_data may be NULL. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the XCM attribute map API. +More...
+ +Go to the source code of this file.
++Typedefs | |
typedef void(* | xcm_attr_map_foreach_cb) (const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len, void *user) |
+Functions | |
struct xcm_attr_map * | xcm_attr_map_create (void) |
struct xcm_attr_map * | xcm_attr_map_clone (const struct xcm_attr_map *original) |
void | xcm_attr_map_add (struct xcm_attr_map *attr_map, const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len) |
void | xcm_attr_map_add_bool (struct xcm_attr_map *attr_map, const char *attr_name, bool attr_value) |
void | xcm_attr_map_add_int64 (struct xcm_attr_map *attr_map, const char *attr_name, int64_t attr_value) |
void | xcm_attr_map_add_str (struct xcm_attr_map *attr_map, const char *attr_name, const char *attr_value) |
const void * | xcm_attr_map_get (const struct xcm_attr_map *attr_map, const char *attr_name, enum xcm_attr_type *attr_type, size_t *attr_value_len) |
const bool * | xcm_attr_map_get_bool (const struct xcm_attr_map *attr_map, const char *attr_name) |
const int64_t * | xcm_attr_map_get_int64 (const struct xcm_attr_map *attr_map, const char *attr_name) |
const char * | xcm_attr_map_get_str (const struct xcm_attr_map *attr_map, const char *attr_name) |
bool | xcm_attr_map_exists (const struct xcm_attr_map *attr_map, const char *attr_name) |
void | xcm_attr_map_del (struct xcm_attr_map *attr_map, const char *attr_name) |
size_t | xcm_attr_map_size (const struct xcm_attr_map *attr_map) |
void | xcm_attr_map_foreach (const struct xcm_attr_map *attr_map, xcm_attr_map_foreach_cb cb, void *user) |
bool | xcm_attr_map_equal (const struct xcm_attr_map *attr_map_a, const struct xcm_attr_map *attr_map_b) |
void | xcm_attr_map_destroy (struct xcm_attr_map *attr_map) |
This file contains the XCM attribute map API.
+A XCM attribute map is a set of key-value pairs. The key is an attribute name in the form of a string. One key maps to at most one value. The attribute value is either a boolean, a signed 64-bit integer, a string, or a variable-length binary object.
+typedef void(* xcm_attr_map_foreach_cb) (const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len, void *user) | +
Callback function prototype used for iteration.
+ +struct xcm_attr_map * xcm_attr_map_create | +( | +void | +) | ++ |
Create an attribute map instance.
+struct xcm_attr_map * xcm_attr_map_clone | +( | +const struct xcm_attr_map * | +original | ) | ++ |
Create a copy of an attribute map instance.
+[in] | attr_map | The original attribute map instance, to be copied. |
void xcm_attr_map_add | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | enum xcm_attr_type | +attr_type, | +
+ | + | const void * | +attr_value, | +
+ | + | size_t | +attr_value_len | +
+ | ) | ++ |
Associate a key with a value.
+This function associates the attribute key attr_name
to the attribute value attr_value
in the attribute map attr_map
. If the key attr_name
already exists, its value is replaced.
Both the key and the value will be copied, and thus attr_name
and attr_value
will still be owned by the caller at call completion.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_type | The type of the value to be added. |
[in] | attr_value | The value of the attribute to be added. |
[in] | attr_value_len | The length (in bytes) of the value. |
void xcm_attr_map_add_bool | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | bool | +attr_value | +
+ | ) | ++ |
Associate a key with a boolean value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The boolean value of the attribute to be added. |
void xcm_attr_map_add_int64 | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | int64_t | +attr_value | +
+ | ) | ++ |
Associate a key with a 64-bit signed integer value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The integer value of the attribute to be added. |
void xcm_attr_map_add_str | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | const char * | +attr_value | +
+ | ) | ++ |
Associate a key with a string value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The string value of the attribute to be added. |
const void * xcm_attr_map_get | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | enum xcm_attr_type * | +attr_type, | +
+ | + | size_t * | +attr_value_len | +
+ | ) | ++ |
Retrieve the value associated with a particular key.
+This function retrieves the attribute value, value type and value length of the attribute attr_name
, in case it exists.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
[out] | attr_type | A pointer to a buffer where the value type will be stored, or NULL. |
[out] | attr_value_len | A pointer to a buffer where the length (in bytes) of the value will be stored, or NULL. |
const bool * xcm_attr_map_get_bool | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the boolean value associated with a particular key.
+This function retrieves the boolean attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_bool.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
const int64_t * xcm_attr_map_get_int64 | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the integer value associated with a particular key.
+This function retrieves the 64-bit signed integer attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_int64.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
const char * xcm_attr_map_get_str | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the string value associated with a particular key.
+This function retrieves the NUL-terminated string attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_str.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
bool xcm_attr_map_exists | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Check if an attribute named attr_name
exists in the attribute map.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute. |
void xcm_attr_map_del | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Removes an attribute from the attribute map.
+This function deletes the attribute attr_name
, in case it exists.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be deleted. |
size_t xcm_attr_map_size | +( | +const struct xcm_attr_map * | +attr_map | ) | ++ |
Returns the number of attributes in the attribute map.
+[in] | attr_map | The attribute map instance. |
attr_map
. void xcm_attr_map_foreach | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | xcm_attr_map_foreach_cb | +cb, | +
+ | + | void * | +user | +
+ | ) | ++ |
Iterates over all attributes in a map.
+This function calls the supplied callback function cb
for each attribute in attr_map
.
The map may not be modified during iteration.
+[in] | attr_map | The attribute map instance. |
[in] | cb | The callback function. |
[in] | user | An opaque pointer, supplied back to the application in every cb call. |
bool xcm_attr_map_equal | +( | +const struct xcm_attr_map * | +attr_map_a, | +
+ | + | const struct xcm_attr_map * | +attr_map_b | +
+ | ) | ++ |
Compares two attribute maps for equality (by value).
+[in] | attr_map_a | An attribute map instance. |
[in] | attr_map_b | An attribute map instance. |
attr_map_a
and attr_map_a
are equal, false otherwise. void xcm_attr_map_destroy | +( | +struct xcm_attr_map * | +attr_map | ) | ++ |
Destroys an attribute map instance.
+This function destroys the attribute map instance and frees all the resources associated with it.
+[in] | attr_map | The attribute map instance, or NULL. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains type definitions for the XCM attribute access API. +More...
+ +Go to the source code of this file.
++Enumerations | |
enum | xcm_attr_type { xcm_attr_type_bool = 1 +, xcm_attr_type_int64 = 2 +, xcm_attr_type_str = 3 +, xcm_attr_type_bin = 4 + } |
This file contains type definitions for the XCM attribute access API.
+enum xcm_attr_type | +
Enumeration representing the different attribute value types.
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains obsolete parts of the XCM core API. +More...
+ +Go to the source code of this file.
++Macros | |
#define | XCM_FD_READABLE (1<<0) |
#define | XCM_FD_WRITABLE (1<<1) |
#define | XCM_FD_EXCEPTION (1<<2) |
+Functions | |
int | xcm_want (struct xcm_socket *socket, int condition, int *fds, int *events, size_t capacity) |
This file contains obsolete parts of the XCM core API.
+It should not be included directly, but rather only via <xcm.h>.
+#define XCM_FD_READABLE (1<<0) | +
Flag bit denoting a readable fd event in xcm_want().
+ +#define XCM_FD_WRITABLE (1<<1) | +
Flag bit denoting a writable fd event.
+ +#define XCM_FD_EXCEPTION (1<<2) | +
Flag bit denoting a exception fd event.
+ +int xcm_want | +( | +struct xcm_socket * | +socket, | +
+ | + | int | +condition, | +
+ | + | int * | +fds, | +
+ | + | int * | +events, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Query the socket what events on which file descriptors it's waiting for.
+Please note: this function is obsolete, replaced by xcm_fd() and xcm_await().
+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.
+With xcm_want(), the application will inform the XCM socket what condition it's waiting for (i.e. what XCM operation it wants to perform), and in return the XCM socket will provide a set of file descriptors and, for each fd, information on what type of event on that fd it require to make progress. Progress can mean both progress toward the goal of reaching the application's desired socket condition, or finishing any outstanding task the XCM socket has.
+In case any of the conditions the application is asking for are believed to be already met, the xcm_want() call will return 0.
+In case the XCM socket has no outstanding tasks, and the application is not asking for any operation that the XCM socket believes it can't immediate fulfill, the call will return 0.
+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.
+Note that XCM may ask the application to wait for the connection's fd or fds to become writable, even if the application is waiting to receive a message. It may also ask the application to wait for the connection's fd to become readable, even if the application is attemting to send a messaging. For the quirks of xcm_want(), see io_waiting.
+Even though the conditions for a particular connection socket are met (fd is becoming writable, for example), there's no guarantee that the xcm_send() or xcm_receive() won't block (or in case of non-blocking mode, won't fail and set EAGAIN).
+The XCM socket fds may only be used with select(). Supplying this fd to any other OS calls (such as setsockopt(2), read(2) etc) is prohibited.
+The information received on which fd to use, and what events on that fd are relevant for the connection socket in its current state, are only valid until more xcm_* calls are made on this socket. See Finishing Outstanding Tasks for more information.
+The fd is an positive integer, unique within this process.
+The condition parameter is a bitmask, with the bits being XCM_SO_RECEIVABLE, XCM_SO_SENDABLE, and/or XCM_SO_ACCEPTABLE. If no bits are set, the application is not interested in anything beyond this XCM socket to finish any outstanding task.
+Each element in the events array is an int used as a bitmask. The bitmask at position N in the events array represents the file descriptor events the XCM transport is waiting for, for fd at position N in the fds array. The bits are XCM_FD_READABLE, XCM_FD_WRITABLE and/or XCM_FD_EXCEPTION. At least one bit is always set.
+If a socket is waiting for multiple events (for example, both readable and writable on the same fd, or readable on one fd, and writeable on another), the condition is met whenever any of the events occur (as oppose to all events).
+[in] | socket | The XCM socket. |
[in] | condition | The condition the application is waiting for. |
[out] | fds | An user-supplied array to store the fds. |
[out] | events | An user-supplied array of int to store the bitmask of each of the fds in the fds array. |
[in] | capacity | The length of the fds and events arrays. |
errno | Description |
---|---|
EOVERFLOW | The user-supplied buffer was too small to fit the socket's fds. |
EINVAL | The socket is not in blocking mode, or the condition bits are invalid. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains functions and macros to retrieve XCM version information. The library (i.e., implementation) version uses the semver convention. +More...
+ +Go to the source code of this file.
++Macros | |
#define | XCM_VERSION_MAJOR 1 |
#define | XCM_VERSION_MINOR 5 |
#define | XCM_VERSION_PATCH 0 |
#define | XCM_VERSION "1.5.0" |
#define | XCM_VERSION_API_MAJOR 0 |
#define | XCM_VERSION_API_MINOR 20 |
#define | XCM_VERSION_API "0.20" |
+Functions | |
unsigned int | xcm_version_major (void) |
unsigned int | xcm_version_minor (void) |
unsigned int | xcm_version_patch (void) |
const char * | xcm_version (void) |
unsigned int | xcm_version_api_major (void) |
unsigned int | xcm_version_api_minor (void) |
const char * | xcm_version_api (void) |
This file contains functions and macros to retrieve XCM version information. The library (i.e., implementation) version uses the semver convention.
+#define XCM_VERSION_MAJOR 1 | +
The XCM library major version.
+ +#define XCM_VERSION_MINOR 5 | +
The XCM library minor version.
+ +#define XCM_VERSION_PATCH 0 | +
The XCM library patch version.
+ +#define XCM_VERSION "1.5.0" | +
The complete XCM library version in string format.
+ +#define XCM_VERSION_API_MAJOR 0 | +
The XCM API/ABI major version this library version implements.
+ +#define XCM_VERSION_API_MINOR 20 | +
The XCM API/ABI minor version this library version implements.
+ +#define XCM_VERSION_API "0.20" | +
The complete XCM API version in string format.
+ +unsigned int xcm_version_major | +( | +void | +) | ++ |
Retrieves the library major version.
+This function returns the implementation major version of the library used at run time.
+ +unsigned int xcm_version_minor | +( | +void | +) | ++ |
Retrieves the library minor version.
+This function returns the implementation minor version of the library used at run time.
+ +unsigned int xcm_version_patch | +( | +void | +) | ++ |
Retrieves the library patch version.
+This function returns the implementation patch version of the library used at run time.
+ +const char * xcm_version | +( | +void | +) | ++ |
Retrieves the library version as a string.
+This function returns the version of the library used at run time, in string format.
+The string returned is statically allocated, and thus must not be free'd by the caller.
+ +unsigned int xcm_version_api_major | +( | +void | +) | ++ |
Retrieves the XCM API major version.
+This function returns the API major version of the library used at run time adheres to.
+ +unsigned int xcm_version_api_minor | +( | +void | +) | ++ |
Retrieves the XCM API minor version.
+This function returns the API minor version of the library used at run time adheres to.
+ +const char * xcm_version_api | +( | +void | +) | ++ |
Retrieves the library API version as a string.
+This function returns the API version of the library used at run time adheres to.
+The string returned is statically allocated, and thus must not be free'd by the caller.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
Cxcm_addr_host | |
Cxcm_addr_ip |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Files | |
xcm.h | |
This file contains the core Extensible Connection-oriented Messaging (XCM) API. | |
xcm_addr.h | |
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses. | |
xcm_attr.h | |
This file contains the XCM attribute access API. See Socket Attributes for an overview. | |
xcm_attr_map.h | |
This file contains the XCM attribute map API. | |
xcm_attr_types.h | |
This file contains type definitions for the XCM attribute access API. | |
xcm_compat.h | |
This file contains obsolete parts of the XCM core API. | |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
▼ include | |
xcm.h | This file contains the core Extensible Connection-oriented Messaging (XCM) API |
xcm_addr.h | This is an API for building and parsing Connection-oriented Messaging (XCM) addresses |
xcm_attr.h | This file contains the XCM attribute access API. See Socket Attributes for an overview |
xcm_attr_map.h | This file contains the XCM attribute map API |
xcm_attr_types.h | This file contains type definitions for the XCM attribute access API |
xcm_compat.h | This file contains obsolete parts of the XCM core API |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Macros | |
#define | XCM_VERSION_API_MAJOR 0 |
#define | XCM_VERSION_API_MINOR 22 |
#define | XCM_VERSION_API "0.22" |
#define XCM_VERSION_API_MAJOR 0 | +
The XCM API/ABI major version this library version implements.
+ +#define XCM_VERSION_API_MINOR 22 | +
The XCM API/ABI minor version this library version implements.
+ +#define XCM_VERSION_API "0.22" | +
The complete XCM API version in string format.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Macros | |
#define | XCM_VERSION_MAJOR 1 |
#define | XCM_VERSION_MINOR 7 |
#define | XCM_VERSION_PATCH 0 |
#define | XCM_VERSION "1.7.0" |
#define XCM_VERSION_MAJOR 1 | +
The XCM library major version.
+ +#define XCM_VERSION_MINOR 7 | +
The XCM library minor version.
+ +#define XCM_VERSION_PATCH 0 | +
The XCM library patch version.
+ +#define XCM_VERSION "1.7.0" | +
The complete XCM library version in string format.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This is the documentation for the Extensible Connection-oriented Messaging (XCM) programming APIs.
+XCM consists the core API in xcm.h, an address helper library API in xcm_addr.h, and the attribute APIs in xcm_attr.h and xcm_attr_map.h. Obsolete, but still present, functions are available in xcm_compat.h
+The low API/ABI version number is purely a result of all XCM releases being backward compatible, and thus left the major version at 0. It's not to be taken as a sign of immaturity. The API and its implementation have been stable for years.
+XCM provides a connection-oriented, reliable messaging service with in-order delivery. The design goal is to allow for a straight forward mapping to TCP and TLS, but also supporting efficient inter-process commmunication (IPC) mechanisms for local communication.
+XCM reuses much of the terminology of the BSD Sockets API. Unlike the BSD Socket API, XCM has uniform semantics across all underlying transports.
+XCM has a client-server model. A server creates a server socket (with xcm_server()) bound to a specific address (in case of TCP or TLS, a TCP port on a particular IP interface), after which clients may initiate connections to the server. On a successful attempt, two connection sockets will be created; one on the server side (returned from xcm_accept()), and one of the client side (returned from xcm_connect()). Thus, a server serving multiple clients will have multiple sockets; one server socket and N connection sockets, one each for every client. A client will typically have one connection socket for each server it is connected to.
+Messages are always sent and received on a particular connection socket (and never on a server socket).
+In-order delivery - that messages arrive at the recipient in the same order they were sent by the sender side - is guaranteed, but only for messages sent on the same connection.
+XCM transports support flow control. Thus, if the sender message rate or bandwidth is higher than the network or the receiver can handle on a particular connection, xcm_send() in the sender process will eventually block (or return an error EAGAIN, if in non-blocking mode). Unless XCM is used for bulk data transfer (as oppose to signaling traffic), xcm_send() blocking because of slow network or a slow receiver should be rare indeed in practice. TCP, TLS, and UNIX domain socket transports all have large enough windows and socket buffers to allow a large amount of outstanding data.
+In XCM, the application is in control of which transport will be used, with the address supplied to xcm_connect() and xcm_server() including both the transport name and the transport address.
+However, there is nothing preventing a XCM transport to use a more an abstract addressing format, and internally include multiple "physical" IPC transport options. This model is used by the UTLS Transport.
+Addresses are represented as strings with the following general syntax: <transport-name>:<transport-address>
For the UX UNIX Domain Socket transport, the addresses has this more specific form:
+
The addresses of the UXF UNIX Domain Socket transport variant have the following format:
+
For the TCP, TLS, UTLS and SCTP transports the syntax is:
+
'*' is a shorthand for '0.0.0.0' (i.e. bind to all IPv4 interfaces). '[*]' is the IPv6 equivalent, creating a server socket accepting connections on all IPv4 and IPv6 addresses.
+Some examples addresses:
For TCP, TLS, UTLS and SCTP server socket addresses, the port can be set to 0, in which case XCM (or rather, the Linux kernel) will allocate a free TCP port from the local port range.
+For transports allowing a DNS domain name as a part of the address, the transport will attempt resoĺv the name to an IP address. A DNS domain name may resolv to zero or more IPv4 addresses and/or zero or more IPv6 addresses. XCM relies on the operating system to prioritize between IPv4 and IPv6.
+XCM accepts IPv4 addresses in the dotted-decimal format
XCM allows only complete addresses with three '.', and not the archaic, classful, forms, where some bytes where left out, and thus the address contained fewer separators.
+XCM transports attempt to detect a number of conditions which can lead to lost connectivity, and does so even on idle connections.
+If the remote end closes the connection, the local xcm_receive() will return 0. If the process on the remote end crashed, xcm_receive() will return -1 and set errno ECONNRESET. If network connectivity to the remote end is lost, xcm_receive() will return -1 and errno will be set to ETIMEDOUT.
+In general, XCM follow the UNIX system API tradition when it comes to error handling. Where possible, errors are signaled to the application by using unused parts of the value range of the function return type. For functions returning signed integer types, this means the value of -1 (in case -1 is not a valid return value). For functions returning pointers, NULL is used to signal that an error has occurred. For functions where neither -1 or NULL can be used, or where the function does not return anything (side-effect only functions), an 'int' is used as the return type, and is used purely for the purpose to signal success (value 0), or an error (-1) to the application.
+The actual error code is stored in the thread-local errno variable. The error codes are those from the fixed set of errno values defined by POSIX, found in errno.h. Standard functions such as perror() and strerror() may be used to turn the code into a human-readable string.
+In non-blocking operation, given the fact the actual transmission might be defered (and the message buffered in the XCM layer), and that message receive processing might happen before the application has called receive, the error being signaled at the point of a certain XCM call might not be a direct result of the requested operation, but rather an error discovered previously.
+The documentation for xcm_finish() includes a list of generic error codes, applicable xcm_connect(), xcm_accept(), xcm_send() and xcm_receive().
+Also, for errors resulting in an unusable connection, repeated calls will produce the same errno.
+In UNIX-style event-driven programming, a single application thread handles multiple clients (and thus multiple XCM connection sockets) and the task of accepting new clients on the XCM server socket concurrently (although not in parallel). To wait for events from multiple sources, an I/O multiplexing facility such as select(2), poll(2) or epoll(2) is used.
+Each XCM socket is represented by a single fd, retrieved with xcm_fd(). The fd number and underlying file object is stable across the life-time of the socket.
+On BSD Sockets, the socket fd being readable means it's likely that the application can successfully read data from the socket. Similarily, a fd marked writable by, for example, poll() means that the application is likely to be able to write data to the BSD Sockets fd. For an application using XCM going into select(), it must always wait for all the fds its XCM sockets to become readable (e.g. being in the readfds
in the select() call), regardless what are their target conditions. Thus, even if the application is waiting for an opportunity to try to send a message on a XCM socket, or it doesn't want to do anything with the socket, it must wait for the socket fd to become readable. Not wanting to do nothing here means that the application has the xcm_await() condition set to 0, and is neither interested in waiting to call xcm_send(), xcm_receive(), nor xcm_accept() on the socket. An application may never leave a XCM socket unattended in the sense its fd is not in the set of fds passed to select() and/or xcm_send(), xcm_receive(), xcm_accept() or xcm_finish() are not called.
XCM is oblivious to what I/O multiplexing mechanism employed by the application. It may call select(), poll() or epoll_wait() directly, or make use of any of the many available event loop libraries (such as libevent). For simplicity, select() is used in this documentation to denote the whole family of Linux I/O multiplexing facilities.
+An event-driven application needs to set the XCM sockets it handles into non-blocking mode, by calling xcm_set_blocking(), setting the "xcm.blocking" socket attribute, or using the XCM_NONBLOCK flag in xcm_connect().
+For XCM sockets in non-blocking mode, all potentially blocking API calls related to XCM connections - xcm_connect(), xcm_accept(), xcm_send(), and xcm_receive() - finish immediately.
+For xcm_send(), xcm_connect() and xcm_accept(), XCM signaling success means that the XCM layer has accepted the request. It may or may not have completed the operation.
+In case the XCM_NONBLOCK flag is set in the xcm_connect() call, or in case the a XCM server socket is in non-blocking mode at the time of a xcm_accept() call, the newly created XCM connection returned to the application may be in a semi-operational state, with some internal processing and/or signaling with the remote peer still required before actual message transmission and reception may occur.
+The application may attempt to send or receive messages on such semi-operational connections.
+There are ways for an application to determine when connection establishment or the task of accepting a new client have completed. See Finishing Outstanding Tasks for more information.
+To receive a message on a XCM connection socket in non-blocking mode, the application may need to wait for the right conditions to arise (i.e. a message being available). The application needs to inform the socket that it wants to receive by calling xcm_await() with the XCM_SO_RECEIVABLE
bit in the condition
bit mask set. It will pass the fd it received from xcm_fd() into select(), asking to get notified when the fd becomes readable. When select() marks the socket fd as readable, the application should issue xcm_receive() to attempt to retrieve a message.
xcm_receive() may also called on speculation, prior to any select() call, to poll the socket for incoming messages.
+A XCM connection socket may have a number of messages buffered, and applications should generally, for optimal performance, repeat xcm_receive() until it returns an error, and errno is set to EAGAIN.
+Similarly to receiving a message, an application may set the XCM_SO_SENDABLE
bit in the condition
bit mask, if it wants to wait for a socket state where it's likely it can successfully send a message. When select() marks the socket fd as readable, the application should attempt to send a message.
Just like with xcm_receive(), it may also choose to issue a xcm_send() call on speculation (i.e. without going into select()), which is often a good idea for performance reasons.
+For send operations on non-blocking connection sockets, XCM may buffer whole or part of the message before transmission to the lower layer. This may be due to socket output buffer underrun, or the need for some in-band signaling, like cryptographic key exchange, to happen before the transmission of the complete message may finish. The XCM layer will (re-)attempt to hand the message over to the lower layer at a future call to xcm_finish(), xcm_send(), or xcm_receive().
+For applications wishing to determine when all buffered messages have successfully be deliver to the lower layer, they may use xcm_finish() to do so. Normally, applications aren't expected to require this kind of control. Please also note that the fact a message has left the XCM layer doesn't necessarily mean it has successfully been delivered to the recipient.
+xcm_connect(), xcm_accept(), xcm_send() may all leave the socket in a state where work is initiated, but not completed. In addition, the socket may have pending internal tasks, such flushing the output buffer into the TCP/IP stack, processing XCM control interface messages, or finishing the TLS hand shake procedure.
+After waking up from a select() call, where a particular XCM non-blocking socket's fd is marked readable, the application must, if no xcm_send(), xcm_receive() or xcm_accept() calls are to be made, call xcm_finish(). This is to allow the socket to finish any outstanding tasks, even in the case the application has no immediate plans for the socket.
+Prior to changing a socket from non-blocking to blocking mode, any outstanding tasks should be finished, or otherwise the switch might cause xcm_set_blocking() to return -1 and set errno to EAGAIN.
+For example, if a server socket's desired condition has been set (with xcm_await()) to XCM_SO_ACCEPTABLE
, and the application wakes up from select() with the socket's fd marked readable, a call to xcm_accept() may still not produce a new connection socket.
The same holds true when reaching XCM_SO_RECEIVABLE
and a xcm_receive() call is made, and XCM_SO_SENDABLE
and calls to xcm_send().
In this example, the application connects and tries to send a message, before knowing if the connection is actually established. This may fail (for example, in case TCP and/or TLS-level connection establishement has not yet been completed), in which case the application will fall back and wait with the use of xcm_await(), xcm_fd() and select().
+In case the application wants to know when the connection establishment has finished, it may use xcm_finish() to do so, like in the below example sequence.
+While connecting to a server socket, the client's connection attempt may be refused immediately.
+In many cases, the application is handed a connection socket before the connection establishment is completed. Any errors occuring during this process is handed over to the application at the next XCM call; would it be xcm_finish(), xcm_send() or xcm_receive().
+In this example the application flushes any internal XCM buffers before shutting down the connection, to ensure that any buffered messages are delivered to the lower layer.
+In this sequence, a server accepts a new connection, and continues to attempt to receive a message on this connection, while still, concurrently, is ready to accept more clients on the server socket.
+Tied to an XCM server or connection socket is a set of key-value pairs known as attributes. Which attributes are available varies across different transports, and different socket types.
+An attribute's name is a string, and follows a hierarchical naming schema. For example, all generic XCM attributes, available in all transports, have the prefix "xcm.". Transport-specific attributes are prefixed with the transport or protocol name (e.g. "tcp." for TCP-specific attributes applicable to the TLS and TCP transports).
+An attribute may be read-only, write-only or available both for reading and writing. This is referred to as the attribute's mode. The mode may vary across the lifetime of the socket. For example, an attribute may be writable at the time of the xcm_connect() call, and read-only thereafter.
+The attribute value is coded in the native C data type and byte order. Strings are NUL-terminated, and the NUL character is included in the length of the attribute. There are four value types; a boolean type, a 64-bit signed integer type, a string type and a type for arbitrary binary data. See xcm_attr_types.h for details.
+The attribute access API is in xcm_attr.h.
+Retrieving an integer attribute's value may look like this:
Changing an integer attribyte value may be done in the following manner:
Both of these examples are missing error handling.
+XCM allows supplying a set of writable attributes at the time of socket creation, by using the xcm_connect_a(), xcm_server_a(), or xcm_accept_a() functions.
+The attribute sets are represented by the xcm_attr_map
type in xcm_attr_map.h.
An example:
These attributes are expected to be found on XCM sockets regardless of transport type.
+For TCP transport-specific attributes, see TCP Socket Attributes, and for TLS, see TLS Socket Attributes.
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
xcm.type | All | String | R | The socket type: "server" or "connection". |
xcm.transport | All | String | R | The transport type. |
xcm.local_addr | All | String | RW | The local address of a socket. Writable only if supplied to xcm_connect_a(). |
xcm.blocking | All | Boolean | RW | See xcm_set_blocking() and xcm_is_blocking(). |
xcm.remote_addr | Connection | String | R | See xcm_remote_addr(). |
xcm.max_msg_size | Connection | Integer | R | The maximum size of any message transported by this connection. |
XCM has a set of generic message counters, which keeps track of the number of messages crossing a certain boundary for a particular connection, and a sum of their size.
+Some of the message and byte counter attributes use the concept of a "lower layer". What this means depends on the transport. For the UX And TCP transports, it is the Linux kernel. For example, for TCP, if the xcm.to_lower_msgs is incremented, it means that XCM has successfully sent the complete message to the kernel's networking stack for further processing. It does not means it has reached the receiving process. It may have, but it also may be sitting on the local or remote socket buffer, on a NIC queue, or be in-transmit in the network. For TLS, the lower layer is OpenSSL.
+All the "xcm.*_bytes" counters count the length of the XCM message payload (as in the length field in xcm_send()), and thus does not include any underlying headers.
+The message counters only count messages succesfully sent and/or received.
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
xcm.from_app_msgs | Connection | Integer | R | Messages sent from the application and accepted into XCM. |
xcm.from_app_bytes | Connection | Integer | R | The sum of the size of all messages counted by xcm.from_app_msgs. |
xcm.to_app_msgs | Connection | Integer | R | Messages delivered from XCM to the application. |
xcm.to_app_bytes | Connection | Integer | R | The sum of the size of all messages counter by xcm.to_app_msgs. |
xcm.from_lower_msgs | Connection | Integer | R | Messages received by XCM from the lower layer. |
xcm.from_lower_bytes | Connection | Integer | R | The sum of the size of all messages counted by xcm.from_lower_msgs. |
xcm.to_lower_msgs | Connection | Integer | R | Messages successfully sent by XCM into the lower layer. |
xcm.to_lower_bytes | Connection | Integer | R | The sum of the size of all messages counted by xcm.to_lower_msgs. |
XCM includes a control interface, which allows iteration over the OS instance's XCM server and connection sockets (for processes with the appropriate permissions), and access to their attributes (see Socket Attributes).
+The control interface is optional by means of build-time configuration.
+For each XCM server or connection socket, there is a corresponding UNIX domain socket which is used for control signaling (i.e. state retrieval).
+By default, the control interface's UNIX domain sockets are stored in the /run/xcm/ctl
directory.
This directory needs to be created prior to running any XCM applications (for the control interface to worker properly) and should be writable for all XCM users.
+A particular process using XCM may be configured to use a non-default directory for storing the UNIX domain sockets used for the control interface by means of setting the XCM_CTL
variable. Please note that using this setting will cause the XCM connections to be not visible globally on the OS instance (unless all other XCM-using processes also are using this non-default directory).
Generally, since the application is left unaware (from an API perspective) of the existence of the control interface, errors are not reported up to the application. They are however logged.
+Application threads owning XCM sockets, but which are busy with non-XCM processing for a long duration of time, or otherwise are leaving their XCM sockets unattended to (in violation of XCM API contract), will not respond on the control interface's UNIX domain sockets (corresponding to their XCM sockets). Only the presence of these sockets may be detected, but their state cannot be retrieved.
+Internally, the XCM implementation has control interface client library, but this library's API is not public at this point.
+XCM includes a command-line program xcmctl
which uses the Control API to iterate of the system's current XCM sockets, and allow access (primarily for debugging purposes) to the sockets' attributes.
Unlike BSD sockets, a XCM socket may not be shared among different threads without synchronization external to XCM. With proper external serialization, a socket may be shared by different threads in the same process, although it might provide difficult in practice since a thread in a blocking XCM function will continue to hold the lock, and thus preventing other threads from accessing the socket at all.
+For non-blocking sockets, threads sharing a socket need to agree on what is the appropriate socket condition
to wait for. When this condition is met, all threads are woken up, returning from select().
It is safe to "give away" a XCM socket from one thread to another, provided the appropriate memory fences are used.
+These limitations (compared to BSD Sockets) are in place to allow socket state outside the kernel (which is required for TCP framing and TLS).
+Sharing a XCM socket between threads in different processes is not possible.
+After a fork() call, either of the two process (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 not call any other XCM API call than xcm_cleanup(), which frees local memory tied to this socket in the non-owner's process address space, without impacting the connection state in the owner process.
+The core XCM API functions are oblivious to the transports used. However, the support for building, and parsing addresses are available only for a set of pre-defined set of transports. There is nothing preventing xcm_addr.h from being extended, and also nothing prevents an alternative XCM implementation to include more transports without extending the address helper API.
+The UX transport uses UNIX Domain (AF_UNIX, also known as AF_LOCAL) Sockets.
+UX sockets may only be used with the same OS instance (or, more specifically, between processes in the same Linux kernel network namespace).
+UNIX Domain Sockets comes in a number of flavors, and XCM uses the SOCK_SEQPACKET variety. SOCK_SEQPACKET sockets are connection-oriented, preserves message boundaries and delivers messages in the same order they were sent; perfectly matching XCM semantics and provides for an near-trivial mapping.
+UX is the most efficient of the XCM transports.
+The standard UNIX Domain Sockets as defined by POSIX uses the file system as its namespace, with the sockets also being files. However, for simplicity and to avoid situations where stale socket files (originating from crashed processes) causing problems, the UX transport uses a Linux-specific extension, allowing a private UNIX Domain Socket namespace. This is known as the abstract namespace (see the unix(7) man page for details). With the abstract namespace, server socket address allocation has the same life time as TCP ports (i.e. if the process dies, the address is free'd).
+The UX transport enables the SO_PASSCRED BSD socket option, to give the remote peer a name (which UNIX domain connection socket doesn't have by default). This is for debugging and observability purposes. Without a remote peer name, in server processes with multiple incoming connections to the same server socket, it's difficult to say which of the server-side connection sockets goes to which remote peer. The kernel-generated, unique, name is an integer in the form "%05x" (printf format). Applications using hardcoded UX addresses should avoid such names by, for example, using a prefix.
+The UTLS Transport also indirectly uses the UX namespace, so care should be taken to avoid any clashes between UX and UTLS sockets in the same network namespace.
+The UXF transport is identical to the UX transport, only it uses the standard POSIX naming mechanism. The name of a server socket is a file system path, and the socket is also a file.
+The UXF sockets resides in a file system namespace, as opposed to UX sockets, which live in a network namespace.
+Upon xcm_close(), the socket will be closed and the file removed. If an application crashes or otherwise fails to run xcm_close(), it will leave a file in the file system pointing toward a non-existing socket. This file will prevent the creation another server socket with the same name.
+The TCP transport uses the Transmission Control Protocol (TCP), by means of the BSD Sockets API.
+TCP is a byte-stream service, but the XCM TCP transport adds framing on top of the stream. A single-field 32-bit header containing the message length in network byte order is added to every message.
+TCP uses TCP Keepalive to detect lost network connectivity between the peers.
+The TCP transport supports IPv4 and IPv6.
+Since XCM is designed for signaling traffic, the TCP transport disables the Nagle algorithm of TCP to avoid its excessive latency.
+The read-only TCP attributes are retrieved from the kernel (struct tcp_info in linux/tcp.h).
+The read-write attributes are mapped directly to setsockopt() calls.
+See the tcp(7) manual page for a more detailed description of these attributes. The struct retrieved with TCP_INFO
is the basis for the read-only attributes. The read-write attributes are mapped to TCP_KEEP*
and TCP_USER_TIMEOUT
.
Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
tcp.rtt | Connection | Integer | R | The current TCP round-trip estimate (in us). |
tcp.total_retrans | Connection | Integer | R | The total number of retransmitted TCP segments. |
tcp.segs_in | Connection | Integer | R | The total number of segments received. |
tcp.segs_out | Connection | Integer | R | The total number of segments sent. |
tcp.keepalive | Connection | Boolean | RW | Controls if TCP keepalive is enabled. |
tcp.keepalive_time | Connection | Integer | RW | The time (in s) before the first keepalive probe is sent on an idle connection. |
tcp.keepalive_interval | Connection | Integer | RW | The time (in s) between keepalive probes. |
tcp.keepalive_count | Connection | Integer | RW | The number of keepalive probes sent before the connection is dropped. |
tcp.user_timeout | Connection | Integer | RW | The time (in s) before a connection is dropped due to unacknowledged data. |
tcp.segs_in
and tcp.segs_out
are only present when running XCM on Linux kernel 4.2 or later.The TLS transport uses TLS to provide a secure, private, two-way authenticated transport.
+TLS is a byte-stream service, but the XCM TLS transport adds framing in the same manner as does the XCM TCP transport.
+The TLS transport supports IPv4 and IPv6.
+The TLS transport disables the Nagle algorithm of TCP.
+The TLS transport reads the leaf certificate and its private key, from the file system, as well as a file containing all trusted CA certificates. Default paths are configured at build-time.
+TLS Socket Attributes may be used to override one or more of the default paths, on a per-socket basis. Paths set on server sockets are inherited by its connection sockets, but may in turn be overriden at the time of a xcm_accept_a() call, using the proper attributes.
+The default paths may also be overriden on a per-process basis by means of a UNIX environment variable. The current value of XCM_TLS_CERT
(at the time of xcm_connect() or xcm_accept()) determines the certificate directory used for that connection.
The TLS transport will, at the time of xcm_connect() or xcm_server(), look up the process' current network namespace, unless that file's path was given as a TLS Socket Attributes. If the namespace is given a name per the iproute2 convention, XCM will retrieve this name and use it in the certificate and key lookup.
+In case the certificate, key and trusted CA files are configured using TLS Socket Attributes, no network namespace lookup will be performed.
+In the certificate directory (either the compile-time default, or the directory specified with XCM_TLS_CERT
), the TLS transport expects the files to follow the following naming conventions (where <ns> is the namespace):
The private key is stored in:
The trusted CA certificates are stored in:
For the default namespace (or any other network namespace not named according to iproute2 standards), the certificate need to be stored in a file "cert.pem", the private key in "key.pem" and the trusted CA certificates in "tc.pem".
+In case the certificate, key or trusted CAs files are not in place (for a particular namespace), a xcm_server() call will return an error and set errno to EPROTO. The application may choose to retry at a later time.
+In case a certificate, private key, or trusted CAs file is modified, the new version of the file(s) will be used by new connections. Such a change does not affect already-established connections. The TLS transport works with differences between set of files, and thus the new generation of files need not nesserarily be newer (as in having a more recent file system mtime).
+The certificate, key and trusted CA certificates should be updated in an atomic manner, or XCM may end up using the certificate file from one generation of files and the key file from another, for example.
+One way of achieving an atomic update is to have the three files in a common directory. This certificate directory is then made a symbolic link to the directory where the actual files are located. Upon update, a new directory is created and populated, and the old symbolic link is replace an atomic manner (i.e. with rename(2)).
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
tls.cert_file | All | String | RW | The leaf certificate file. For connection sockets, writable only at socket creation. |
tls.key_file | All | String | RW | The leaf certificate private key file. For connection sockets, writable only at socket creation. |
tls.tc_file | All | String | RW | The trusted CA certificates bundle. For connection sockets, writable only at socket creation. |
tls.peer_subject_key_id | Connection | String | R | The X509v3 Subject Key Identifier of the remote peer, or a zero-length string in case the TLS connection is not established. |
In addition to the TLS-specific attributes, a TLS socket also has all the TCP Socket Attributes.
+The UTLS transport provides a hybrid transport, utilizing both the TLS and UX transports internally for actual connection establishment and message delivery.
+On the client side, at the time of xcm_connect(), the UTLS transport determines if the server socket can be reached by using the UX transport (i.e. if the server socket is located on the same OS instance, in the same network namespace). If not, UTLS will attempt to reach the server by means of the TLS transport.
+For a particular UTLS connection, either TLS or UX is used (never both). XCM connections to a particular UTLS server socket may be a mix of the two different types.
+For an UTLS server socket with the address utls:<ip>:<port>
, two underlying addresses will be allocated; tls:<ip>:<port>
and ux:<ip>:<port>
.
In case DNS is used: tls:<hostname>:<port>
and ux:<hostname>:<port>
.
A wildcard should never be used when creating a UTLS server socket.
+If a DNS hostname is used in place of the IP address, both the client and server need employ DNS, and also agree upon which hostname to use (in case there are several pointing at the same IP address).
+Failure to adhere to the above two rules will prevent a client from finding a local server. Such a client will instead establish a TLS connection to the server.
+The SCTP transport uses the Stream Control Transmission Protocol (SCTP). SCTP provides a reliable, message-oriented service. In-order delivery is optional, but to adhere to XCM semantics (and for other reasons) XCM leaves SCTP in-order delivery enabled.
+The SCTP transport utilizes the native Linux kernel's implementation of SCTP, via the BSD Socket API. The operating mode is such that there is a 1:1-mapping between an association and a socket (fd).
+The SCTP transport supports IPv4 and IPv6.
+To minimize latency, the SCTP transport disables the Nagle algorithm.
+Namespaces is a Linux kernel facility concept for creating multiple, independent namespaces for kernel resources of a certain kind.
+Linux Network Namespaces will affect all transports, including the UX transport.
+XCM has no explicit namespace support. Rather, the application is expected to use the Linux kernel facilities for this functionality (i.e. switch to the right namespace before xcm_server() och xcm_connect()).
+In case the system follows the iproute2 conventions in regards to network namespace naming, the TLS and UTLS transports support per-network namespace TLS certificates and private keys.
+XCM, in its current form, does not support binding to a local socket before doing connect() - something that is possible with BSD Sockets, but very rarely makes sense.
+XCM also doesn't have a sendmmsg() or recvmmsg() equivalent. Those could easily be added, and would provide some major performance improvements for applications that are sending or receiving multiple messages on the same connection on the same time. *mmsg() equivalents have been left out because there are strong doubts there are such applications.
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
#include <xcm_addr.h>
+Data Fields | ||
enum xcm_addr_type | type | |
union { | ||
+ struct xcm_addr_ip ip | ||
+ char name [254] | ||
}; | ||
Hostname or IPv4/IPv6 address data type.
+enum xcm_addr_type xcm_addr_host::type | +
Type tag
+ +union { ... } xcm_addr_host | +
Union containing the actual hostname, IPv4 or IPv6 address bytes
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
#include <xcm_addr.h>
+Data Fields | ||
sa_family_t | family | |
union { | ||
in_addr_t ip4 | ||
uint8_t ip6 [16] | ||
} | addr | |
IPv4 or IPv6 address data type.
+sa_family_t xcm_addr_ip::family | +
Type tag; AF_INET or AF_INET6
+ +in_addr_t xcm_addr_ip::ip4 | +
Contains the IPv4 address in network byte order (in case family is set to AF_INET).
+ +uint8_t xcm_addr_ip::ip6[16] | +
Contains the IPv6 address (in case family is set to AF_INET6).
+ +union { ... } xcm_addr_ip::addr | +
Union containing the actual IPv4 or a IPv6 address bytes
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
Library Version | |
API Version |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the core Extensible Connection-oriented Messaging (XCM) API. +More...
+#include <errno.h>
#include <stdbool.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 *conn_socket, const void *buf, size_t len) |
int | xcm_receive (struct xcm_socket *conn_socket, void *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) |
This file contains the core Extensible Connection-oriented Messaging (XCM) API.
+#define XCM_NONBLOCK (1<<0) | +
Flag used in xcm_connect()
+ +#define XCM_SO_RECEIVABLE (1<<0) | +
Flag bit denoting a socket where the application likely can receive a message.
+ +#define XCM_SO_SENDABLE (1<<1) | +
Flag bit denoting a socket where the application likely can send a message.
+ +#define XCM_SO_ACCEPTABLE (1<<2) | +
Flag bit denoting a socket with a pending incoming connection.
+ +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).
+[in] | remote_addr | The remote address which to connect. |
[in] | flags | Either 0, or XCM_NONBLOCK for a non-blocking connect. |
errno | Description |
---|---|
EINVAL | Invalid address format. |
ENOPROTOOPT | Transport protocol not available. |
EMFILE | The limit on the total number of open fds has been reached. |
ENOENT | DNS domain name resolution failed. |
See xcm_finish() for other possible errno values.
+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.
+[in] | remote_addr | The remote address which to connect. |
[in] | attrs | A set of attributes to be applied to the connection socket, or NULL. |
See xcm_connect() and xcm_attr_set() for possible errno values.
+ +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), a xcm_server() call also includes a blocking name resolution (e.g. gethostbyname()).
+[in] | local_addr | The local address to which this socket should be bound. |
errno | Description |
---|---|
EACCESS | Permission to create the socket is denied. |
EADDRINUSE | Local socket address is already in use. |
ENOMEM | Insufficient memory. |
EINVAL | Invalid address format. |
ENOPROTOOPT | Transport protocol not available. |
EMFILE | The limit on the total number of open fds has been reached. |
EPROTO | A protocol error occured. |
ENOENT | DNS domain name resolution failed. |
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.
+[in] | local_addr | The local address to which this socket should be bound. |
[in] | attrs | A set of attributes to be applied to the socket, or NULL. |
See xcm_server() and xcm_attr_set() for possible errno values.
+ +int xcm_close | +( | +struct xcm_socket * | +socket | ) | ++ |
Close an endpoint.
+This function close a 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.
+[in] | socket | The socket to be closed, or NULL (in case xcm_close() is a no-operation). |
void xcm_cleanup | +( | +struct xcm_socket * | +socket | ) | ++ |
Cleans up any local resources tied to a 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().
+[in] | socket | The socket which local resources are to be freed, or NULL (in case xcm_cleanup() is a no-operation). |
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.
+[in] | server_socket | The server socket on which to attempt to accept one pending connection. |
errno | Description |
---|---|
EMFILE | The limit on the total number of open fds has been reached. |
See xcm_finish() for other possible errno values.
+ +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.
+[in] | server_socket | The server socket on which to attempt to accept one pending connection. |
[in] | attrs | A set of attributes to be applied to the socket, or NULL. |
See xcm_accept() and xcm_attr_set() for possible errno values.
+ +int xcm_send | +( | +struct xcm_socket * | +conn_socket, | +
+ | + | const void * | +buf, | +
+ | + | size_t | +len | +
+ | ) | ++ |
Send message on a particular connection.
+The xcm_send() function is used to send a message out on a connection socket. A XCM connection goes from a client to a server, and this connection socket may represent either one of the two endpoints.
+[in] | conn_socket | The connection socket the message will be sent on. |
[in] | buf | A pointer to the message data buffer. |
[in] | len | The length of the message in bytes. Zero-length messages are not allowed. |
errno | Description |
---|---|
EMSGSIZE | Message is too large. See also Generic Attributes. |
See xcm_finish() for more errno values.
+ +int xcm_receive | +( | +struct xcm_socket * | +conn_socket, | +
+ | + | void * | +buf, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Receive message on a particular connection.
+The xcm_receive() function is used to receive message on a connection socket. A XCM connection goes from a client to a server, and this connection socket may represent either one of the two endpoints.
+If 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).
+[in] | conn_socket | The connection socket the message will receive be on. |
[out] | buf | The user-supplied buffer where the incoming message will be stored. |
[in] | capacity | The capacity in bytes of the buffer. |
See xcm_finish() for possible errno values.
+ +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.
+[in] | socket | The XCM socket. |
[in] | condition | The condition the application is waiting for. |
errno | Description |
---|---|
EINVAL | The socket is not in non-blocking mode, or the condition bits are invalid. |
int xcm_fd | +( | +struct xcm_socket * | +socket | ) | ++ |
Returns XCM socket fd.
+This call retrieves the XCM socket fd for a XCM socket 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.
+Please 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.
[in] | socket | The connection or server socket. |
errno | Description |
---|---|
EINVAL | The socket is not in non-blocking mode. |
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, xcm_accept() or xcm_send() call on a connection socket in non-blocking mode, wishing to finish outstanding processing related to that operation, 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.
+[in] | socket | The connection or server socket. |
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. |
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.
+[in] | socket | The socket. |
[in] | should_block | Set to true for blocking operation, false for non-blocking mode. |
errno | Description |
---|---|
EAGAIN | The connection socket has unfinished work that needs to completed before mode can be switched. |
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.
+[in] | socket | The socket. |
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.
+[in] | conn_socket | The connection socket. |
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.
+[in] | socket | A server or connection socket. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses. +More...
+#include <errno.h>
#include <inttypes.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <xcm_addr_compat.h>
Go to the source code of this file.
++Data Structures | |
struct | xcm_addr_ip |
struct | xcm_addr_host |
+Macros | |
#define | XCM_UTLS_PROTO "utls" |
#define | XCM_TLS_PROTO "tls" |
#define | XCM_TCP_PROTO "tcp" |
#define | XCM_SCTP_PROTO "sctp" |
#define | XCM_UX_PROTO "ux" |
#define | XCM_UXF_PROTO "uxf" |
+Enumerations | |
enum | xcm_addr_type { xcm_addr_type_name +, xcm_addr_type_ip + } |
+Functions | |
int | xcm_addr_parse_proto (const char *addr_s, char *proto, size_t capacity) |
int | xcm_addr_parse_utls (const char *utls_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_tls (const char *tls_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_tcp (const char *tcp_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_sctp (const char *sctp_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_ux (const char *ux_addr_s, char *ux_path, size_t capacity) |
int | xcm_addr_parse_uxf (const char *uxf_addr_s, char *uxf_path, size_t capacity) |
int | xcm_addr_make_utls (const struct xcm_addr_host *host, unsigned short port, char *utls_addr_s, size_t capacity) |
int | xcm_addr_make_tls (const struct xcm_addr_host *host, unsigned short port, char *tls_addr_s, size_t capacity) |
int | xcm_addr_make_tcp (const struct xcm_addr_host *host, unsigned short port, char *tcp_addr_s, size_t capacity) |
int | xcm_addr_make_sctp (const struct xcm_addr_host *host, unsigned short port, char *sctp_addr_s, size_t capacity) |
int | xcm_addr_make_ux (const char *ux_name, char *ux_addr_s, size_t capacity) |
int | xcm_addr_make_uxf (const char *uxf_name, char *uxf_addr_s, size_t capacity) |
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses.
+#define XCM_UTLS_PROTO "utls" | +
Protocol string for the combined TLS+UX transport.
+ +#define XCM_TLS_PROTO "tls" | +
Protocol string for the Transport Layer Security (TLS) transport.
+ +#define XCM_TCP_PROTO "tcp" | +
Protocol string for the TCP transport.
+ +#define XCM_SCTP_PROTO "sctp" | +
Protocol string for the SCTP transport.
+ +#define XCM_UX_PROTO "ux" | +
Protocol string for the UNIX Domain socket (AF_UNIX SEQPACKET) transport (using the abstract namespace).
+ +#define XCM_UXF_PROTO "uxf" | +
Protocol string for the UNIX Domain socket (AF_UNIX SEQPACKET) transport (using file system-based naming).
+ +int xcm_addr_parse_proto | +( | +const char * | +addr_s, | +
+ | + | char * | +proto, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses the protocol part of a XCM address.
+[in] | addr_s | The XCM address string. |
[out] | proto | The buffer where to store the protocol part of the address. |
[in] | capacity | The buffer length in bytes. |
errno | Description |
---|---|
EINVAL | Malformed address. |
ENAMETOOLONG | The user-supplied buffer is too small to fit the protocol. |
int xcm_addr_parse_utls | +( | +const char * | +utls_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a UTLS XCM address.
+[in] | utls_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TLS port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_tls | +( | +const char * | +tls_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a TLS XCM address.
+[in] | tls_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TLS port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_tcp | +( | +const char * | +tcp_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a TCP XCM address.
+[in] | tcp_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TCP port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_sctp | +( | +const char * | +sctp_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parse a SCTP XCM address.
+[in] | sctp_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The SCTP port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_ux | +( | +const char * | +ux_addr_s, | +
+ | + | char * | +ux_path, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses an UX (UNIX Domain Socket) XCM address.
+[in] | ux_addr_s | The string to sparse. |
[out] | ux_path | The UNIX (NUL-terminated) abstract name portion of the UX address. |
[in] | capacity | The length of the user-supplied path buffer. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_uxf | +( | +const char * | +uxf_addr_s, | +
+ | + | char * | +uxf_path, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses an UXF (UNIX Domain Socket) XCM address.
+[in] | uxf_addr_s | The string to sparse. |
[out] | uxf_path | The UNIX (NUL-terminated) path name portion of the UXF address. |
[in] | capacity | The length of the user-supplied path buffer. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_make_utls | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +utls_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a UTLS XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | utls_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_tls | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +tls_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a TLS XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | tls_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_tcp | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +tcp_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a TCP XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | tcp_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_sctp | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +sctp_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a SCTP XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | sctp_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_ux | +( | +const char * | +ux_name, | +
+ | + | char * | +ux_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds an UX XCM address string from the supplied UNIX Domain Socket name.
+[in] | ux_name | The UNIX Domain Socket name. |
[out] | ux_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid format of or too long UNIX Domain Socket address. |
int xcm_addr_make_uxf | +( | +const char * | +uxf_name, | +
+ | + | char * | +uxf_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds an UXF XCM address string from the supplied file system path.
+[in] | uxf_name | The UNIX Domain path. |
[out] | uxf_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid format of or too long UNIX Domain Socket address. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the XCM attribute access API. See Socket Attributes for an overview. +More...
+ +Go to the source code of this file.
++Typedefs | |
typedef void(* | xcm_attr_cb) (const char *attr_name, enum xcm_attr_type type, void *value, size_t value_len, void *cb_data) |
+Functions | |
int | xcm_attr_set (struct xcm_socket *socket, const char *name, enum xcm_attr_type type, const void *value, size_t len) |
int | xcm_attr_set_bool (struct xcm_socket *socket, const char *name, bool value) |
int | xcm_attr_set_int64 (struct xcm_socket *socket, const char *name, int64_t value) |
int | xcm_attr_set_str (struct xcm_socket *socket, const char *name, const char *value) |
int | xcm_attr_get (struct xcm_socket *socket, const char *name, enum xcm_attr_type *type, void *value, size_t capacity) |
int | xcm_attr_get_bool (struct xcm_socket *socket, const char *name, bool *value) |
int | xcm_attr_get_int64 (struct xcm_socket *socket, const char *name, int64_t *value) |
int | xcm_attr_get_str (struct xcm_socket *socket, const char *name, char *value, size_t capacity) |
void | xcm_attr_get_all (struct xcm_socket *socket, xcm_attr_cb cb, void *cb_data) |
This file contains the XCM attribute access API. See Socket Attributes for an overview.
+typedef void(* xcm_attr_cb) (const char *attr_name, enum xcm_attr_type type, void *value, size_t value_len, void *cb_data) | +
The signature of the user-supplied callback used in xcm_attr_get_all().
+ +int xcm_attr_set | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | enum xcm_attr_type | +type, | +
+ | + | const void * | +value, | +
+ | + | size_t | +len | +
+ | ) | ++ |
Sets the value of a socket attribute.
+Only attributes marked as writable may be set. For a list of available attributes for different socket and transport types, see Generic Attributes, TCP Socket Attributes and TLS Socket Attributes.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[in] | type | The value type of the new value. |
[in] | value | The new value. |
[in] | len | The length of the value. |
errno | Description |
---|---|
ENOENT | The attribute does not exist. |
EACCES | The attribute exists, but is read-only. |
EINVAL | The attribute name is too long, the attribute value type, value or value length is not valid for the specified attribute. |
int xcm_attr_set_bool | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | bool | +value | +
+ | ) | ++ |
Sets the value of a boolean socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[in] | value | The new boolean value. |
See xcm_attr_set() for possible errno values.
+ +int xcm_attr_set_int64 | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | int64_t | +value | +
+ | ) | ++ |
Sets the value of an integer socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[in] | value | The new integer value. |
See xcm_attr_set() for possible errno values.
+ +int xcm_attr_set_str | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | const char * | +value | +
+ | ) | ++ |
Sets the value of a string socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[in] | value | The new string value. |
See xcm_attr_set() for possible errno values.
+ +int xcm_attr_get | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | enum xcm_attr_type * | +type, | +
+ | + | void * | +value, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Retrieves the value of a socket attribute.
+For a list of available attributes for different socket and transport types, see Generic Attributes, TCP Socket Attributes and TLS Socket Attributes.
+For a description of the C types and buffer capacity requirements of the attribute types, see xcm_attr_types.h.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[out] | type | A pointer to a location where the type of the attribute will be stored. May be left to NULL, in case the type is known a priori. |
[out] | value | A user-supplied buffer where the value of the attribute will be stored. |
[in] | capacity | The length of the buffer (in bytes). |
errno | Description |
---|---|
ENOENT | The attribute does not exist. |
EACCES | The attribute exists, but is write-only. |
EOVERFLOW | The user-supplied buffer was too small to fit the value. |
int xcm_attr_get_bool | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | bool * | +value | +
+ | ) | ++ |
Retrieves the value of a boolean socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[out] | value | A user-supplied buffer where the value of the attribute will be stored. |
errno | Description |
---|---|
ENOENT | The attribute does not exist, or is not boolean. |
See xcm_attr_get() for other possible errno values.
+ +int xcm_attr_get_int64 | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | int64_t * | +value | +
+ | ) | ++ |
Retrieves the value of an integer socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[out] | value | A user-supplied buffer where the value of the attribute will be stored. |
errno | Description |
---|---|
ENOENT | The attribute does not exist, or is not an integer. |
See xcm_attr_get() for other possible errno values.
+ +int xcm_attr_get_str | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | char * | +value, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Retrieves the value of a string socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[out] | value | A user-supplied buffer where the string value of the attribute will be stored. |
[in] | capacity | The length of the buffer (in bytes). |
errno | Description |
---|---|
ENOENT | The attribute does not exist, or is not a string. |
See xcm_attr_get() for other possible errno values.
+ +void xcm_attr_get_all | +( | +struct xcm_socket * | +socket, | +
+ | + | xcm_attr_cb | +cb, | +
+ | + | void * | +cb_data | +
+ | ) | ++ |
Retrieves all XCM socket attributes.
+This function retrieves all available attribute names, types and their current values on a particular connection or server socket.
+The memory locations refered to by the attr_name and attr_value pointers is only guaranteed to be valid for the execution of the callback. If needed later, they need to be copied.
+[in] | socket | The connection or server socket. |
[in] | cb | The function to be called for every attribute on the socket. |
[in] | cb_data | An opaque (for XCM) pointer returned back to the application in the callback. cb_data may be NULL. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the XCM attribute map API. +More...
+ +Go to the source code of this file.
++Typedefs | |
typedef void(* | xcm_attr_map_foreach_cb) (const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len, void *user) |
+Functions | |
struct xcm_attr_map * | xcm_attr_map_create (void) |
struct xcm_attr_map * | xcm_attr_map_clone (const struct xcm_attr_map *original) |
void | xcm_attr_map_add (struct xcm_attr_map *attr_map, const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len) |
void | xcm_attr_map_add_bool (struct xcm_attr_map *attr_map, const char *attr_name, bool attr_value) |
void | xcm_attr_map_add_int64 (struct xcm_attr_map *attr_map, const char *attr_name, int64_t attr_value) |
void | xcm_attr_map_add_str (struct xcm_attr_map *attr_map, const char *attr_name, const char *attr_value) |
const void * | xcm_attr_map_get (const struct xcm_attr_map *attr_map, const char *attr_name, enum xcm_attr_type *attr_type, size_t *attr_value_len) |
const bool * | xcm_attr_map_get_bool (const struct xcm_attr_map *attr_map, const char *attr_name) |
const int64_t * | xcm_attr_map_get_int64 (const struct xcm_attr_map *attr_map, const char *attr_name) |
const char * | xcm_attr_map_get_str (const struct xcm_attr_map *attr_map, const char *attr_name) |
bool | xcm_attr_map_exists (const struct xcm_attr_map *attr_map, const char *attr_name) |
void | xcm_attr_map_del (struct xcm_attr_map *attr_map, const char *attr_name) |
size_t | xcm_attr_map_size (const struct xcm_attr_map *attr_map) |
void | xcm_attr_map_foreach (const struct xcm_attr_map *attr_map, xcm_attr_map_foreach_cb cb, void *user) |
bool | xcm_attr_map_equal (const struct xcm_attr_map *attr_map_a, const struct xcm_attr_map *attr_map_b) |
void | xcm_attr_map_destroy (struct xcm_attr_map *attr_map) |
This file contains the XCM attribute map API.
+A XCM attribute map is a set of key-value pairs. The key is an attribute name in the form of a string. One key maps to at most one value. The attribute value is either a boolean, a signed 64-bit integer, a string, or a variable-length binary object.
+typedef void(* xcm_attr_map_foreach_cb) (const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len, void *user) | +
Callback function prototype used for iteration.
+ +struct xcm_attr_map * xcm_attr_map_create | +( | +void | +) | ++ |
Create an attribute map instance.
+struct xcm_attr_map * xcm_attr_map_clone | +( | +const struct xcm_attr_map * | +original | ) | ++ |
Create a copy of an attribute map instance.
+[in] | original | The original attribute map instance, to be copied. |
void xcm_attr_map_add | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | enum xcm_attr_type | +attr_type, | +
+ | + | const void * | +attr_value, | +
+ | + | size_t | +attr_value_len | +
+ | ) | ++ |
Associate a key with a value.
+This function associates the attribute key attr_name
to the attribute value attr_value
in the attribute map attr_map
. If the key attr_name
already exists, its value is replaced.
Both the key and the value will be copied, and thus attr_name
and attr_value
will still be owned by the caller at call completion.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_type | The type of the value to be added. |
[in] | attr_value | The value of the attribute to be added. |
[in] | attr_value_len | The length (in bytes) of the value. |
void xcm_attr_map_add_bool | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | bool | +attr_value | +
+ | ) | ++ |
Associate a key with a boolean value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The boolean value of the attribute to be added. |
void xcm_attr_map_add_int64 | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | int64_t | +attr_value | +
+ | ) | ++ |
Associate a key with a 64-bit signed integer value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The integer value of the attribute to be added. |
void xcm_attr_map_add_str | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | const char * | +attr_value | +
+ | ) | ++ |
Associate a key with a string value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The string value of the attribute to be added. |
const void * xcm_attr_map_get | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | enum xcm_attr_type * | +attr_type, | +
+ | + | size_t * | +attr_value_len | +
+ | ) | ++ |
Retrieve the value associated with a particular key.
+This function retrieves the attribute value, value type and value length of the attribute attr_name
, in case it exists.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
[out] | attr_type | A pointer to a buffer where the value type will be stored, or NULL. |
[out] | attr_value_len | A pointer to a buffer where the length (in bytes) of the value will be stored, or NULL. |
const bool * xcm_attr_map_get_bool | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the boolean value associated with a particular key.
+This function retrieves the boolean attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_bool.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
const int64_t * xcm_attr_map_get_int64 | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the integer value associated with a particular key.
+This function retrieves the 64-bit signed integer attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_int64.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
const char * xcm_attr_map_get_str | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the string value associated with a particular key.
+This function retrieves the NUL-terminated string attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_str.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
bool xcm_attr_map_exists | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Check if an attribute named attr_name
exists in the attribute map.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute. |
void xcm_attr_map_del | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Removes an attribute from the attribute map.
+This function deletes the attribute attr_name
, in case it exists.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be deleted. |
size_t xcm_attr_map_size | +( | +const struct xcm_attr_map * | +attr_map | ) | ++ |
Returns the number of attributes in the attribute map.
+[in] | attr_map | The attribute map instance. |
attr_map
. void xcm_attr_map_foreach | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | xcm_attr_map_foreach_cb | +cb, | +
+ | + | void * | +user | +
+ | ) | ++ |
Iterates over all attributes in a map.
+This function calls the supplied callback function cb
for each attribute in attr_map
.
The map may not be modified during iteration.
+[in] | attr_map | The attribute map instance. |
[in] | cb | The callback function. |
[in] | user | An opaque pointer, supplied back to the application in every cb call. |
bool xcm_attr_map_equal | +( | +const struct xcm_attr_map * | +attr_map_a, | +
+ | + | const struct xcm_attr_map * | +attr_map_b | +
+ | ) | ++ |
Compares two attribute maps for equality (by value).
+[in] | attr_map_a | An attribute map instance. |
[in] | attr_map_b | An attribute map instance. |
attr_map_a
and attr_map_a
are equal, false otherwise. void xcm_attr_map_destroy | +( | +struct xcm_attr_map * | +attr_map | ) | ++ |
Destroys an attribute map instance.
+This function destroys the attribute map instance and frees all the resources associated with it.
+[in] | attr_map | The attribute map instance, or NULL. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains type definitions for the XCM attribute access API. +More...
+ +Go to the source code of this file.
++Enumerations | |
enum | xcm_attr_type { xcm_attr_type_bool = 1 +, xcm_attr_type_int64 = 2 +, xcm_attr_type_str = 3 +, xcm_attr_type_bin = 4 + } |
This file contains type definitions for the XCM attribute access API.
+enum xcm_attr_type | +
Enumeration representing the different attribute value types.
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains obsolete parts of the XCM core API. +More...
+ +Go to the source code of this file.
++Macros | |
#define | XCM_FD_READABLE (1<<0) |
#define | XCM_FD_WRITABLE (1<<1) |
#define | XCM_FD_EXCEPTION (1<<2) |
+Functions | |
int | xcm_want (struct xcm_socket *socket, int condition, int *fds, int *events, size_t capacity) |
This file contains obsolete parts of the XCM core API.
+It should not be included directly, but rather only via <xcm.h>.
+#define XCM_FD_READABLE (1<<0) | +
Flag bit denoting a readable fd event in xcm_want().
+ +#define XCM_FD_WRITABLE (1<<1) | +
Flag bit denoting a writable fd event.
+ +#define XCM_FD_EXCEPTION (1<<2) | +
Flag bit denoting a exception fd event.
+ +int xcm_want | +( | +struct xcm_socket * | +socket, | +
+ | + | int | +condition, | +
+ | + | int * | +fds, | +
+ | + | int * | +events, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Query the socket what events on which file descriptors it's waiting for.
+Please note: this function is obsolete, replaced by xcm_fd() and xcm_await().
+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.
+With xcm_want(), the application will inform the XCM socket what condition it's waiting for (i.e. what XCM operation it wants to perform), and in return the XCM socket will provide a set of file descriptors and, for each fd, information on what type of event on that fd it require to make progress. Progress can mean both progress toward the goal of reaching the application's desired socket condition, or finishing any outstanding task the XCM socket has.
+In case any of the conditions the application is asking for are believed to be already met, the xcm_want() call will return 0.
+In case the XCM socket has no outstanding tasks, and the application is not asking for any operation that the XCM socket believes it can't immediate fulfill, the call will return 0.
+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.
+Note that XCM may ask the application to wait for the connection's fd or fds to become writable, even if the application is waiting to receive a message. It may also ask the application to wait for the connection's fd to become readable, even if the application is attemting to send a messaging.
+Even though the conditions for a particular connection socket are met (fd is becoming writable, for example), there's no guarantee that the xcm_send() or xcm_receive() won't block (or in case of non-blocking mode, won't fail and set EAGAIN).
+The XCM socket fds may only be used with select(). Supplying this fd to any other OS calls (such as setsockopt(2), read(2) etc) is prohibited.
+The information received on which fd to use, and what events on that fd are relevant for the connection socket in its current state, are only valid until more xcm_* calls are made on this socket. See Finishing Outstanding Tasks for more information.
+The fd is an positive integer, unique within this process.
+The condition parameter is a bitmask, with the bits being XCM_SO_RECEIVABLE, XCM_SO_SENDABLE, and/or XCM_SO_ACCEPTABLE. If no bits are set, the application is not interested in anything beyond this XCM socket to finish any outstanding task.
+Each element in the events array is an int used as a bitmask. The bitmask at position N in the events array represents the file descriptor events the XCM transport is waiting for, for fd at position N in the fds array. The bits are XCM_FD_READABLE, XCM_FD_WRITABLE and/or XCM_FD_EXCEPTION. At least one bit is always set.
+If a socket is waiting for multiple events (for example, both readable and writable on the same fd, or readable on one fd, and writeable on another), the condition is met whenever any of the events occur (as oppose to all events).
+[in] | socket | The XCM socket. |
[in] | condition | The condition the application is waiting for. |
[out] | fds | An user-supplied array to store the fds. |
[out] | events | An user-supplied array of int to store the bitmask of each of the fds in the fds array. |
[in] | capacity | The length of the fds and events arrays. |
errno | Description |
---|---|
EOVERFLOW | The user-supplied buffer was too small to fit the socket's fds. |
EINVAL | The socket is not in blocking mode, or the condition bits are invalid. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains functions and macros to retrieve XCM version information. The library (i.e., implementation) version uses the semver convention. +More...
+ +Go to the source code of this file.
++Macros | |
#define | XCM_VERSION_MAJOR 1 |
#define | XCM_VERSION_MINOR 5 |
#define | XCM_VERSION_PATCH 0 |
#define | XCM_VERSION "1.5.0" |
#define | XCM_VERSION_API_MAJOR 0 |
#define | XCM_VERSION_API_MINOR 20 |
#define | XCM_VERSION_API "0.20" |
+Functions | |
unsigned int | xcm_version_major (void) |
unsigned int | xcm_version_minor (void) |
unsigned int | xcm_version_patch (void) |
const char * | xcm_version (void) |
unsigned int | xcm_version_api_major (void) |
unsigned int | xcm_version_api_minor (void) |
const char * | xcm_version_api (void) |
This file contains functions and macros to retrieve XCM version information. The library (i.e., implementation) version uses the semver convention.
+#define XCM_VERSION_MAJOR 1 | +
The XCM library major version.
+ +#define XCM_VERSION_MINOR 5 | +
The XCM library minor version.
+ +#define XCM_VERSION_PATCH 0 | +
The XCM library patch version.
+ +#define XCM_VERSION "1.5.0" | +
The complete XCM library version in string format.
+ +#define XCM_VERSION_API_MAJOR 0 | +
The XCM API/ABI major version this library version implements.
+ +#define XCM_VERSION_API_MINOR 20 | +
The XCM API/ABI minor version this library version implements.
+ +#define XCM_VERSION_API "0.20" | +
The complete XCM API version in string format.
+ +unsigned int xcm_version_major | +( | +void | +) | ++ |
Retrieves the library major version.
+This function returns the implementation major version of the library used at run time.
+ +unsigned int xcm_version_minor | +( | +void | +) | ++ |
Retrieves the library minor version.
+This function returns the implementation minor version of the library used at run time.
+ +unsigned int xcm_version_patch | +( | +void | +) | ++ |
Retrieves the library patch version.
+This function returns the implementation patch version of the library used at run time.
+ +const char * xcm_version | +( | +void | +) | ++ |
Retrieves the library version as a string.
+This function returns the version of the library used at run time, in string format.
+The string returned is statically allocated, and thus must not be free'd by the caller.
+ +unsigned int xcm_version_api_major | +( | +void | +) | ++ |
Retrieves the XCM API major version.
+This function returns the API major version of the library used at run time adheres to.
+ +unsigned int xcm_version_api_minor | +( | +void | +) | ++ |
Retrieves the XCM API minor version.
+This function returns the API minor version of the library used at run time adheres to.
+ +const char * xcm_version_api | +( | +void | +) | ++ |
Retrieves the library API version as a string.
+This function returns the API version of the library used at run time adheres to.
+The string returned is statically allocated, and thus must not be free'd by the caller.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
Cxcm_addr_host | |
Cxcm_addr_ip |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Files | |
xcm.h | |
This file contains the core Extensible Connection-oriented Messaging (XCM) API. | |
xcm_addr.h | |
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses. | |
xcm_attr.h | |
This file contains the XCM attribute access API. See Socket Attributes for an overview. | |
xcm_attr_map.h | |
This file contains the XCM attribute map API. | |
xcm_attr_types.h | |
This file contains type definitions for the XCM attribute access API. | |
xcm_compat.h | |
This file contains obsolete parts of the XCM core API. | |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
▼ include | |
xcm.h | This file contains the core Extensible Connection-oriented Messaging (XCM) API |
xcm_addr.h | This is an API for building and parsing Connection-oriented Messaging (XCM) addresses |
xcm_attr.h | This file contains the XCM attribute access API. See Socket Attributes for an overview |
xcm_attr_map.h | This file contains the XCM attribute map API |
xcm_attr_types.h | This file contains type definitions for the XCM attribute access API |
xcm_compat.h | This file contains obsolete parts of the XCM core API |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Macros | |
#define | XCM_VERSION_API_MAJOR 0 |
#define | XCM_VERSION_API_MINOR 22 |
#define | XCM_VERSION_API "0.22" |
#define XCM_VERSION_API_MAJOR 0 | +
The XCM API/ABI major version this library version implements.
+ +#define XCM_VERSION_API_MINOR 22 | +
The XCM API/ABI minor version this library version implements.
+ +#define XCM_VERSION_API "0.22" | +
The complete XCM API version in string format.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Macros | |
#define | XCM_VERSION_MAJOR 1 |
#define | XCM_VERSION_MINOR 7 |
#define | XCM_VERSION_PATCH 0 |
#define | XCM_VERSION "1.7.0" |
#define XCM_VERSION_MAJOR 1 | +
The XCM library major version.
+ +#define XCM_VERSION_MINOR 7 | +
The XCM library minor version.
+ +#define XCM_VERSION_PATCH 0 | +
The XCM library patch version.
+ +#define XCM_VERSION "1.7.0" | +
The complete XCM library version in string format.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This is the documentation for the Extensible Connection-oriented Messaging (XCM) programming APIs.
+XCM consists the core API in xcm.h, an address helper library API in xcm_addr.h, and the attribute APIs in xcm_attr.h and xcm_attr_map.h. Obsolete, but still present, functions are available in xcm_compat.h
+The low API/ABI version number is purely a result of all XCM releases being backward compatible, and thus left the major version at 0. It's not to be taken as a sign of immaturity. The API and its implementation have been stable for years.
+XCM provides a connection-oriented, reliable messaging service with in-order delivery. The design goal is to allow for a straight forward mapping to TCP and TLS, but also supporting efficient inter-process commmunication (IPC) mechanisms for local communication.
+XCM reuses much of the terminology of the BSD Sockets API. Unlike the BSD Socket API, XCM has uniform semantics across all underlying transports.
+XCM has a client-server model. A server creates a server socket (with xcm_server()) bound to a specific address (in case of TCP or TLS, a TCP port on a particular IP interface), after which clients may initiate connections to the server. On a successful attempt, two connection sockets will be created; one on the server side (returned from xcm_accept()), and one of the client side (returned from xcm_connect()). Thus, a server serving multiple clients will have multiple sockets; one server socket and N connection sockets, one each for every client. A client will typically have one connection socket for each server it is connected to.
+Messages are always sent and received on a particular connection socket (and never on a server socket).
+In-order delivery - that messages arrive at the recipient in the same order they were sent by the sender side - is guaranteed, but only for messages sent on the same connection.
+XCM transports support flow control. Thus, if the sender message rate or bandwidth is higher than the network or the receiver can handle on a particular connection, xcm_send() in the sender process will eventually block (or return an error EAGAIN, if in non-blocking mode). Unless XCM is used for bulk data transfer (as oppose to signaling traffic), xcm_send() blocking because of slow network or a slow receiver should be rare indeed in practice. TCP, TLS, and UNIX domain socket transports all have large enough windows and socket buffers to allow a large amount of outstanding data.
+In XCM, the application is in control of which transport will be used, with the address supplied to xcm_connect() and xcm_server() including both the transport name and the transport address.
+However, there is nothing preventing a XCM transport to use a more an abstract addressing format, and internally include multiple "physical" IPC transport options. This model is used by the UTLS Transport.
+Addresses are represented as strings with the following general syntax: <transport-name>:<transport-address>
For the UX UNIX Domain Socket transport, the addresses has this more specific form:
+
The addresses of the UXF UNIX Domain Socket transport variant have the following format:
+
For the TCP, TLS, UTLS and SCTP transports the syntax is:
+
'*' is a shorthand for '0.0.0.0' (i.e. bind to all IPv4 interfaces). '[*]' is the IPv6 equivalent, creating a server socket accepting connections on all IPv4 and IPv6 addresses.
+Some examples addresses:
For TCP, TLS, UTLS and SCTP server socket addresses, the port can be set to 0, in which case XCM (or rather, the Linux kernel) will allocate a free TCP port from the local port range.
+For transports allowing a DNS domain name as a part of the address, the transport will attempt resoĺv the name to an IP address. A DNS domain name may resolv to zero or more IPv4 addresses and/or zero or more IPv6 addresses. XCM relies on the operating system to prioritize between IPv4 and IPv6.
+XCM accepts IPv4 addresses in the dotted-decimal format
XCM allows only complete addresses with three '.', and not the archaic, classful, forms, where some bytes where left out, and thus the address contained fewer separators.
+XCM transports attempt to detect a number of conditions which can lead to lost connectivity, and does so even on idle connections.
+If the remote end closes the connection, the local xcm_receive() will return 0. If the process on the remote end crashed, xcm_receive() will return -1 and set errno ECONNRESET. If network connectivity to the remote end is lost, xcm_receive() will return -1 and errno will be set to ETIMEDOUT.
+In general, XCM follow the UNIX system API tradition when it comes to error handling. Where possible, errors are signaled to the application by using unused parts of the value range of the function return type. For functions returning signed integer types, this means the value of -1 (in case -1 is not a valid return value). For functions returning pointers, NULL is used to signal that an error has occurred. For functions where neither -1 or NULL can be used, or where the function does not return anything (side-effect only functions), an 'int' is used as the return type, and is used purely for the purpose to signal success (value 0), or an error (-1) to the application.
+The actual error code is stored in the thread-local errno variable. The error codes are those from the fixed set of errno values defined by POSIX, found in errno.h. Standard functions such as perror() and strerror() may be used to turn the code into a human-readable string.
+In non-blocking operation, given the fact the actual transmission might be defered (and the message buffered in the XCM layer), and that message receive processing might happen before the application has called receive, the error being signaled at the point of a certain XCM call might not be a direct result of the requested operation, but rather an error discovered previously.
+The documentation for xcm_finish() includes a list of generic error codes, applicable xcm_connect(), xcm_accept(), xcm_send() and xcm_receive().
+Also, for errors resulting in an unusable connection, repeated calls will produce the same errno.
+In UNIX-style event-driven programming, a single application thread handles multiple clients (and thus multiple XCM connection sockets) and the task of accepting new clients on the XCM server socket concurrently (although not in parallel). To wait for events from multiple sources, an I/O multiplexing facility such as select(2), poll(2) or epoll(2) is used.
+Each XCM socket is represented by a single fd, retrieved with xcm_fd(). The fd number and underlying file object is stable across the life-time of the socket.
+On BSD Sockets, the socket fd being readable means it's likely that the application can successfully read data from the socket. Similarily, a fd marked writable by, for example, poll() means that the application is likely to be able to write data to the BSD Sockets fd. For an application using XCM going into select(), it must always wait for all the fds its XCM sockets to become readable (e.g. being in the readfds
in the select() call), regardless what are their target conditions. Thus, even if the application is waiting for an opportunity to try to send a message on a XCM socket, or it doesn't want to do anything with the socket, it must wait for the socket fd to become readable. Not wanting to do nothing here means that the application has the xcm_await() condition set to 0, and is neither interested in waiting to call xcm_send(), xcm_receive(), nor xcm_accept() on the socket. An application may never leave a XCM socket unattended in the sense its fd is not in the set of fds passed to select() and/or xcm_send(), xcm_receive(), xcm_accept() or xcm_finish() are not called.
XCM is oblivious to what I/O multiplexing mechanism employed by the application. It may call select(), poll() or epoll_wait() directly, or make use of any of the many available event loop libraries (such as libevent). For simplicity, select() is used in this documentation to denote the whole family of Linux I/O multiplexing facilities.
+An event-driven application needs to set the XCM sockets it handles into non-blocking mode, by calling xcm_set_blocking(), setting the "xcm.blocking" socket attribute, or using the XCM_NONBLOCK flag in xcm_connect().
+For XCM sockets in non-blocking mode, all potentially blocking API calls related to XCM connections - xcm_connect(), xcm_accept(), xcm_send(), and xcm_receive() - finish immediately.
+For xcm_send(), xcm_connect() and xcm_accept(), XCM signaling success means that the XCM layer has accepted the request. It may or may not have completed the operation.
+In case the XCM_NONBLOCK flag is set in the xcm_connect() call, or in case the a XCM server socket is in non-blocking mode at the time of a xcm_accept() call, the newly created XCM connection returned to the application may be in a semi-operational state, with some internal processing and/or signaling with the remote peer still required before actual message transmission and reception may occur.
+The application may attempt to send or receive messages on such semi-operational connections.
+There are ways for an application to determine when connection establishment or the task of accepting a new client have completed. See Finishing Outstanding Tasks for more information.
+To receive a message on a XCM connection socket in non-blocking mode, the application may need to wait for the right conditions to arise (i.e. a message being available). The application needs to inform the socket that it wants to receive by calling xcm_await() with the XCM_SO_RECEIVABLE
bit in the condition
bit mask set. It will pass the fd it received from xcm_fd() into select(), asking to get notified when the fd becomes readable. When select() marks the socket fd as readable, the application should issue xcm_receive() to attempt to retrieve a message.
xcm_receive() may also called on speculation, prior to any select() call, to poll the socket for incoming messages.
+A XCM connection socket may have a number of messages buffered, and applications should generally, for optimal performance, repeat xcm_receive() until it returns an error, and errno is set to EAGAIN.
+Similarly to receiving a message, an application may set the XCM_SO_SENDABLE
bit in the condition
bit mask, if it wants to wait for a socket state where it's likely it can successfully send a message. When select() marks the socket fd as readable, the application should attempt to send a message.
Just like with xcm_receive(), it may also choose to issue a xcm_send() call on speculation (i.e. without going into select()), which is often a good idea for performance reasons.
+For send operations on non-blocking connection sockets, XCM may buffer whole or part of the message before transmission to the lower layer. This may be due to socket output buffer underrun, or the need for some in-band signaling, like cryptographic key exchange, to happen before the transmission of the complete message may finish. The XCM layer will (re-)attempt to hand the message over to the lower layer at a future call to xcm_finish(), xcm_send(), or xcm_receive().
+For applications wishing to determine when all buffered messages have successfully be deliver to the lower layer, they may use xcm_finish() to do so. Normally, applications aren't expected to require this kind of control. Please also note that the fact a message has left the XCM layer doesn't necessarily mean it has successfully been delivered to the recipient.
+xcm_connect(), xcm_accept(), xcm_send() may all leave the socket in a state where work is initiated, but not completed. In addition, the socket may have pending internal tasks, such flushing the output buffer into the TCP/IP stack, processing XCM control interface messages, or finishing the TLS hand shake procedure.
+After waking up from a select() call, where a particular XCM non-blocking socket's fd is marked readable, the application must, if no xcm_send(), xcm_receive() or xcm_accept() calls are to be made, call xcm_finish(). This is to allow the socket to finish any outstanding tasks, even in the case the application has no immediate plans for the socket.
+Prior to changing a socket from non-blocking to blocking mode, any outstanding tasks should be finished, or otherwise the switch might cause xcm_set_blocking() to return -1 and set errno to EAGAIN.
+For example, if a server socket's desired condition has been set (with xcm_await()) to XCM_SO_ACCEPTABLE
, and the application wakes up from select() with the socket's fd marked readable, a call to xcm_accept() may still not produce a new connection socket.
The same holds true when reaching XCM_SO_RECEIVABLE
and a xcm_receive() call is made, and XCM_SO_SENDABLE
and calls to xcm_send().
In this example, the application connects and tries to send a message, before knowing if the connection is actually established. This may fail (for example, in case TCP and/or TLS-level connection establishment has not yet been completed), in which case the application will fall back and wait with the use of xcm_await(), xcm_fd() and select().
+In case the application wants to know when the connection establishment has finished, it may use xcm_finish() to do so, like in the below example sequence.
+While connecting to a server socket, the client's connection attempt may be refused immediately.
+In many cases, the application is handed a connection socket before the connection establishment is completed. Any errors occuring during this process is handed over to the application at a future call to xcm_finish(), xcm_send() or xcm_receive().
+In this example the application flushes any internal XCM buffers before shutting down the connection, to ensure that any buffered messages are delivered to the lower layer.
+In this sequence, a server accepts a new connection, and continues to attempt to receive a message on this connection, while still, concurrently, is ready to accept more clients on the server socket.
+Tied to an XCM server or connection socket is a set of key-value pairs known as attributes. Which attributes are available varies across different transports, and different socket types.
+An attribute's name is a string, and follows a hierarchical naming schema. For example, all generic XCM attributes, available in all transports, have the prefix "xcm.". Transport-specific attributes are prefixed with the transport or protocol name (e.g. "tcp." for TCP-specific attributes applicable to the TLS and TCP transports).
+An attribute may be read-only, write-only or available both for reading and writing. This is referred to as the attribute's mode. The mode may vary across the lifetime of the socket. For example, an attribute may be writable at the time of the xcm_connect() call, and read-only thereafter.
+The attribute value is coded in the native C data type and byte order. Strings are NUL-terminated, and the NUL character is included in the length of the attribute. There are four value types; a boolean type, a 64-bit signed integer type, a string type and a type for arbitrary binary data. See xcm_attr_types.h for details.
+The attribute access API is in xcm_attr.h.
+Retrieving an integer attribute's value may look like this:
Changing an integer attribyte value may be done in the following manner:
Both of these examples are missing error handling.
+XCM allows supplying a set of writable attributes at the time of socket creation, by using the xcm_connect_a(), xcm_server_a(), or xcm_accept_a() functions.
+The attribute sets are represented by the xcm_attr_map
type in xcm_attr_map.h.
An example:
These attributes are expected to be found on XCM sockets regardless of transport type.
+For TCP transport-specific attributes, see TCP Socket Attributes, and for TLS, see TLS Socket Attributes.
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
xcm.type | All | String | R | The socket type: "server" or "connection". |
xcm.transport | All | String | R | The transport type. |
xcm.local_addr | All | String | RW | The local address of a socket. Writable only if supplied to xcm_connect_a(). |
xcm.blocking | All | Boolean | RW | See xcm_set_blocking() and xcm_is_blocking(). |
xcm.remote_addr | Connection | String | R | See xcm_remote_addr(). |
xcm.max_msg_size | Connection | Integer | R | The maximum size of any message transported by this connection. |
XCM has a set of generic message counters, which keeps track of the number of messages crossing a certain boundary for a particular connection, and a sum of their size.
+Some of the message and byte counter attributes use the concept of a "lower layer". What this means depends on the transport. For the UX And TCP transports, it is the Linux kernel. For example, for TCP, if the xcm.to_lower_msgs is incremented, it means that XCM has successfully sent the complete message to the kernel's networking stack for further processing. It does not means it has reached the receiving process. It may have, but it also may be sitting on the local or remote socket buffer, on a NIC queue, or be in-transmit in the network. For TLS, the lower layer is OpenSSL.
+All the "xcm.*_bytes" counters count the length of the XCM message payload (as in the length field in xcm_send()), and thus does not include any underlying headers.
+The message counters only count messages succesfully sent and/or received.
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
xcm.from_app_msgs | Connection | Integer | R | Messages sent from the application and accepted into XCM. |
xcm.from_app_bytes | Connection | Integer | R | The sum of the size of all messages counted by xcm.from_app_msgs. |
xcm.to_app_msgs | Connection | Integer | R | Messages delivered from XCM to the application. |
xcm.to_app_bytes | Connection | Integer | R | The sum of the size of all messages counter by xcm.to_app_msgs. |
xcm.from_lower_msgs | Connection | Integer | R | Messages received by XCM from the lower layer. |
xcm.from_lower_bytes | Connection | Integer | R | The sum of the size of all messages counted by xcm.from_lower_msgs. |
xcm.to_lower_msgs | Connection | Integer | R | Messages successfully sent by XCM into the lower layer. |
xcm.to_lower_bytes | Connection | Integer | R | The sum of the size of all messages counted by xcm.to_lower_msgs. |
XCM includes a control interface, which allows iteration over the OS instance's XCM server and connection sockets (for processes with the appropriate permissions), and access to their attributes (see Socket Attributes).
+The control interface is optional by means of build-time configuration.
+For each XCM server or connection socket, there is a corresponding UNIX domain socket which is used for control signaling (i.e. state retrieval).
+By default, the control interface's UNIX domain sockets are stored in the /run/xcm/ctl
directory.
This directory needs to be created prior to running any XCM applications (for the control interface to worker properly) and should be writable for all XCM users.
+A particular process using XCM may be configured to use a non-default directory for storing the UNIX domain sockets used for the control interface by means of setting the XCM_CTL
variable. Please note that using this setting will cause the XCM connections to be not visible globally on the OS instance (unless all other XCM-using processes also are using this non-default directory).
Generally, since the application is left unaware (from an API perspective) of the existence of the control interface, errors are not reported up to the application. They are however logged.
+Application threads owning XCM sockets, but which are busy with non-XCM processing for a long duration of time, or otherwise are leaving their XCM sockets unattended to (in violation of XCM API contract), will not respond on the control interface's UNIX domain sockets (corresponding to their XCM sockets). Only the presence of these sockets may be detected, but their state cannot be retrieved.
+Internally, the XCM implementation has control interface client library, but this library's API is not public at this point.
+XCM includes a command-line program xcmctl
which uses the Control API to iterate of the system's current XCM sockets, and allow access (primarily for debugging purposes) to the sockets' attributes.
Unlike BSD sockets, a XCM socket may not be shared among different threads without synchronization external to XCM. With proper external serialization, a socket may be shared by different threads in the same process, although it might provide difficult in practice since a thread in a blocking XCM function will continue to hold the lock, and thus preventing other threads from accessing the socket at all.
+For non-blocking sockets, threads sharing a socket need to agree on what is the appropriate socket condition
to wait for. When this condition is met, all threads are woken up, returning from select().
It is safe to "give away" a XCM socket from one thread to another, provided the appropriate memory fences are used.
+These limitations (compared to BSD Sockets) are in place to allow socket state outside the kernel (which is required for TCP framing and TLS).
+Sharing a XCM socket between threads in different processes is not possible.
+After a fork() call, either of the two process (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 not call any other XCM API call than xcm_cleanup(), which frees local memory tied to this socket in the non-owner's process address space, without impacting the connection state in the owner process.
+The core XCM API functions are oblivious to the transports used. However, the support for building, and parsing addresses are available only for a set of pre-defined set of transports. There is nothing preventing xcm_addr.h from being extended, and also nothing prevents an alternative XCM implementation to include more transports without extending the address helper API.
+The UX transport uses UNIX Domain (AF_UNIX, also known as AF_LOCAL) Sockets.
+UX sockets may only be used with the same OS instance (or, more specifically, between processes in the same Linux kernel network namespace).
+UNIX Domain Sockets comes in a number of flavors, and XCM uses the SOCK_SEQPACKET variety. SOCK_SEQPACKET sockets are connection-oriented, preserves message boundaries and delivers messages in the same order they were sent; perfectly matching XCM semantics and provides for an near-trivial mapping.
+UX is the most efficient of the XCM transports.
+The standard UNIX Domain Sockets as defined by POSIX uses the file system as its namespace, with the sockets also being files. However, for simplicity and to avoid situations where stale socket files (originating from crashed processes) causing problems, the UX transport uses a Linux-specific extension, allowing a private UNIX Domain Socket namespace. This is known as the abstract namespace (see the unix(7) man page for details). With the abstract namespace, server socket address allocation has the same life time as TCP ports (i.e. if the process dies, the address is free'd).
+The UX transport enables the SO_PASSCRED BSD socket option, to give the remote peer a name (which UNIX domain connection socket doesn't have by default). This is for debugging and observability purposes. Without a remote peer name, in server processes with multiple incoming connections to the same server socket, it's difficult to say which of the server-side connection sockets goes to which remote peer. The kernel-generated, unique, name is an integer in the form "%05x" (printf format). Applications using hardcoded UX addresses should avoid such names by, for example, using a prefix.
+The UTLS Transport also indirectly uses the UX namespace, so care should be taken to avoid any clashes between UX and UTLS sockets in the same network namespace.
+The UXF transport is identical to the UX transport, only it uses the standard POSIX naming mechanism. The name of a server socket is a file system path, and the socket is also a file.
+The UXF sockets resides in a file system namespace, as opposed to UX sockets, which live in a network namespace.
+Upon xcm_close(), the socket will be closed and the file removed. If an application crashes or otherwise fails to run xcm_close(), it will leave a file in the file system pointing toward a non-existing socket. This file will prevent the creation another server socket with the same name.
+The TCP transport uses the Transmission Control Protocol (TCP), by means of the BSD Sockets API.
+TCP is a byte-stream service, but the XCM TCP transport adds framing on top of the stream. A single-field 32-bit header containing the message length in network byte order is added to every message.
+TCP uses TCP Keepalive to detect lost network connectivity between the peers.
+The TCP transport supports IPv4 and IPv6.
+Since XCM is designed for signaling traffic, the TCP transport disables the Nagle algorithm of TCP to avoid its excessive latency.
+The read-only TCP attributes are retrieved from the kernel (struct tcp_info in linux/tcp.h).
+The read-write attributes are mapped directly to setsockopt() calls.
+See the tcp(7) manual page for a more detailed description of these attributes. The struct retrieved with TCP_INFO
is the basis for the read-only attributes. The read-write attributes are mapped to TCP_KEEP*
and TCP_USER_TIMEOUT
.
Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
tcp.rtt | Connection | Integer | R | The current TCP round-trip estimate (in us). |
tcp.total_retrans | Connection | Integer | R | The total number of retransmitted TCP segments. |
tcp.segs_in | Connection | Integer | R | The total number of segments received. |
tcp.segs_out | Connection | Integer | R | The total number of segments sent. |
tcp.keepalive | Connection | Boolean | RW | Controls if TCP keepalive is enabled. |
tcp.keepalive_time | Connection | Integer | RW | The time (in s) before the first keepalive probe is sent on an idle connection. |
tcp.keepalive_interval | Connection | Integer | RW | The time (in s) between keepalive probes. |
tcp.keepalive_count | Connection | Integer | RW | The number of keepalive probes sent before the connection is dropped. |
tcp.user_timeout | Connection | Integer | RW | The time (in s) before a connection is dropped due to unacknowledged data. |
tcp.segs_in
and tcp.segs_out
are only present when running XCM on Linux kernel 4.2 or later.The TLS transport uses the Transport Layer Security (TLS) protocol to provide a secure, private, two-way authenticated transport over TCP. A TLS connection is a byte stream, but the XCM TLS transport adds framing in the same manner as does the XCM TCP transport.
+The TLS transport supports IPv4 and IPv6. It disables the Nagle algorithm of TCP.
+The TLS transport reads the leaf certificate and its private key from the file system, as well as a file containing all trusted CA certificates. Default paths are configured at build-time.
+TLS Socket Attributes may be used to override one or more of the default paths, on a per-socket basis. Paths set on server sockets are inherited by its connection sockets, but may in turn be overriden at the time of a xcm_accept_a() call, using the proper attributes.
+The default paths may also be overriden on a per-process basis by means of a UNIX environment variable. The current value of XCM_TLS_CERT
(at the time of xcm_connect() or xcm_accept()) determines the certificate directory used for that connection.
The TLS transport will, at the time of xcm_connect() or xcm_server(), look up the process' current network namespace, unless that file's path was given as a TLS Socket Attributes. If the namespace is given a name per the iproute2 convention, XCM will retrieve this name and use it in the certificate and key lookup.
+In case the certificate, key and trusted CA files are configured using TLS Socket Attributes, no network namespace lookup will be performed.
+In the certificate directory (either the compile-time default, or the directory specified with XCM_TLS_CERT
), the TLS transport expects the files to follow the following naming conventions (where <ns> is the namespace):
The private key is stored in:
The trusted CA certificates are stored in:
For the default namespace (or any other network namespace not named according to iproute2 standards), the certificate need to be stored in a file "cert.pem", the private key in "key.pem" and the trusted CA certificates in "tc.pem".
+In case the certificate, key or trusted CAs files are not in place (for a particular namespace), a xcm_server() call will return an error and set errno to EPROTO. The application may choose to retry at a later time.
+In case a certificate, private key, or trusted CAs file is modified, the new version of the file(s) will be used by new connections. Such a change does not affect already-established connections. The TLS transport works with differences between set of files, and thus the new generation of files need not nesserarily be newer (as in having a more recent file system mtime).
+The certificate, key and trusted CA certificates should be updated in an atomic manner, or XCM may end up using the certificate file from one generation of files and the key file from another, for example.
+One way of achieving an atomic update is to have the three files in a common directory. This certificate directory is then made a symbolic link to the directory where the actual files are located. Upon update, a new directory is created and populated, and the old symbolic link is replace an atomic manner (i.e. with rename(2)).
+By default, on sockets that represent the client side of a XCM TLS connection (e.g., returned from xcm_connect_a()), the XCM TLS transport will act as a TLS client. Similarly, the default behavior for sockets representing the XCM (and TCP) server side of a connection is to act as a TLS server.
+The default may be changed by setting the "tls.client" attribute, so that sockets that are XCM (and TCP) level clients, act as TLS servers, and vice versa. If the value is true, the socket will act as a TLS client, and if false, the socket is a TLS server.
+Connection sockets created by xcm_accept() or xcm_accept_a() inherit the "tls.client" attribute value from their parent server sockets.
+The TLS role must be specified at the time of socket creation, and thus cannot be changed on already-established connections.
+By default, both the client and server side authenticate the other peer, often known as mutual TLS (mTLS).
+TLS remote peer authentication may be disabled by setting the "tls.auth" socket attribute to false.
+Connection sockets created by xcm_accept() or xcm_accept_a() inherit the "tls.auth" attribute value from their parent server sockets.
+The "tls.auth" socket attribute may only be set at the time of socket creation (except for server sockets).
+The TLS transport supports verifying the remote peer's certificate subject name against an application-specified expected name, or a set of names. "Subject name" here is used as per RFC 6125 definition, and is either a Distingushed Name (DN) of the X.509 certificate's subject field, or a DNS type subject alternative name extension. XCM does not make any distinction between the two.
+Subject name verification may be enabled by setting the "tls.verify_peer_name" socket attribute to true. It is disabled by default.
+If enabled, XCM will verify the hostname in the address supplied in the xcm_connect_a() call. In case the attribute "tls.peer_names" is also supplied, it overrides this behavior. The value of this attribute is a ':'-separated set of subject names.
+If there is a non-zero overlap between these two sets, the verification is considered successful. The actual procedure is delegated to OpenSSL. Wildcard matching is disabled (X509_CHECK_FLAG_NO_WILDCARDS
) and the check includes the subject field (X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
).
Subject name verification may be used both by a client (in its xcm_connect_a() call) or by a server (in xcm_server_a() or xcm_accept_a()). "tls.peer_names" must be specified in case "tls.verify_peer_name" is set to true on connection sockets created by accepting a TLS connection from a server socket (since there is no hostname to fall back to).
+Connection sockets created by xcm_accept() or xcm_accept_a() inherit the "tls.verify_name" and "tls.peer_names" attributes from their parent server sockets.
+After a connection is established, the "tls.peer_names" will be updated to reflect the remote peer's actual subject names, as opposed to those which were originally allowed.
+OpenSSL refers to this functionality as hostname validation, and that is also how it's usually used. However, the subject name passed in "tls.peer_names" need not be DNS domain name, but can be any kind of name or identifier. All names must follow DNS domain name syntax rules (including label and total length limitations). Also, while uppercase and lowercase letters are allowed in domain names, no significance is attached to the case.
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
tls.cert_file | All | String | RW | The leaf certificate file. For connection sockets, writable only at socket creation. |
tls.key_file | All | String | RW | The leaf certificate private key file. For connection sockets, writable only at socket creation. |
tls.tc_file | All | String | RW | The trusted CA certificates bundle. For connection sockets, writable only at socket creation. |
tls.client | All | Boolean | RW | Controls whether to act as a TLS-level client or a server. For connection sockets, writable only |
tls.auth | All | Boolean | RW | Controls whether or not to authenticate the remote peer. For connection sockets, writable only at socket creation. |
tls.verify_peer_name | All | Boolean | RW | Controls if subject name verification should be performed. For connection sockets, writable only at socket creation. |
tls.peer_names | All | String | RW | At socket creation, a list of acceptable peer subject names. After connection establishment, a list of actual peer subject names. For connection sockets, writable only at socket creation. |
tls.peer_subject_key_id | Connection | String | R | The X509v3 Subject Key Identifier of the remote peer, or a zero-length string in case the TLS connection is not established. |
In addition to the TLS-specific attributes, a TLS socket also has all the TCP Socket Attributes.
+The UTLS transport provides a hybrid transport, utilizing both the TLS and UX transports internally for actual connection establishment and message delivery.
+On the client side, at the time of xcm_connect(), the UTLS transport determines if the server socket can be reached by using the UX transport (i.e. if the server socket is located on the same OS instance, in the same network namespace). If not, UTLS will attempt to reach the server by means of the TLS transport.
+For a particular UTLS connection, either TLS or UX is used (never both). XCM connections to a particular UTLS server socket may be a mix of the two different types.
+For an UTLS server socket with the address utls:<ip>:<port>
, two underlying addresses will be allocated; tls:<ip>:<port>
and ux:<ip>:<port>
.
In case DNS is used: tls:<hostname>:<port>
and ux:<hostname>:<port>
.
UTLS sockets accept all the TLS Socket Attributes, as well as the Generic Attributes. In case a UTLS connection is being established as a UX connection socket, all TLS attributes are ignored.
+A wildcard should never be used when creating a UTLS server socket.
+If a DNS hostname is used in place of the IP address, both the client and server need employ DNS, and also agree upon which hostname to use (in case there are several pointing at the same IP address).
+Failure to adhere to the above two rules will prevent a client from finding a local server. Such a client will instead establish a TLS connection to the server.
+The SCTP transport uses the Stream Control Transmission Protocol (SCTP). SCTP provides a reliable, message-oriented service. In-order delivery is optional, but to adhere to XCM semantics (and for other reasons) XCM leaves SCTP in-order delivery enabled.
+The SCTP transport utilizes the native Linux kernel's implementation of SCTP, via the BSD Socket API. The operating mode is such that there is a 1:1-mapping between an association and a socket (fd).
+The SCTP transport supports IPv4 and IPv6.
+To minimize latency, the SCTP transport disables the Nagle algorithm.
+Namespaces is a Linux kernel facility concept for creating multiple, independent namespaces for kernel resources of a certain kind.
+Linux Network Namespaces will affect all transports, except the UXF Transport.
+XCM has no explicit namespace support. Rather, the application is expected to use the Linux kernel facilities for this functionality (i.e. switch to the right namespace before xcm_server() och xcm_connect()).
+In case the system follows the iproute2 conventions in regards to network namespace naming, the TLS and UTLS transports support per-network namespace TLS certificates and private keys.
+XCM, in its current form, does not support binding to a local socket before doing connect() - something that is possible with BSD Sockets, but very rarely makes sense.
+XCM also doesn't have a sendmmsg() or recvmmsg() equivalent. Those could easily be added, and would provide some major performance improvements for applications that are sending or receiving multiple messages on the same connection on the same time. *mmsg() equivalents have been left out because there are strong doubts there are such applications.
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
#include <xcm_addr.h>
+Data Fields | ||
enum xcm_addr_type | type | |
union { | ||
+ struct xcm_addr_ip ip | ||
+ char name [254] | ||
}; | ||
Hostname or IPv4/IPv6 address data type.
+enum xcm_addr_type xcm_addr_host::type | +
Type tag
+ +union { ... } xcm_addr_host | +
Union containing the actual hostname, IPv4 or IPv6 address bytes
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
#include <xcm_addr.h>
+Data Fields | ||
sa_family_t | family | |
union { | ||
in_addr_t ip4 | ||
uint8_t ip6 [16] | ||
} | addr | |
IPv4 or IPv6 address data type.
+sa_family_t xcm_addr_ip::family | +
Type tag; AF_INET or AF_INET6
+ +in_addr_t xcm_addr_ip::ip4 | +
Contains the IPv4 address in network byte order (in case family is set to AF_INET).
+ +uint8_t xcm_addr_ip::ip6[16] | +
Contains the IPv6 address (in case family is set to AF_INET6).
+ +union { ... } xcm_addr_ip::addr | +
Union containing the actual IPv4 or a IPv6 address bytes
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
Library Version | |
API Version |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the core Extensible Connection-oriented Messaging (XCM) API. +More...
+#include <errno.h>
#include <stdbool.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 *conn_socket, const void *buf, size_t len) |
int | xcm_receive (struct xcm_socket *conn_socket, void *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) |
This file contains the core Extensible Connection-oriented Messaging (XCM) API.
+#define XCM_NONBLOCK (1<<0) | +
Flag used in xcm_connect()
+ +#define XCM_SO_RECEIVABLE (1<<0) | +
Flag bit denoting a socket where the application likely can receive a message.
+ +#define XCM_SO_SENDABLE (1<<1) | +
Flag bit denoting a socket where the application likely can send a message.
+ +#define XCM_SO_ACCEPTABLE (1<<2) | +
Flag bit denoting a socket with a pending incoming connection.
+ +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).
+[in] | remote_addr | The remote address which to connect. |
[in] | flags | Either 0, or XCM_NONBLOCK for a non-blocking connect. |
errno | Description |
---|---|
EINVAL | Invalid address format. |
ENOPROTOOPT | Transport protocol not available. |
EMFILE | The limit on the total number of open fds has been reached. |
ENOENT | DNS domain name resolution failed. |
See xcm_finish() for other possible errno values.
+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.
+[in] | remote_addr | The remote address which to connect. |
[in] | attrs | A set of attributes to be applied to the connection socket, or NULL. |
See xcm_connect() and xcm_attr_set() for possible errno values.
+ +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), a xcm_server() call also includes a blocking name resolution (e.g. gethostbyname()).
+[in] | local_addr | The local address to which this socket should be bound. |
errno | Description |
---|---|
EACCESS | Permission to create the socket is denied. |
EADDRINUSE | Local socket address is already in use. |
ENOMEM | Insufficient memory. |
EINVAL | Invalid address format. |
ENOPROTOOPT | Transport protocol not available. |
EMFILE | The limit on the total number of open fds has been reached. |
EPROTO | A protocol error occured. |
ENOENT | DNS domain name resolution failed. |
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.
+[in] | local_addr | The local address to which this socket should be bound. |
[in] | attrs | A set of attributes to be applied to the socket, or NULL. |
See xcm_server() and xcm_attr_set() for possible errno values.
+ +int xcm_close | +( | +struct xcm_socket * | +socket | ) | ++ |
Close an endpoint.
+This function close a 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.
+[in] | socket | The socket to be closed, or NULL (in case xcm_close() is a no-operation). |
void xcm_cleanup | +( | +struct xcm_socket * | +socket | ) | ++ |
Cleans up any local resources tied to a 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().
+[in] | socket | The socket which local resources are to be freed, or NULL (in case xcm_cleanup() is a no-operation). |
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.
+[in] | server_socket | The server socket on which to attempt to accept one pending connection. |
errno | Description |
---|---|
EMFILE | The limit on the total number of open fds has been reached. |
See xcm_finish() for other possible errno values.
+ +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.
+[in] | server_socket | The server socket on which to attempt to accept one pending connection. |
[in] | attrs | A set of attributes to be applied to the socket, or NULL. |
See xcm_accept() and xcm_attr_set() for possible errno values.
+ +int xcm_send | +( | +struct xcm_socket * | +conn_socket, | +
+ | + | const void * | +buf, | +
+ | + | size_t | +len | +
+ | ) | ++ |
Send message on a particular connection.
+The xcm_send() function is used to send a message out on a connection socket. A XCM connection goes from a client to a server, and this connection socket may represent either one of the two endpoints.
+[in] | conn_socket | The connection socket the message will be sent on. |
[in] | buf | A pointer to the message data buffer. |
[in] | len | The length of the message in bytes. Zero-length messages are not allowed. |
errno | Description |
---|---|
EMSGSIZE | Message is too large. See also Generic Attributes. |
See xcm_finish() for more errno values.
+ +int xcm_receive | +( | +struct xcm_socket * | +conn_socket, | +
+ | + | void * | +buf, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Receive message on a particular connection.
+The xcm_receive() function is used to receive message on a connection socket. A XCM connection goes from a client to a server, and this connection socket may represent either one of the two endpoints.
+If 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).
+[in] | conn_socket | The connection socket the message will receive be on. |
[out] | buf | The user-supplied buffer where the incoming message will be stored. |
[in] | capacity | The capacity in bytes of the buffer. |
See xcm_finish() for possible errno values.
+ +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.
+[in] | socket | The XCM socket. |
[in] | condition | The condition the application is waiting for. |
errno | Description |
---|---|
EINVAL | The socket is not in non-blocking mode, or the condition bits are invalid. |
int xcm_fd | +( | +struct xcm_socket * | +socket | ) | ++ |
Returns XCM socket fd.
+This call retrieves the XCM socket fd for a XCM socket 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.
+Please 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.
[in] | socket | The connection or server socket. |
errno | Description |
---|---|
EINVAL | The socket is not in non-blocking mode. |
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, xcm_accept() or xcm_send() call on a connection socket in non-blocking mode, wishing to finish outstanding processing related to that operation, 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.
+[in] | socket | The connection or server socket. |
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. |
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.
+[in] | socket | The socket. |
[in] | should_block | Set to true for blocking operation, false for non-blocking mode. |
errno | Description |
---|---|
EAGAIN | The connection socket has unfinished work that needs to completed before mode can be switched. |
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.
+[in] | socket | The socket. |
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.
+[in] | conn_socket | The connection socket. |
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.
+[in] | socket | A server or connection socket. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses. +More...
+#include <errno.h>
#include <inttypes.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <xcm_addr_compat.h>
Go to the source code of this file.
++Data Structures | |
struct | xcm_addr_ip |
struct | xcm_addr_host |
+Macros | |
#define | XCM_UTLS_PROTO "utls" |
#define | XCM_TLS_PROTO "tls" |
#define | XCM_TCP_PROTO "tcp" |
#define | XCM_SCTP_PROTO "sctp" |
#define | XCM_UX_PROTO "ux" |
#define | XCM_UXF_PROTO "uxf" |
+Enumerations | |
enum | xcm_addr_type { xcm_addr_type_name +, xcm_addr_type_ip + } |
+Functions | |
int | xcm_addr_parse_proto (const char *addr_s, char *proto, size_t capacity) |
int | xcm_addr_parse_utls (const char *utls_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_tls (const char *tls_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_tcp (const char *tcp_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_sctp (const char *sctp_addr_s, struct xcm_addr_host *host, uint16_t *port) |
int | xcm_addr_parse_ux (const char *ux_addr_s, char *ux_path, size_t capacity) |
int | xcm_addr_parse_uxf (const char *uxf_addr_s, char *uxf_path, size_t capacity) |
int | xcm_addr_make_utls (const struct xcm_addr_host *host, unsigned short port, char *utls_addr_s, size_t capacity) |
int | xcm_addr_make_tls (const struct xcm_addr_host *host, unsigned short port, char *tls_addr_s, size_t capacity) |
int | xcm_addr_make_tcp (const struct xcm_addr_host *host, unsigned short port, char *tcp_addr_s, size_t capacity) |
int | xcm_addr_make_sctp (const struct xcm_addr_host *host, unsigned short port, char *sctp_addr_s, size_t capacity) |
int | xcm_addr_make_ux (const char *ux_name, char *ux_addr_s, size_t capacity) |
int | xcm_addr_make_uxf (const char *uxf_name, char *uxf_addr_s, size_t capacity) |
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses.
+#define XCM_UTLS_PROTO "utls" | +
Protocol string for the combined TLS+UX transport.
+ +#define XCM_TLS_PROTO "tls" | +
Protocol string for the Transport Layer Security (TLS) transport.
+ +#define XCM_TCP_PROTO "tcp" | +
Protocol string for the TCP transport.
+ +#define XCM_SCTP_PROTO "sctp" | +
Protocol string for the SCTP transport.
+ +#define XCM_UX_PROTO "ux" | +
Protocol string for the UNIX Domain socket (AF_UNIX SEQPACKET) transport (using the abstract namespace).
+ +#define XCM_UXF_PROTO "uxf" | +
Protocol string for the UNIX Domain socket (AF_UNIX SEQPACKET) transport (using file system-based naming).
+ +int xcm_addr_parse_proto | +( | +const char * | +addr_s, | +
+ | + | char * | +proto, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses the protocol part of a XCM address.
+[in] | addr_s | The XCM address string. |
[out] | proto | The buffer where to store the protocol part of the address. |
[in] | capacity | The buffer length in bytes. |
errno | Description |
---|---|
EINVAL | Malformed address. |
ENAMETOOLONG | The user-supplied buffer is too small to fit the protocol. |
int xcm_addr_parse_utls | +( | +const char * | +utls_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a UTLS XCM address.
+[in] | utls_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TLS port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_tls | +( | +const char * | +tls_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a TLS XCM address.
+[in] | tls_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TLS port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_tcp | +( | +const char * | +tcp_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parses a TCP XCM address.
+[in] | tcp_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The TCP port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_sctp | +( | +const char * | +sctp_addr_s, | +
+ | + | struct xcm_addr_host * | +host, | +
+ | + | uint16_t * | +port | +
+ | ) | ++ |
Parse a SCTP XCM address.
+[in] | sctp_addr_s | The string to sparse. |
[out] | host | The host (either DNS domain name or IPv4/v6 adress). |
[out] | port | The SCTP port in network byte order. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_ux | +( | +const char * | +ux_addr_s, | +
+ | + | char * | +ux_path, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses an UX (UNIX Domain Socket) XCM address.
+[in] | ux_addr_s | The string to sparse. |
[out] | ux_path | The UNIX (NUL-terminated) abstract name portion of the UX address. |
[in] | capacity | The length of the user-supplied path buffer. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_parse_uxf | +( | +const char * | +uxf_addr_s, | +
+ | + | char * | +uxf_path, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Parses an UXF (UNIX Domain Socket) XCM address.
+[in] | uxf_addr_s | The string to sparse. |
[out] | uxf_path | The UNIX (NUL-terminated) path name portion of the UXF address. |
[in] | capacity | The length of the user-supplied path buffer. |
errno | Description |
---|---|
EINVAL | Malformed address. |
int xcm_addr_make_utls | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +utls_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a UTLS XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | utls_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_tls | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +tls_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a TLS XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | tls_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_tcp | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +tcp_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a TCP XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | tcp_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_sctp | +( | +const struct xcm_addr_host * | +host, | +
+ | + | unsigned short | +port, | +
+ | + | char * | +sctp_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds a SCTP XCM address string from the supplied host and port.
+[in] | host | The host (either DNS domain name or IPv4/v6 adress). |
[in] | port | The port in network byte order. |
[out] | sctp_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid IP address. |
int xcm_addr_make_ux | +( | +const char * | +ux_name, | +
+ | + | char * | +ux_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds an UX XCM address string from the supplied UNIX Domain Socket name.
+[in] | ux_name | The UNIX Domain Socket name. |
[out] | ux_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid format of or too long UNIX Domain Socket address. |
int xcm_addr_make_uxf | +( | +const char * | +uxf_name, | +
+ | + | char * | +uxf_addr_s, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Builds an UXF XCM address string from the supplied file system path.
+[in] | uxf_name | The UNIX Domain path. |
[out] | uxf_addr_s | The user-supplied buffer where to store the result. |
[in] | capacity | The length of the buffer. |
errno | Description |
---|---|
ENAMETOOLONG | The user-supplied buffer is too small to fit the address. |
EINVAL | Invalid format of or too long UNIX Domain Socket address. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the XCM attribute access API. See Socket Attributes for an overview. +More...
+ +Go to the source code of this file.
++Typedefs | |
typedef void(* | xcm_attr_cb) (const char *attr_name, enum xcm_attr_type type, void *value, size_t value_len, void *cb_data) |
+Functions | |
int | xcm_attr_set (struct xcm_socket *socket, const char *name, enum xcm_attr_type type, const void *value, size_t len) |
int | xcm_attr_set_bool (struct xcm_socket *socket, const char *name, bool value) |
int | xcm_attr_set_int64 (struct xcm_socket *socket, const char *name, int64_t value) |
int | xcm_attr_set_str (struct xcm_socket *socket, const char *name, const char *value) |
int | xcm_attr_get (struct xcm_socket *socket, const char *name, enum xcm_attr_type *type, void *value, size_t capacity) |
int | xcm_attr_get_bool (struct xcm_socket *socket, const char *name, bool *value) |
int | xcm_attr_get_int64 (struct xcm_socket *socket, const char *name, int64_t *value) |
int | xcm_attr_get_str (struct xcm_socket *socket, const char *name, char *value, size_t capacity) |
void | xcm_attr_get_all (struct xcm_socket *socket, xcm_attr_cb cb, void *cb_data) |
This file contains the XCM attribute access API. See Socket Attributes for an overview.
+typedef void(* xcm_attr_cb) (const char *attr_name, enum xcm_attr_type type, void *value, size_t value_len, void *cb_data) | +
The signature of the user-supplied callback used in xcm_attr_get_all().
+ +int xcm_attr_set | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | enum xcm_attr_type | +type, | +
+ | + | const void * | +value, | +
+ | + | size_t | +len | +
+ | ) | ++ |
Sets the value of a socket attribute.
+Only attributes marked as writable may be set. For a list of available attributes for different socket and transport types, see Generic Attributes, TCP Socket Attributes and TLS Socket Attributes.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[in] | type | The value type of the new value. |
[in] | value | The new value. |
[in] | len | The length of the value. |
errno | Description |
---|---|
ENOENT | The attribute does not exist. |
EACCES | The attribute exists, but is read-only. |
EINVAL | The attribute name is too long, the attribute value type, value or value length is not valid for the specified attribute. |
int xcm_attr_set_bool | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | bool | +value | +
+ | ) | ++ |
Sets the value of a boolean socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[in] | value | The new boolean value. |
See xcm_attr_set() for possible errno values.
+ +int xcm_attr_set_int64 | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | int64_t | +value | +
+ | ) | ++ |
Sets the value of an integer socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[in] | value | The new integer value. |
See xcm_attr_set() for possible errno values.
+ +int xcm_attr_set_str | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | const char * | +value | +
+ | ) | ++ |
Sets the value of a string socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[in] | value | The new string value. |
See xcm_attr_set() for possible errno values.
+ +int xcm_attr_get | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | enum xcm_attr_type * | +type, | +
+ | + | void * | +value, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Retrieves the value of a socket attribute.
+For a list of available attributes for different socket and transport types, see Generic Attributes, TCP Socket Attributes and TLS Socket Attributes.
+For a description of the C types and buffer capacity requirements of the attribute types, see xcm_attr_types.h.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[out] | type | A pointer to a location where the type of the attribute will be stored. May be left to NULL, in case the type is known a priori. |
[out] | value | A user-supplied buffer where the value of the attribute will be stored. |
[in] | capacity | The length of the buffer (in bytes). |
errno | Description |
---|---|
ENOENT | The attribute does not exist. |
EACCES | The attribute exists, but is write-only. |
EOVERFLOW | The user-supplied buffer was too small to fit the value. |
int xcm_attr_get_bool | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | bool * | +value | +
+ | ) | ++ |
Retrieves the value of a boolean socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[out] | value | A user-supplied buffer where the value of the attribute will be stored. |
errno | Description |
---|---|
ENOENT | The attribute does not exist, or is not boolean. |
See xcm_attr_get() for other possible errno values.
+ +int xcm_attr_get_int64 | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | int64_t * | +value | +
+ | ) | ++ |
Retrieves the value of an integer socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[out] | value | A user-supplied buffer where the value of the attribute will be stored. |
errno | Description |
---|---|
ENOENT | The attribute does not exist, or is not an integer. |
See xcm_attr_get() for other possible errno values.
+ +int xcm_attr_get_str | +( | +struct xcm_socket * | +socket, | +
+ | + | const char * | +name, | +
+ | + | char * | +value, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Retrieves the value of a string socket attribute.
+[in] | socket | The connection or server socket. |
[in] | name | The name of the attribute. |
[out] | value | A user-supplied buffer where the string value of the attribute will be stored. |
[in] | capacity | The length of the buffer (in bytes). |
errno | Description |
---|---|
ENOENT | The attribute does not exist, or is not a string. |
See xcm_attr_get() for other possible errno values.
+ +void xcm_attr_get_all | +( | +struct xcm_socket * | +socket, | +
+ | + | xcm_attr_cb | +cb, | +
+ | + | void * | +cb_data | +
+ | ) | ++ |
Retrieves all XCM socket attributes.
+This function retrieves all available attribute names, types and their current values on a particular connection or server socket.
+The memory locations refered to by the attr_name and attr_value pointers is only guaranteed to be valid for the execution of the callback. If needed later, they need to be copied.
+[in] | socket | The connection or server socket. |
[in] | cb | The function to be called for every attribute on the socket. |
[in] | cb_data | An opaque (for XCM) pointer returned back to the application in the callback. cb_data may be NULL. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the XCM attribute map API. +More...
+ +Go to the source code of this file.
++Typedefs | |
typedef void(* | xcm_attr_map_foreach_cb) (const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len, void *user) |
+Functions | |
struct xcm_attr_map * | xcm_attr_map_create (void) |
struct xcm_attr_map * | xcm_attr_map_clone (const struct xcm_attr_map *original) |
void | xcm_attr_map_add (struct xcm_attr_map *attr_map, const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len) |
void | xcm_attr_map_add_bool (struct xcm_attr_map *attr_map, const char *attr_name, bool attr_value) |
void | xcm_attr_map_add_int64 (struct xcm_attr_map *attr_map, const char *attr_name, int64_t attr_value) |
void | xcm_attr_map_add_str (struct xcm_attr_map *attr_map, const char *attr_name, const char *attr_value) |
const void * | xcm_attr_map_get (const struct xcm_attr_map *attr_map, const char *attr_name, enum xcm_attr_type *attr_type, size_t *attr_value_len) |
const bool * | xcm_attr_map_get_bool (const struct xcm_attr_map *attr_map, const char *attr_name) |
const int64_t * | xcm_attr_map_get_int64 (const struct xcm_attr_map *attr_map, const char *attr_name) |
const char * | xcm_attr_map_get_str (const struct xcm_attr_map *attr_map, const char *attr_name) |
bool | xcm_attr_map_exists (const struct xcm_attr_map *attr_map, const char *attr_name) |
void | xcm_attr_map_del (struct xcm_attr_map *attr_map, const char *attr_name) |
size_t | xcm_attr_map_size (const struct xcm_attr_map *attr_map) |
void | xcm_attr_map_foreach (const struct xcm_attr_map *attr_map, xcm_attr_map_foreach_cb cb, void *user) |
bool | xcm_attr_map_equal (const struct xcm_attr_map *attr_map_a, const struct xcm_attr_map *attr_map_b) |
void | xcm_attr_map_destroy (struct xcm_attr_map *attr_map) |
This file contains the XCM attribute map API.
+A XCM attribute map is a set of key-value pairs. The key is an attribute name in the form of a string. One key maps to at most one value. The attribute value is either a boolean, a signed 64-bit integer, a string, or a variable-length binary object.
+typedef void(* xcm_attr_map_foreach_cb) (const char *attr_name, enum xcm_attr_type attr_type, const void *attr_value, size_t attr_value_len, void *user) | +
Callback function prototype used for iteration.
+ +struct xcm_attr_map * xcm_attr_map_create | +( | +void | +) | ++ |
Create an attribute map instance.
+struct xcm_attr_map * xcm_attr_map_clone | +( | +const struct xcm_attr_map * | +original | ) | ++ |
Create a copy of an attribute map instance.
+[in] | original | The original attribute map instance, to be copied. |
void xcm_attr_map_add | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | enum xcm_attr_type | +attr_type, | +
+ | + | const void * | +attr_value, | +
+ | + | size_t | +attr_value_len | +
+ | ) | ++ |
Associate a key with a value.
+This function associates the attribute key attr_name
to the attribute value attr_value
in the attribute map attr_map
. If the key attr_name
already exists, its value is replaced.
Both the key and the value will be copied, and thus attr_name
and attr_value
will still be owned by the caller at call completion.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_type | The type of the value to be added. |
[in] | attr_value | The value of the attribute to be added. |
[in] | attr_value_len | The length (in bytes) of the value. |
void xcm_attr_map_add_bool | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | bool | +attr_value | +
+ | ) | ++ |
Associate a key with a boolean value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The boolean value of the attribute to be added. |
void xcm_attr_map_add_int64 | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | int64_t | +attr_value | +
+ | ) | ++ |
Associate a key with a 64-bit signed integer value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The integer value of the attribute to be added. |
void xcm_attr_map_add_str | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | const char * | +attr_value | +
+ | ) | ++ |
Associate a key with a string value.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be added. |
[in] | attr_value | The string value of the attribute to be added. |
const void * xcm_attr_map_get | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name, | +
+ | + | enum xcm_attr_type * | +attr_type, | +
+ | + | size_t * | +attr_value_len | +
+ | ) | ++ |
Retrieve the value associated with a particular key.
+This function retrieves the attribute value, value type and value length of the attribute attr_name
, in case it exists.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
[out] | attr_type | A pointer to a buffer where the value type will be stored, or NULL. |
[out] | attr_value_len | A pointer to a buffer where the length (in bytes) of the value will be stored, or NULL. |
const bool * xcm_attr_map_get_bool | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the boolean value associated with a particular key.
+This function retrieves the boolean attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_bool.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
const int64_t * xcm_attr_map_get_int64 | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the integer value associated with a particular key.
+This function retrieves the 64-bit signed integer attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_int64.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
const char * xcm_attr_map_get_str | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Retrieve the string value associated with a particular key.
+This function retrieves the NUL-terminated string attribute value of the attribute attr_name
, in case it exists and is of type xcm_attr_type_str.
The value pointer returned is valid as long as the key is not removed, its value is changed, or the map is destroyed.
+[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be retrieved. |
bool xcm_attr_map_exists | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Check if an attribute named attr_name
exists in the attribute map.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute. |
void xcm_attr_map_del | +( | +struct xcm_attr_map * | +attr_map, | +
+ | + | const char * | +attr_name | +
+ | ) | ++ |
Removes an attribute from the attribute map.
+This function deletes the attribute attr_name
, in case it exists.
[in] | attr_map | The attribute map instance. |
[in] | attr_name | The name of the attribute to be deleted. |
size_t xcm_attr_map_size | +( | +const struct xcm_attr_map * | +attr_map | ) | ++ |
Returns the number of attributes in the attribute map.
+[in] | attr_map | The attribute map instance. |
attr_map
. void xcm_attr_map_foreach | +( | +const struct xcm_attr_map * | +attr_map, | +
+ | + | xcm_attr_map_foreach_cb | +cb, | +
+ | + | void * | +user | +
+ | ) | ++ |
Iterates over all attributes in a map.
+This function calls the supplied callback function cb
for each attribute in attr_map
.
The map may not be modified during iteration.
+[in] | attr_map | The attribute map instance. |
[in] | cb | The callback function. |
[in] | user | An opaque pointer, supplied back to the application in every cb call. |
bool xcm_attr_map_equal | +( | +const struct xcm_attr_map * | +attr_map_a, | +
+ | + | const struct xcm_attr_map * | +attr_map_b | +
+ | ) | ++ |
Compares two attribute maps for equality (by value).
+[in] | attr_map_a | An attribute map instance. |
[in] | attr_map_b | An attribute map instance. |
attr_map_a
and attr_map_a
are equal, false otherwise. void xcm_attr_map_destroy | +( | +struct xcm_attr_map * | +attr_map | ) | ++ |
Destroys an attribute map instance.
+This function destroys the attribute map instance and frees all the resources associated with it.
+[in] | attr_map | The attribute map instance, or NULL. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains type definitions for the XCM attribute access API. +More...
+ +Go to the source code of this file.
++Enumerations | |
enum | xcm_attr_type { xcm_attr_type_bool = 1 +, xcm_attr_type_int64 = 2 +, xcm_attr_type_str = 3 +, xcm_attr_type_bin = 4 + } |
This file contains type definitions for the XCM attribute access API.
+enum xcm_attr_type | +
Enumeration representing the different attribute value types.
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains obsolete parts of the XCM core API. +More...
+ +Go to the source code of this file.
++Macros | |
#define | XCM_FD_READABLE (1<<0) |
#define | XCM_FD_WRITABLE (1<<1) |
#define | XCM_FD_EXCEPTION (1<<2) |
+Functions | |
int | xcm_want (struct xcm_socket *socket, int condition, int *fds, int *events, size_t capacity) |
This file contains obsolete parts of the XCM core API.
+It should not be included directly, but rather only via <xcm.h>.
+#define XCM_FD_READABLE (1<<0) | +
Flag bit denoting a readable fd event in xcm_want().
+ +#define XCM_FD_WRITABLE (1<<1) | +
Flag bit denoting a writable fd event.
+ +#define XCM_FD_EXCEPTION (1<<2) | +
Flag bit denoting a exception fd event.
+ +int xcm_want | +( | +struct xcm_socket * | +socket, | +
+ | + | int | +condition, | +
+ | + | int * | +fds, | +
+ | + | int * | +events, | +
+ | + | size_t | +capacity | +
+ | ) | ++ |
Query the socket what events on which file descriptors it's waiting for.
+Please note: this function is obsolete, replaced by xcm_fd() and xcm_await().
+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.
+With xcm_want(), the application will inform the XCM socket what condition it's waiting for (i.e. what XCM operation it wants to perform), and in return the XCM socket will provide a set of file descriptors and, for each fd, information on what type of event on that fd it require to make progress. Progress can mean both progress toward the goal of reaching the application's desired socket condition, or finishing any outstanding task the XCM socket has.
+In case any of the conditions the application is asking for are believed to be already met, the xcm_want() call will return 0.
+In case the XCM socket has no outstanding tasks, and the application is not asking for any operation that the XCM socket believes it can't immediate fulfill, the call will return 0.
+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.
+Note that XCM may ask the application to wait for the connection's fd or fds to become writable, even if the application is waiting to receive a message. It may also ask the application to wait for the connection's fd to become readable, even if the application is attemting to send a messaging.
+Even though the conditions for a particular connection socket are met (fd is becoming writable, for example), there's no guarantee that the xcm_send() or xcm_receive() won't block (or in case of non-blocking mode, won't fail and set EAGAIN).
+The XCM socket fds may only be used with select(). Supplying this fd to any other OS calls (such as setsockopt(2), read(2) etc) is prohibited.
+The information received on which fd to use, and what events on that fd are relevant for the connection socket in its current state, are only valid until more xcm_* calls are made on this socket. See Finishing Outstanding Tasks for more information.
+The fd is an positive integer, unique within this process.
+The condition parameter is a bitmask, with the bits being XCM_SO_RECEIVABLE, XCM_SO_SENDABLE, and/or XCM_SO_ACCEPTABLE. If no bits are set, the application is not interested in anything beyond this XCM socket to finish any outstanding task.
+Each element in the events array is an int used as a bitmask. The bitmask at position N in the events array represents the file descriptor events the XCM transport is waiting for, for fd at position N in the fds array. The bits are XCM_FD_READABLE, XCM_FD_WRITABLE and/or XCM_FD_EXCEPTION. At least one bit is always set.
+If a socket is waiting for multiple events (for example, both readable and writable on the same fd, or readable on one fd, and writeable on another), the condition is met whenever any of the events occur (as oppose to all events).
+[in] | socket | The XCM socket. |
[in] | condition | The condition the application is waiting for. |
[out] | fds | An user-supplied array to store the fds. |
[out] | events | An user-supplied array of int to store the bitmask of each of the fds in the fds array. |
[in] | capacity | The length of the fds and events arrays. |
errno | Description |
---|---|
EOVERFLOW | The user-supplied buffer was too small to fit the socket's fds. |
EINVAL | The socket is not in blocking mode, or the condition bits are invalid. |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains functions and macros to retrieve XCM version information. The library (i.e., implementation) version uses the semver convention. +More...
+ +Go to the source code of this file.
++Macros | |
#define | XCM_VERSION_MAJOR 1 |
#define | XCM_VERSION_MINOR 5 |
#define | XCM_VERSION_PATCH 0 |
#define | XCM_VERSION "1.5.0" |
#define | XCM_VERSION_API_MAJOR 0 |
#define | XCM_VERSION_API_MINOR 20 |
#define | XCM_VERSION_API "0.20" |
+Functions | |
unsigned int | xcm_version_major (void) |
unsigned int | xcm_version_minor (void) |
unsigned int | xcm_version_patch (void) |
const char * | xcm_version (void) |
unsigned int | xcm_version_api_major (void) |
unsigned int | xcm_version_api_minor (void) |
const char * | xcm_version_api (void) |
This file contains functions and macros to retrieve XCM version information. The library (i.e., implementation) version uses the semver convention.
+#define XCM_VERSION_MAJOR 1 | +
The XCM library major version.
+ +#define XCM_VERSION_MINOR 5 | +
The XCM library minor version.
+ +#define XCM_VERSION_PATCH 0 | +
The XCM library patch version.
+ +#define XCM_VERSION "1.5.0" | +
The complete XCM library version in string format.
+ +#define XCM_VERSION_API_MAJOR 0 | +
The XCM API/ABI major version this library version implements.
+ +#define XCM_VERSION_API_MINOR 20 | +
The XCM API/ABI minor version this library version implements.
+ +#define XCM_VERSION_API "0.20" | +
The complete XCM API version in string format.
+ +unsigned int xcm_version_major | +( | +void | +) | ++ |
Retrieves the library major version.
+This function returns the implementation major version of the library used at run time.
+ +unsigned int xcm_version_minor | +( | +void | +) | ++ |
Retrieves the library minor version.
+This function returns the implementation minor version of the library used at run time.
+ +unsigned int xcm_version_patch | +( | +void | +) | ++ |
Retrieves the library patch version.
+This function returns the implementation patch version of the library used at run time.
+ +const char * xcm_version | +( | +void | +) | ++ |
Retrieves the library version as a string.
+This function returns the version of the library used at run time, in string format.
+The string returned is statically allocated, and thus must not be free'd by the caller.
+ +unsigned int xcm_version_api_major | +( | +void | +) | ++ |
Retrieves the XCM API major version.
+This function returns the API major version of the library used at run time adheres to.
+ +unsigned int xcm_version_api_minor | +( | +void | +) | ++ |
Retrieves the XCM API minor version.
+This function returns the API minor version of the library used at run time adheres to.
+ +const char * xcm_version_api | +( | +void | +) | ++ |
Retrieves the library API version as a string.
+This function returns the API version of the library used at run time adheres to.
+The string returned is statically allocated, and thus must not be free'd by the caller.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
Cxcm_addr_host | |
Cxcm_addr_ip |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Files | |
xcm.h | |
This file contains the core Extensible Connection-oriented Messaging (XCM) API. | |
xcm_addr.h | |
This is an API for building and parsing Connection-oriented Messaging (XCM) addresses. | |
xcm_attr.h | |
This file contains the XCM attribute access API. See Socket Attributes for an overview. | |
xcm_attr_map.h | |
This file contains the XCM attribute map API. | |
xcm_attr_types.h | |
This file contains type definitions for the XCM attribute access API. | |
xcm_compat.h | |
This file contains obsolete parts of the XCM core API. | |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
▼ include | |
xcm.h | This file contains the core Extensible Connection-oriented Messaging (XCM) API |
xcm_addr.h | This is an API for building and parsing Connection-oriented Messaging (XCM) addresses |
xcm_attr.h | This file contains the XCM attribute access API. See Socket Attributes for an overview |
xcm_attr_map.h | This file contains the XCM attribute map API |
xcm_attr_types.h | This file contains type definitions for the XCM attribute access API |
xcm_compat.h | This file contains obsolete parts of the XCM core API |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Macros | |
#define | XCM_VERSION_API_MAJOR 0 |
#define | XCM_VERSION_API_MINOR 22 |
#define | XCM_VERSION_API "0.22" |
#define XCM_VERSION_API_MAJOR 0 | +
The XCM API/ABI major version this library version implements.
+ +#define XCM_VERSION_API_MINOR 22 | +
The XCM API/ABI minor version this library version implements.
+ +#define XCM_VERSION_API "0.22" | +
The complete XCM API version in string format.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
+Macros | |
#define | XCM_VERSION_MAJOR 1 |
#define | XCM_VERSION_MINOR 7 |
#define | XCM_VERSION_PATCH 0 |
#define | XCM_VERSION "1.7.0" |
#define XCM_VERSION_MAJOR 1 | +
The XCM library major version.
+ +#define XCM_VERSION_MINOR 7 | +
The XCM library minor version.
+ +#define XCM_VERSION_PATCH 0 | +
The XCM library patch version.
+ +#define XCM_VERSION "1.7.0" | +
The complete XCM library version in string format.
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This is the documentation for the Extensible Connection-oriented Messaging (XCM) programming APIs.
+XCM consists the core API in xcm.h, an address helper library API in xcm_addr.h, and the attribute APIs in xcm_attr.h and xcm_attr_map.h. Obsolete, but still present, functions are available in xcm_compat.h
+The low API/ABI version number is a result of all XCM releases being backward compatible, and thus left the major version at 0.
+XCM is an inter-process communication API and an implementation of this C API in the form a shared library. For certain transports, XCM may also be used to denote a tiny bit of wire protocol, providing framing over byte stream transport protocols.
+The primary component of the XCM library is a set of inter-process communication transports - all hosted under the same API. A XCM transport provides a connection-oriented, reliable service, with in-order delivery. There are two types of transports; one providing a messaging service and another providing a byte stream.
+The XCM API allows a straight-forward mapping to TLS, TCP and SCTP for remote communcation, as well as more efficient inter-process commmunication (IPC) mechanisms for local communication.
+This document focuses on the API, but also contains information specific to the implementation.
+XCM reuses much of the terminology of the BSD Sockets API. Compared to the BSD Socket API, XCM has more uniform semantics across underlying transports.
+XCM implements a connection-oriented, client-server model. The server process creates one or more server sockets (e.g, with xcm_server()) bound to a specific address, after which clients may successfully establish connections to the server. When a connection is establishment, two connection sockets will be created; one on the server side (e.g., returned from xcm_accept()), and one of the client side (e.g., returned from xcm_connect()). Thus, a server serving multiple clients will have multiple sockets; one server socket and N connection sockets, one each for every client. A client will typically have one connection socket for each server it is connected to.
+User application data (messages or bytes, depending on service type) are always sent and received on a particular connection socket - never on a server socket.
+A XCM transport either provides a messaging or a byte stream service.
+Messaging transports preserve message boundaries across the network. The buffer passed to xcm_send() constitutes one (and only one) message. What's received on the other end, in exactly one xcm_receive() call, is a buffer with the same length and contents.
+The UX Transport, TCP Transport, TLS Transport, UTLS Transport, and SCTP Transport all provide a messaging type service.
+For byte streams, there's no such thing as message boundaries: the data transported on the connection is just a sequence of bytes. The fact that xcm_send() accepts an array of bytes of a particular length, as opposed to individual bytes one-by-one, is a mere performance optimization.
+For example, if two messages "abc" and "d" are passed to xcm_send() on to a messaging transport, they will arrive as "abc" and "d" in exactly two xcm_receive() call on the receiver. On a byte stream transport however, all the data "abcd" may arrive in a single xcm_receive(), or it may arrive in multiple calls, such as three calls, each producing "ab", "c", and "d", respectively, or any other combination.
+The BTLS Transport transport provides a byte stream service.
+Applications that allow the user to configure an arbitrary XCM address, but are designed to handle only a certain service type, may limit what type of sockets may be instantiated to be of only the messaging service type, or only byte stream, by passing the "xcm.service" attribute with the appropriate value (see Generic Attributes for details) at the time of socket creation. Because of XCM's history as a messaging-only framework, "xcm.service" defaults to "messaging".
+Applications which are designed to handle both messaging and byte stream transports may retrieve the value of "xcm.service" and use it to differentiate the treatment where so is required (e.g., in xcm_send() return code handling).
+Connections spawned off a server socket (e.g., with xcm_accept()) always have the same service type as their parent socket.
+In-order delivery - that data arrives at the recipient in the same order it was sent by the sender - is guaranteed, but only for data sent on the same connection.
+XCM transports support flow control. Thus, if the sender message rate or bandwidth is higher than the network or the receiver can handle on a particular connection, xcm_send() in the sender process will eventually block (or return an error EAGAIN, if in non-blocking mode). Unless XCM is used for bulk data transfer (as oppose to signaling traffic), xcm_send() blocking because of slow network or a slow receiver should be rare in practice. TCP, TLS, and UNIX domain socket transports all have large protocol windows and/or socket buffers to allow a large amount of outstanding data.
+In XCM, the application is in control of which transport will be used, using the address supplied to xcm_connect() and xcm_server() including both the transport name and the transport address.
+However, there is nothing preventing a XCM transport to use a more abstract addressing format, and internally include multiple underlying IPC transport mechanism. This model is implemented by the UTLS Transport.
+Addresses are represented as strings with the following general syntax: <transport-name>:<transport-address>
For the UX UNIX Domain Socket transport, the addresses has this more specific form:
+
The addresses of the UXF UNIX Domain Socket transport variant have the following format:
+
For the TCP, TLS, UTLS, SCTP and BTLS transports the syntax is:
+
'*' is a shorthand for '0.0.0.0' (i.e. bind to all IPv4 interfaces). '[*]' is the IPv6 equivalent, creating a server socket accepting connections on all IPv4 and IPv6 addresses.
+IPv6 link local addresses are not supported.
+Some examples addresses:
For TCP, TLS, UTLS, SCTP and BTLS server socket addresses, the port can be set to 0, in which case XCM (or rather, the Linux kernel) will allocate a free TCP port from the local port range.
+For transports allowing a DNS domain name as a part of the address, the transport will attempt resoĺv the name to an IP address. A DNS domain name may resolv to zero or more IPv4 addresses and/or zero or more IPv6 addresses. XCM relies on the operating system to prioritize between IPv4 and IPv6.
+XCM accepts IPv4 addresses in the dotted-decimal format
XCM allows only complete addresses with three '.', and not the archaic, classful, forms, where some bytes where left out, and thus the address contained fewer separators.
+XCM transports attempt to detect a number of conditions which can lead to lost connectivity, and does so even on idle connections.
+If the remote end closes the connection, the local xcm_receive() will return 0. If the process on the remote end crashed, xcm_receive() will return -1 and set errno ECONNRESET. If network connectivity to the remote end is lost, xcm_receive() will return -1 and errno will be set to ETIMEDOUT.
+In general, XCM follows the UNIX system API tradition when it comes to error handling. Where possible, errors are signaled to the application by using unused parts of the value range of the function return type. For functions returning signed integer types, this means the value of -1 (in case -1 is not a valid return value). For functions returning pointers, NULL is used to signal that an error has occurred. For functions where neither -1 or NULL can be used, or where the function does not return anything (side-effect only functions), an 'int' is used as the return type, and is used purely for the purpose to signal success (value 0), or an error (-1) to the application.
+The actual error code is stored in the thread-local errno variable. The error codes are those from the fixed set of errno values defined by POSIX, found in errno.h. Standard functions such as perror() and strerror() may be used to turn the code into a human-readable string.
+In non-blocking operation, given the fact the actual transmission might be defered (and the message buffered in the XCM layer), and that message receive processing might happen before the application has called receive, the error being signaled at the point of a certain XCM call might not be a direct result of the requested operation, but rather an error discovered previously.
+The documentation for xcm_finish() includes a list of generic error codes, applicable xcm_connect(), xcm_accept(), xcm_send() and xcm_receive().
+Also, for errors resulting in an unusable connection, repeated calls will produce the same errno.
+In UNIX-style event-driven programming, a single application thread handles multiple clients (and thus multiple XCM connection sockets) and the task of accepting new clients on the XCM server socket concurrently (although not in parallel). To wait for events from multiple sources, an I/O multiplexing facility such as select(2), poll(2) or epoll(2) is used.
+Each XCM socket is represented by a single fd, retrieved with xcm_fd(). The fd number and underlying file object is stable across the life-time of the socket.
+On BSD Sockets, the socket fd being readable means it's likely that the application can successfully read data from the socket. Similarily, a fd marked writable by, for example, poll() means that the application is likely to be able to write data to the BSD Sockets fd. For an application using XCM going into select(), it must always wait for all the fds its XCM sockets to become readable (e.g. being in the readfds
in the select() call), regardless what are their target conditions. Thus, even if the application is waiting for an opportunity to try to send a message on a XCM socket, or it doesn't want to do anything with the socket, it must wait for the socket fd to become readable. Not wanting to do nothing here means that the application has the xcm_await() condition set to 0, and is neither interested in waiting to call xcm_send(), xcm_receive(), nor xcm_accept() on the socket. An application may never leave a XCM socket unattended in the sense its fd is not in the set of fds passed to select() and/or xcm_send(), xcm_receive(), xcm_accept() or xcm_finish() are not called.
XCM is oblivious to what I/O multiplexing mechanism employed by the application. It may call select(), poll() or epoll_wait() directly, or make use of any of the many available event loop libraries (such as libevent). For simplicity, select() is used in this documentation to denote the whole family of Linux I/O multiplexing facilities.
+An event-driven application needs to set the XCM sockets it handles into non-blocking mode, by calling xcm_set_blocking(), setting the "xcm.blocking" socket attribute, or using the XCM_NONBLOCK flag in xcm_connect().
+For XCM sockets in non-blocking mode, all potentially blocking API calls related to XCM connections - xcm_connect(), xcm_accept(), xcm_send(), and xcm_receive() - finish immediately.
+For xcm_send(), xcm_connect() and xcm_accept(), XCM signaling success means that the XCM layer has accepted the request. It may or may not have completed the operation.
+In case the XCM_NONBLOCK flag is set in the xcm_connect() call, or in case the a XCM server socket is in non-blocking mode at the time of a xcm_accept() call, the newly created XCM connection returned to the application may be in a semi-operational state, with some internal processing and/or signaling with the remote peer still required before actual message transmission and reception may occur.
+The application may attempt to send or receive messages on such semi-operational connections.
+There are ways for an application to determine when connection establishment or the task of accepting a new client have completed. See Finishing Outstanding Tasks for more information.
+To receive a message on a XCM connection socket in non-blocking mode, the application may need to wait for the right conditions to arise (i.e. a message being available). The application needs to inform the socket that it wants to receive by calling xcm_await() with the XCM_SO_RECEIVABLE
bit in the condition
bit mask set. It will pass the fd it received from xcm_fd() into select(), asking to get notified when the fd becomes readable. When select() marks the socket fd as readable, the application should issue xcm_receive() to attempt to retrieve a message.
xcm_receive() may also called on speculation, prior to any select() call, to poll the socket for incoming messages.
+A XCM connection socket may have a number of messages buffered, and applications should generally, for optimal performance, repeat xcm_receive() until it returns an error, and errno is set to EAGAIN.
+Similarly to receiving a message, an application may set the XCM_SO_SENDABLE
bit in the condition
bit mask, if it wants to wait for a socket state where it's likely it can successfully send a message. When select() marks the socket fd as readable, the application should attempt to send a message.
Just like with xcm_receive(), it may also choose to issue a xcm_send() call on speculation (i.e. without going into select()), which is often a good idea for performance reasons.
+For send operations on non-blocking connection sockets, XCM may buffer whole or part of the message (or data, for byte stream transports) before transmission to the lower layer. This may be due to socket output buffer underrun, or the need for some in-band signaling, like cryptographic key exchange, to happen before the transmission of the complete message may finish. The XCM layer will (re-)attempt to hand the message over to the lower layer at a future call to xcm_finish(), xcm_send(), or xcm_receive().
+For applications wishing to determine when all buffered data have successfully been deliver to the lower layer, may use xcm_finish() to do so. Normally, applications aren't expected to require this kind of control. Please also note that the fact a message has left the XCM layer doesn't necessarily mean it has successfully been delivered to the recipient. In particular, if for some reason the data can be dispatched immediately, it may be lingering in kernel buffers. Such buffers may be discarded in case the application close the connection.
+xcm_connect(), xcm_accept(), xcm_send() may all leave the socket in a state where work is initiated, but not completed. In addition, the socket may have pending internal tasks, such flushing the output buffer into the TCP/IP stack, processing XCM control interface messages, or finishing the TLS hand shake procedure.
+After waking up from a select() call, where a particular XCM non-blocking socket's fd is marked readable, the application must, if no xcm_send(), xcm_receive() or xcm_accept() calls are to be made, call xcm_finish(). This is to allow the socket to finish any outstanding tasks, even in the case the application has no immediate plans for the socket.
+Prior to changing a socket from non-blocking to blocking mode, any outstanding tasks should be finished, or otherwise the switch might cause xcm_set_blocking() to return -1 and set errno to EAGAIN.
+For example, if a server socket's desired condition has been set (with xcm_await()) to XCM_SO_ACCEPTABLE
, and the application wakes up from select() with the socket's fd marked readable, a call to xcm_accept() may still not produce a new connection socket.
The same holds true when reaching XCM_SO_RECEIVABLE
and a xcm_receive() call is made, and XCM_SO_SENDABLE
and calls to xcm_send().
In this example, the application connects and tries to send a message, before knowing if the connection is actually established. This may fail (for example, in case TCP and/or TLS-level connection establishment has not yet been completed), in which case the application will fall back and wait with the use of xcm_await(), xcm_fd() and select().
+In case the application wants to know when the connection establishment has finished, it may use xcm_finish() to do so, like in the below example sequence.
+While connecting to a server socket, the client's connection attempt may be refused immediately.
+In many cases, the application is handed a connection socket before the connection establishment is completed. Any errors occuring during this process is handed over to the application at a future call to xcm_finish(), xcm_send() or xcm_receive().
+In this example the application flushes any internal XCM buffers before shutting down the connection, to ensure that any buffered messages are delivered to the lower layer.
+In this sequence, a server accepts a new connection, and continues to attempt to receive a message on this connection, while still, concurrently, is ready to accept more clients on the server socket.
+Tied to an XCM server or connection socket is a set of key-value pairs known as attributes. Which attributes are available varies across different transports, and different socket types.
+An attribute's name is a string, and follows a hierarchical naming schema. For example, all generic XCM attributes, available in all transports, have the prefix "xcm.". Transport-specific attributes are prefixed with the transport or protocol name (e.g. "tcp." for TCP-specific attributes applicable to the TLS, BTLS, and TCP transports).
+An attribute may be read-only, write-only or available both for reading and writing. This is referred to as the attribute's mode. The mode may vary across the lifetime of the socket. For example, an attribute may be writable at the time of the xcm_connect() call, and read-only thereafter.
+The attribute value is coded in the native C data type and byte order. Strings are NUL-terminated, and the NUL character is included in the length of the attribute. There are four value types; a boolean type, a 64-bit signed integer type, a string type and a type for arbitrary binary data. See xcm_attr_types.h for details.
+The attribute access API is in xcm_attr.h.
+Retrieving an integer attribute's value may look like this:
Changing an integer attribyte value may be done in the following manner:
Both of these examples are missing error handling.
+XCM allows supplying a set of writable attributes at the time of socket creation, by using the xcm_connect_a(), xcm_server_a(), or xcm_accept_a() functions.
+The attribute sets are represented by the xcm_attr_map
type in xcm_attr_map.h.
A somewhat contrived example:
These attributes are expected to be found on XCM sockets regardless of transport type.
+For TCP transport-specific attributes, see TCP Socket Attributes, and for TLS, see TLS Socket Attributes.
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
xcm.type | All | String | R | The socket type: "server" or "connection". |
xcm.transport | All | String | R | The transport type. |
xcm.service | All | String | RW | The service type: "messaging" or "bytestream". Writable only at the time of socket creation. If specified, it may be used by an application to limit the type of transports being used. The string "any" may be used to signify that any type of service is accepted. The default is "messaging". |
xcm.local_addr | All | String | RW | The local address of a socket. Writable only if supplied to xcm_connect_a() together with a TLS, UTLS or TCP type address. Usually only needs to be written on multihomed hosts, in cases where the application needs to specify the source IP address to be used. Also see xcm_local_addr(). |
xcm.blocking | All | Boolean | RW | See xcm_set_blocking() and xcm_is_blocking(). |
xcm.remote_addr | Connection | String | R | See xcm_remote_addr(). |
xcm.max_msg_size | Connection | Integer | R | The maximum size of any message transported by this connection. |
XCM connections sockets keeps track of the amount of data entering or leaving the XCM layer, both from the application and to the lower layer. Additionally, messaging transports also track the number of messages.
+Some of the message and byte counter attributes use the concept of a "lower layer". What this means depends on the transport. For the UX And TCP transports, it is the Linux kernel. For example, for TCP, if the xcm.to_lower_msgs is incremented, it means that XCM has successfully sent the complete message to the kernel's networking stack for further processing. It does not means it has reached the receiving process. It may have, but it also may be sitting on the local or remote socket buffer, on a NIC queue, or be in-transmit in the network. For TLS, the lower layer is OpenSSL.
+The counters only reflect data succesfully sent and/or received.
+These counters are available on both byte stream and messaging type connection sockets.
+The byte counters are incremented with the length of the XCM data (as in the length field in xcm_send()), and thus does not include any underlying headers or other lower layer overhead.
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
xcm.from_app_bytes | Connection | Integer | R | Bytes sent from the application and accepted into XCM. |
xcm.to_app_bytes | Connection | Integer | R | Bytes delivered from XCM to the application. |
xcm.from_lower_bytes | Connection | Integer | R | Bytes received by XCM from the lower layer. |
xcm.to_lower_bytes | Connection | Integer | R | Bytes successfully sent by XCM into the lower layer. |
These counters are available only on messaging type connection sockets.
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
xcm.from_app_msgs | Connection | Integer | R | Messages sent from the application and accepted into XCM. |
xcm.to_app_msgs | Connection | Integer | R | Messages delivered from XCM to the application. |
xcm.from_lower_msgs | Connection | Integer | R | Messages received by XCM from the lower layer. |
xcm.to_lower_msgs | Connection | Integer | R | Messages successfully sent by XCM into the lower layer. |
XCM includes a control interface, which allows iteration over the OS instance's XCM server and connection sockets (for processes with the appropriate permissions), and access to their attributes (see Socket Attributes).
+The control interface is optional by means of build-time configuration.
+For each XCM server or connection socket, there is a corresponding UNIX domain socket which is used for control signaling (i.e. state retrieval).
+By default, the control interface's UNIX domain sockets are stored in the /run/xcm/ctl
directory.
This directory should to be created prior to running any XCM applications for the control interface to worker properly and should be writable for all XCM users.
+A particular process using XCM may be configured to use a non-default directory for storing the UNIX domain sockets used for the control interface by means of setting the XCM_CTL
variable. Please note that using this setting will cause the XCM connections to be not visible globally on the OS instance (unless all other XCM-using processes also are using this non-default directory).
Generally, since the application is left unaware (from an API perspective) of the existence of the control interface, errors are not reported up to the application. They are however logged.
+Application threads owning XCM sockets, but which are busy with non-XCM processing for a long duration of time, or otherwise are leaving their XCM sockets unattended to (in violation of XCM API contract), will not respond on the control interface's UNIX domain sockets (corresponding to their XCM sockets). Only the presence of these sockets may be detected, but their state cannot be retrieved.
+Internally, the XCM implementation has control interface client library, but this library's API is not public at this point.
+XCM includes a command-line program xcmctl
which uses the Control API to iterate of the system's current XCM sockets, and allow access (primarily for debugging purposes) to the sockets' attributes.
Unlike BSD sockets, a XCM socket may not be shared among different threads without synchronization external to XCM. With proper external serialization, a socket may be shared by different threads in the same process, although it might provide difficult in practice since a thread in a blocking XCM function will continue to hold the lock, and thus preventing other threads from accessing the socket at all.
+For non-blocking sockets, threads sharing a socket need to agree on what is the appropriate socket condition
to wait for. When this condition is met, all threads are woken up, returning from select().
It is safe to "give away" a XCM socket from one thread to another, provided the appropriate memory fences are used.
+These limitations (compared to BSD Sockets) are in place to allow socket state outside the kernel (which is required for TCP framing and TLS).
+Sharing a XCM socket between threads in different processes is not possible.
+After a fork() call, either of the two process (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 not call any other XCM API call than xcm_cleanup(), which frees local memory tied to this socket in the non-owner's process address space, without impacting the connection state in the owner process.
+The core XCM API functions are oblivious to the transports used. However, the support for building, and parsing addresses are available only for a set of pre-defined set of transports. There is nothing preventing xcm_addr.h from being extended, and also nothing prevents an alternative XCM implementation to include more transports without extending the address helper API.
+The UX transport uses UNIX Domain (AF_UNIX, also known as AF_LOCAL) Sockets to providing a service of the messaging type.
+UX sockets may only be used with the same OS instance (or, more specifically, between processes in the same Linux kernel network namespace).
+UNIX Domain Sockets comes in a number of flavors, and XCM uses the SOCK_SEQPACKET variety. SOCK_SEQPACKET sockets are connection-oriented, preserves message boundaries and delivers messages in the same order they were sent; perfectly matching XCM semantics and provides for an near-trivial mapping.
+UX is the most efficient of the XCM transports.
+The standard UNIX Domain Sockets as defined by POSIX uses the file system as its namespace, with the sockets also being files. However, for simplicity and to avoid situations where stale socket files (originating from crashed processes) causing problems, the UX transport uses a Linux-specific extension, allowing a private UNIX Domain Socket namespace. This is known as the abstract namespace (see the unix(7) man page for details). With the abstract namespace, server socket address allocation has the same life time as TCP ports (i.e. if the process dies, the address is free'd).
+The UX transport enables the SO_PASSCRED BSD socket option, to give the remote peer a name (which UNIX domain connection socket doesn't have by default). This is for debugging and observability purposes. Without a remote peer name, in server processes with multiple incoming connections to the same server socket, it's difficult to say which of the server-side connection sockets goes to which remote peer. The kernel-generated, unique, name is an integer in the form "%05x" (printf format). Applications using hardcoded UX addresses should avoid such names by, for example, using a prefix.
+The UTLS Transport also indirectly uses the UX namespace, so care should be taken to avoid any clashes between UX and UTLS sockets in the same network namespace.
+The UXF transport is identical to the UX transport, only it uses the standard POSIX naming mechanism. The name of a server socket is a file system path, and the socket is also a file.
+The UXF sockets resides in a file system namespace, as opposed to UX sockets, which live in a network namespace.
+Upon xcm_close(), the socket will be closed and the file removed. If an application crashes or otherwise fails to run xcm_close(), it will leave a file in the file system pointing toward a non-existing socket. This file will prevent the creation another server socket with the same name.
+The TCP transport uses the Transmission Control Protocol (TCP), by means of the BSD Sockets API.
+TCP is a byte-stream service, but the XCM TCP transport adds framing on top of the stream. A single-field 32-bit header containing the message length in network byte order is added to every message.
+TCP uses TCP Keepalive to detect lost network connectivity between the peers.
+The TCP transport supports IPv4 and IPv6.
+Since XCM is designed for signaling traffic, the TCP transport disables the Nagle algorithm of TCP to avoid its excessive latency.
+The read-only TCP attributes are retrieved from the kernel (struct tcp_info in linux/tcp.h).
+The read-write attributes are mapped directly to setsockopt() calls.
+See the tcp(7) manual page for a more detailed description of these attributes. The struct retrieved with TCP_INFO
is the basis for the read-only attributes. The read-write attributes are mapped to TCP_KEEP*
and TCP_USER_TIMEOUT
.
Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
tcp.rtt | Connection | Integer | R | The current TCP round-trip estimate (in us). |
tcp.total_retrans | Connection | Integer | R | The total number of retransmitted TCP segments. |
tcp.segs_in | Connection | Integer | R | The total number of segments received. |
tcp.segs_out | Connection | Integer | R | The total number of segments sent. |
tcp.keepalive | Connection | Boolean | RW | Controls if TCP keepalive is enabled. The default is true. |
tcp.keepalive_time | Connection | Integer | RW | The time (in s) before the first keepalive probe is sent on an idle connection. The default is 1 s. |
tcp.keepalive_interval | Connection | Integer | RW | The time (in s) between keepalive probes. The default is 1 s. |
tcp.keepalive_count | Connection | Integer | RW | The number of keepalive probes sent before the connection is dropped. The default is 3. |
tcp.user_timeout | Connection | Integer | RW | The time (in s) before a connection is dropped due to unacknowledged data. The default is 3 s. |
tcp.segs_in
and tcp.segs_out
are only present when running XCM on Linux kernel 4.2 or later.The TLS transport uses the Transport Layer Security (TLS) protocol to provide a secure, private, two-way authenticated transport over TCP. A TLS connection is a byte stream, but the XCM TLS transport adds framing in the same manner as does the XCM TCP transport.
+The TLS transport supports IPv4 and IPv6. It disables the Nagle algorithm of TCP.
+The TLS transport honors any limitations set by the X.509 extended key usage extension, if present in the remote peer's certificate.
+The TLS transport uses only TLS 1.2 and, if the XCM library is built with OpenSSL 1.1.1 or later, TLS 1.3 as well.
+TLS 1.2 renegotiation is disabled, if the XCM library is built with OpenSSL 1.1.1c or later.
+The TLS transport disables both client and server-side TLS session caching, and thus does not allow for TLS session reuse across TCP connections.
+The TLS 1.2 cipher list is (in order of preference, using OpenSSL naming): ECDHE-ECDSA-AES128-GCM-SHA256, ECDHE-ECDSA-AES256-GCM-SHA384, ECDHE-ECDSA-CHACHA20-POLY1305, ECDHE-RSA-AES128-GCM-SHA256, ECDHE-RSA-AES256-GCM-SHA384, ECDHE-RSA-CHACHA20-POLY1305, DHE-RSA-AES128-GCM-SHA256, DHE-RSA-AES256-GCM-SHA384, and DHE-RSA-CHACHA20-POLY1305.
+The TLS 1.3 cipher suites used are: TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256 and TLS_AES_128_GCM_SHA256.
+The TLS cipher lists are neither build- nor run-time configurable.
+The TLS transport reads the leaf certificate and its private key from the file system, as well as a file containing all trusted CA certificates. Default paths are configured at build-time.
+TLS Socket Attributes may be used to override one or more of the default paths, on a per-socket basis. Paths set on server sockets are inherited by its connection sockets, but may in turn be overriden at the time of a xcm_accept_a() call, using the proper attributes.
+The default paths may also be overriden on a per-process basis by means of a UNIX environment variable. The current value of XCM_TLS_CERT
(at the time of xcm_connect() or xcm_accept()) determines the certificate directory used for that connection.
The TLS transport will, at the time of xcm_connect() or xcm_server(), look up the process' current network namespace, unless that file's path was given as a TLS Socket Attributes. If the namespace is given a name per the iproute2 convention, XCM will retrieve this name and use it in the certificate and key lookup.
+In case the certificate, key and trusted CA files are configured using TLS Socket Attributes, no network namespace lookup will be performed.
+In the certificate directory (either the compile-time default, or the directory specified with XCM_TLS_CERT
), the TLS transport expects the files to follow the following naming conventions (where <ns> is the namespace):
The private key is stored in:
The trusted CA certificates are stored in:
For the default namespace (or any other network namespace not named according to iproute2 standards), the certificate need to be stored in a file "cert.pem", the private key in "key.pem" and the trusted CA certificates in "tc.pem".
+In case the certificate, key or trusted CAs files are not in place (for a particular namespace), a xcm_server() call will return an error and set errno to EPROTO. The application may choose to retry at a later time.
+In case a certificate, private key, or trusted CAs file is modified, the new version of the file(s) will be used by new connections. Such a change does not affect already-established connections. The TLS transport works with differences between set of files, and thus the new generation of files need not nesserarily be newer (as in having a more recent file system mtime).
+The certificate, key and trusted CA certificates should be updated in an atomic manner, or XCM may end up using the certificate file from one generation of files and the key file from another, for example.
+One way of achieving an atomic update is to have the three files in a common directory. This certificate directory is then made a symbolic link to the directory where the actual files are located. Upon update, a new directory is created and populated, and the old symbolic link is replace an atomic manner (i.e. with rename(2)).
+By default, on sockets that represent the client side of a XCM TLS connection (e.g., returned from xcm_connect_a()), the XCM TLS transport will act as a TLS client. Similarly, the default behavior for sockets representing the XCM (and TCP) server side of a connection is to act as a TLS server.
+The default may be changed by setting the "tls.client" attribute, so that sockets that are XCM (and TCP) level clients, act as TLS servers, and vice versa. If the value is true, the socket will act as a TLS client, and if false, the socket is a TLS server.
+Connection sockets created by xcm_accept() or xcm_accept_a() inherit the "tls.client" attribute value from their parent server sockets.
+The TLS role must be specified at the time of socket creation, and thus cannot be changed on already-established connections.
+By default, both the client and server side authenticate the other peer, often referred to as mutual TLS (mTLS).
+TLS remote peer authentication may be disabled by setting the "tls.auth" socket attribute to false.
+Connection sockets created by xcm_accept() or xcm_accept_a() inherit the "tls.auth" attribute value from their parent server sockets.
+The "tls.auth" socket attribute may only be set at the time of socket creation (except for server sockets).
+The TLS transport supports verifying the remote peer's certificate subject name against an application-specified expected name, or a set of names. "Subject name" here is used as per RFC 6125 definition, and is either a Distingushed Name (DN) of the X.509 certificate's subject field, or a DNS type subject alternative name extension. XCM does not make any distinction between the two.
+Subject name verification may be enabled by setting the "tls.verify_peer_name" socket attribute to true. It is disabled by default.
+If enabled, XCM will verify the hostname in the address supplied in the xcm_connect_a() call. In case the attribute "tls.peer_names" is also supplied, it overrides this behavior. The value of this attribute is a ':'-separated set of subject names.
+If there is a non-zero overlap between these two sets, the verification is considered successful. The actual procedure is delegated to OpenSSL. Wildcard matching is disabled (X509_CHECK_FLAG_NO_WILDCARDS
) and the check includes the subject field (X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT
).
Subject name verification may be used both by a client (in its xcm_connect_a() call) or by a server (in xcm_server_a() or xcm_accept_a()). "tls.peer_names" must be specified in case "tls.verify_peer_name" is set to true on connection sockets created by accepting a TLS connection from a server socket (since there is no hostname to fall back to).
+Connection sockets created by xcm_accept() or xcm_accept_a() inherit the "tls.verify_name" and "tls.peer_names" attributes from their parent server sockets.
+After a connection is established, the "tls.peer_names" will be updated to reflect the remote peer's actual subject names, as opposed to those which were originally allowed.
+OpenSSL refers to this functionality as hostname validation, and that is also how it's usually used. However, the subject name passed in "tls.peer_names" need not be DNS domain name, but can be any kind of name or identifier. All names must follow DNS domain name syntax rules (including label and total length limitations). Also, while uppercase and lowercase letters are allowed in domain names, no significance is attached to the case.
+Attribute Name | Socket Type | Value Type | Mode | Description |
---|---|---|---|---|
tls.cert_file | All | String | RW | The leaf certificate file. For connection sockets, writable only at socket creation. |
tls.key_file | All | String | RW | The leaf certificate private key file. For connection sockets, writable only at socket creation. |
tls.tc_file | All | String | RW | The trusted CA certificates bundle. For connection sockets, writable only at socket creation. |
tls.client | All | Boolean | RW | Controls whether to act as a TLS-level client or a server. For connection sockets, writable only |
tls.auth | All | Boolean | RW | Controls whether or not to authenticate the remote peer. For connection sockets, writable only at socket creation. |
tls.verify_peer_name | All | Boolean | RW | Controls if subject name verification should be performed. For connection sockets, writable only at socket creation. |
tls.peer_names | All | String | RW | At socket creation, a list of acceptable peer subject names. After connection establishment, a list of actual peer subject names. For connection sockets, writable only at socket creation. |
tls.peer_subject_key_id | Connection | String | R | The X509v3 Subject Key Identifier of the remote peer, or a zero-length string in case the TLS connection is not established. |
In addition to the TLS-specific attributes, a TLS socket also has all the TCP Socket Attributes.
+The UTLS transport provides a hybrid transport, utilizing both the TLS and UX transports internally for actual connection establishment and message delivery.
+On the client side, at the time of xcm_connect(), the UTLS transport determines if the server socket can be reached by using the UX transport (i.e. if the server socket is located on the same OS instance, in the same network namespace). If not, UTLS will attempt to reach the server by means of the TLS transport.
+For a particular UTLS connection, either TLS or UX is used (never both). XCM connections to a particular UTLS server socket may be a mix of the two different types.
+For an UTLS server socket with the address utls:<ip>:<port>
, two underlying addresses will be allocated; tls:<ip>:<port>
and ux:<ip>:<port>
.
In case DNS is used: tls:<hostname>:<port>
and ux:<hostname>:<port>
.
UTLS sockets accept all the TLS Socket Attributes, as well as the Generic Attributes. In case a UTLS connection is being established as a UX connection socket, all TLS attributes are ignored.
+A wildcard should never be used when creating a UTLS server socket.
+If a DNS hostname is used in place of the IP address, both the client and server need employ DNS, and also agree upon which hostname to use (in case there are several pointing at the same IP address).
+Failure to adhere to the above two rules will prevent a client from finding a local server. Such a client will instead establish a TLS connection to the server.
+The SCTP transport uses the Stream Control Transmission Protocol (SCTP). SCTP provides a reliable, message-oriented service. In-order delivery is optional, but to adhere to XCM semantics (and for other reasons) XCM leaves SCTP in-order delivery enabled.
+The SCTP transport utilizes the native Linux kernel's implementation of SCTP, via the BSD Socket API. The operating mode is such that there is a 1:1-mapping between an association and a socket (fd).
+The SCTP transport supports IPv4 and IPv6.
+To minimize latency, the SCTP transport disables the Nagle algorithm.
+The BTLS transport uses the Transport Layer Security (TLS) protocol to provide a secure, private, two-way authenticated byte stream service over TCP.
+Unlike the TLS Transport, BTLS doesn't have a framing header nor anything else on the wire protocol level that is specific to XCM. It's a "raw" TLS connection.
+Other than providing a byte stream, it's identical to the TLS Transport.
+Namespaces is a Linux kernel facility concept for creating multiple, independent namespaces for kernel resources of a certain kind.
+Linux Network Namespaces will affect all transports, except the UXF Transport.
+XCM has no explicit namespace support. Rather, the application is expected to use the Linux kernel facilities for this functionality (i.e. switch to the right namespace before xcm_server() och xcm_connect()).
+In case the system follows the iproute2 conventions in regards to network namespace naming, the TLS and UTLS transports support per-network namespace TLS certificates and private keys.
+XCM, in its current form, does not support binding to a local socket before doing connect() - something that is possible with BSD Sockets, but very rarely makes sense.
+XCM also doesn't have a sendmmsg() or recvmmsg() equivalent. Those could easily be added, and would provide some major performance improvements for applications that are sending or receiving multiple messages on the same connection on the same time. *mmsg() equivalents have been left out because there are strong doubts there are such applications.
+
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
#include <xcm_addr.h>
+Data Fields | ||
enum xcm_addr_type | type | |
union { | ||
+ struct xcm_addr_ip ip | ||
+ char name [254] | ||
}; | ||
Hostname or IPv4/IPv6 address data type.
+enum xcm_addr_type xcm_addr_host::type | +
Type tag
+ +union { ... } xcm_addr_host | +
Union containing the actual hostname, IPv4 or IPv6 address bytes
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
#include <xcm_addr.h>
+Data Fields | ||
sa_family_t | family | |
union { | ||
in_addr_t ip4 | ||
uint8_t ip6 [16] | ||
} | addr | |
IPv4 or IPv6 address data type.
+sa_family_t xcm_addr_ip::family | +
Type tag; AF_INET or AF_INET6
+ +in_addr_t xcm_addr_ip::ip4 | +
Contains the IPv4 address in network byte order (in case family is set to AF_INET).
+ +uint8_t xcm_addr_ip::ip6[16] | +
Contains the IPv6 address (in case family is set to AF_INET6).
+ +union { ... } xcm_addr_ip::addr | +
Union containing the actual IPv4 or a IPv6 address bytes
+ +
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
Library Version | |
API Version |
+ Extensible Connection-oriented Messaging (XCM)
+
+ |
+
This file contains the core Extensible Connection-oriented Messaging (XCM) API. +More...
+#include <errno.h>
#include <stdbool.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 *conn_socket, const void *buf, size_t len) |
int | xcm_receive (struct xcm_socket *conn_socket, void *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) |
This file contains the core Extensible Connection-oriented Messaging (XCM) API.
+#define XCM_NONBLOCK (1<<0) | +
Flag used in xcm_connect()
+ +#define XCM_SO_RECEIVABLE (1<<0) | +
Flag bit denoting a socket where the application likely can receive data.
+ +#define XCM_SO_SENDABLE (1<<1) | +
Flag bit denoting a socket where the application likely can send data.
+ +#define XCM_SO_ACCEPTABLE (1<<2) | +
Flag bit denoting a socket with a pending incoming connection.
+ +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.
+