CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
Sockets

Data Structures

struct  NetSocket
 

Macros

#define netsocketSendEx(self, data, len, dest, info, flags)   NetSocket_sendEx(NetSocket(self), data, len, dest, info, flags)
 
#define netsocketSetRecvInfo(self, enable)   NetSocket_setRecvInfo(NetSocket(self), enable)
 
#define netsocketSetDontFragment(self, enable)   NetSocket_setDontFragment(NetSocket(self), enable)
 
#define netsocketSetHandlers(self, handlers, ctx)   NetSocket_setHandlers(NetSocket(self), handlers, ctx)
 
#define netsocketSetHandlersObj(self, handlers, ctx)   NetSocket_setHandlersObj(NetSocket(self), handlers, ObjInst(ctx))
 
#define netsocketAddFilter(self, filter)   NetSocket_addFilter(NetSocket(self), NetFilter(filter))
 
#define netsocketRemoveFilters(self)   NetSocket_removeFilters(NetSocket(self))
 
#define netsocketRecv(self, buf, bufsz, src, flags)   (self)->_->recv(NetSocket(self), buf, bufsz, src, flags)
 
#define netsocketRecvMsgs(self, cb, ctx)   (self)->_->recvMsgs(NetSocket(self), cb, ctx)
 
#define netsocketSend(self, data, len, dest, flags)   (self)->_->send(NetSocket(self), data, len, dest, flags)
 
#define netsocketConnect(self, host, port)   (self)->_->connect(NetSocket(self), host, port)
 
#define netsocketClose(self)   (self)->_->close(NetSocket(self))
 

Typedefs

typedef struct NetSocket NetSocket
 
typedef bool(* socketRecvCB) (NetSocket *sock, NetMessage *msg, void *ctx)
 

Detailed Description

Class that encapsulates a network socket.

Macro Definition Documentation

◆ netsocketAddFilter

#define netsocketAddFilter (   self,
  filter 
)    NetSocket_addFilter(NetSocket(self), NetFilter(filter))

bool netsocketAddFilter(NetSocket* self, NetFilter* filter);

Attach a filter to the socket, applying it to every flow

The filter is appended to the socket's list, so the first one attached is the stage closest to the application and the last is the one nearest the wire. A per-flow NetFlowFilter is created immediately for every flow the socket already has – the single flow of a stream socket, or every peer flow of a datagram socket – and for every flow it opens afterwards.

The socket acquires its own reference, so the caller keeps theirs and should release it when done; the same filter may be attached to any number of sockets, which is how one filter holding a certificate and key serves every accepted connection on a server.

A filter attached to a listening socket is inherited by every connection it accepts, and is installed on the accepted socket before that socket becomes reachable – so no byte can arrive on a new connection ahead of its chain. That is the way to secure a server: attach once to the listener, not per connection from the NET_Accepted handler, which races the worker already servicing the new socket.

Install filters before data starts moving – right after creating the socket, and before connect or listen.

Parameters
filterFilter to attach
Returns
true if the filter was attached, false if it declined this socket type (see netfilterCanFilter) or the socket is closed

Definition at line 330 of file socket.h.

◆ netsocketClose

#define netsocketClose (   self)    (self)->_->close(NetSocket(self))

bool netsocketClose(NetSocket* self);

Close socket

Will also remove from a NetQueue if it is registered to one. The socket cannot be reused once closed.

A connection is shut down at once, but its OS handle – and the local address it is bound to – is only released when the last reference to the socket is. A listening socket is the exception and releases its handle immediately, so its address can be listened on again.

Returns
true if the socket was successfully disconnected, false otherwise.

Definition at line 581 of file socket.h.

◆ netsocketConnect

#define netsocketConnect (   self,
  host,
  port 
)    (self)->_->connect(NetSocket(self), host, port)

bool netsocketConnect(NetSocket* self, strref host, uint16 port);

Open an outbound connection to a host and port

Stream sockets only. This call is asynchronous: it returns immediately after starting the process, and the result arrives later as a NET_Connection event on the socket's flow. The host is resolved on a dedicated resolver thread, never on a net I/O thread, and the socket passes through NS_Resolving and NS_Connecting on the way. Each resolved address is tried in turn with a fresh OS handle of the right family, falling through on failure or timeout, until one connects or the list is exhausted.

The socket must already be registered with a queue (that is where the resolver, backend, and flow live). A literal address is accepted directly without a DNS lookup.

Parameters
hostHostname or literal address to connect to (NULL/empty means loopback)
portPort number, host byte order
Returns
true if the connect was started, false if it could not be (wrong socket type, no queue, or already connecting/connected)

Definition at line 562 of file socket.h.

◆ netsocketRecv

#define netsocketRecv (   self,
  buf,
  bufsz,
  src,
  flags 
)    (self)->_->recv(NetSocket(self), buf, bufsz, src, flags)

size_t netsocketRecv(NetSocket* self, uint8* buf, size_t bufsz, NetAddr* src, flags_t flags);

Read buffered stream data out of the socket receive buffer

This does not actively try to receive; it only drains bytes already buffered in the socket's receive ring by the queue's ingest thread (or by tick() in polled mode). With a filter attached it drains decoded application bytes from the end of the flow's filter chain instead – the raw wire bytes in the receive ring were already consumed by the decode pass that ran before NET_DataReceived was delivered.

Note
Stream sockets only. A datagram is delivered whole on the NET_DataReceived event as event->recv.msg instead of being buffered here. Calling recv() on a datagram socket returns 0.
Parameters
bufBuffer to store received data
bufszSize of the buffer
srcUnused; retained for signature compatibility. Datagram source addresses arrive on the event, not here.
flagsOptional flags to control receive behavior
Returns
Amount of data actually received (0 on a datagram socket, or when the ring is empty)

Definition at line 488 of file socket.h.

◆ netsocketRecvMsgs

#define netsocketRecvMsgs (   self,
  cb,
  ctx 
)    (self)->_->recvMsgs(NetSocket(self), cb, ctx)

bool netsocketRecvMsgs(NetSocket* self, socketRecvCB cb, void* ctx);

Drain buffered stream data as a series of zero-copy messages

Invokes the callback for each chunk of data available in the receive ring, repeatedly, until it returns false or the ring is exhausted. More efficient than recv() when draining a lot of data, since it hands out the ring's own segments instead of copying into a caller-supplied buffer.

Note
Stream sockets only, for the same reason as recv(): datagrams arrive on the event with their buffer attached, so there's nothing here to drain. Returns false on a datagram socket.

The callback receives ownership of the buffer in the NetMessage. It may keep the buffer by setting msg->buf to NULL, otherwise the buffer is automatically destroyed after the callback returns.

Parameters
cbCallback invoked for each message (return false to stop)
ctxUser-defined context pointer passed to callback
Returns
true if at least one message was processed, false if the ring was empty or the socket is a datagram socket

Definition at line 510 of file socket.h.

◆ netsocketRemoveFilters

#define netsocketRemoveFilters (   self)    NetSocket_removeFilters(NetSocket(self))

void netsocketRemoveFilters(NetSocket* self);

Detach and release every filter on the socket

Drops the socket's filter list and tears down the corresponding chain on every flow it owns, discarding anything those stages still had buffered. After this the socket's send/recv paths are back on the unfiltered fast path.

Definition at line 340 of file socket.h.

◆ netsocketSend

#define netsocketSend (   self,
  data,
  len,
  dest,
  flags 
)    (self)->_->send(NetSocket(self), data, len, dest, flags)

bool netsocketSend(NetSocket* self, const uint8* data, size_t len, const NetAddr* dest, flags_t flags);

Send data on the socket

Data the OS won't accept immediately is queued and flushed later when the socket becomes writable. The same logic is shared by both socket types: a stream socket copies the data into its outbound chain and sends it with scatter/gather; a datagram socket queues whole messages, each with its own destination.

Note
Backpressure: once more than sendHigh bytes are already queued, the call returns false and queues nothing; back off until NET_SendReady fires, which happens once the backlog drains below sendLow. NSO_Immediate never queues – it sends what the OS takes right now and returns true only if the whole payload went out.

For connected (stream) sockets, dest is ignored. For connectionless (datagram) sockets, dest must be a valid address.

Note
Filters: with a filter attached the payload is run through the destination flow's filter chain on its way out, so what reaches the wire is whatever the chain produced – which may be nothing at all if a stage is still negotiating and chose to buffer the payload. A datagram sent to a peer with no flow yet opens one (firing NET_FlowOpen) so the chain exists to encode it; if the queue is at its flow cap the send is refused. Either way the call returns true when the payload was accepted, not when bytes reached the wire. NSO_Immediate is ignored on a filtered socket – the filter owns the framing, and a payload jumping the chain would land in the middle of whatever the chain is producing.
Parameters
dataPointer to data to send (copied; need not outlive the call)
lenLength of data in bytes
destDestination address (required for connectionless, ignored for connected)
flagsOptional flags to control send behavior
Returns
true if the data was sent or queued, false if it was refused (over the high watermark, not connected, or a fatal socket error)

Definition at line 543 of file socket.h.

◆ netsocketSendEx

#define netsocketSendEx (   self,
  data,
  len,
  dest,
  info,
  flags 
)    NetSocket_sendEx(NetSocket(self), data, len, dest, info, flags)

bool netsocketSendEx(NetSocket* self, const uint8* data, size_t len, const NetAddr* dest, const NetPktInfo* info, flags_t flags);

Send a datagram, asking the IP layer for a specific local address and ECN mark

Everything send() does, plus the two things a plain send cannot express: which of this machine's addresses the datagram leaves from, and the ECN codepoint it carries. Both are requests – a platform that cannot honour one sends the datagram without it rather than failing, so a caller that needs to know whether the mark survived has to ask the peer.

Datagram sockets only, and unfiltered ones: a filter chain owns what reaches the wire, so there is nothing here for one to attach per-datagram information to.

Parameters
dataPointer to data to send (copied; need not outlive the call)
lenLength of data in bytes
destDestination address
infoLocal address and ECN mark to ask for, or NULL for neither
flagsOptional flags to control send behavior
Returns
true if the data was sent or queued, false if it was refused

Definition at line 252 of file socket.h.

◆ netsocketSetDontFragment

#define netsocketSetDontFragment (   self,
  enable 
)    NetSocket_setDontFragment(NetSocket(self), enable)

bool netsocketSetDontFragment(NetSocket* self, bool enable);

Set the don't-fragment bit on datagrams leaving this socket

A datagram larger than the path allows is then dropped instead of being fragmented, which is what turns an oversized send into a measurement rather than a slow success. Call it after bind(), for the same reason as setRecvInfo().

Parameters
enabletrue to set the bit, false to leave fragmentation to the OS
Returns
true if the platform could set it

Definition at line 279 of file socket.h.

◆ netsocketSetHandlers

#define netsocketSetHandlers (   self,
  handlers,
  ctx 
)    NetSocket_setHandlers(NetSocket(self), handlers, ctx)

void netsocketSetHandlers(NetSocket* self, const NetHandlers* handlers, void* ctx);

Register per-socket handler overrides

Fields left NULL fall through to the queue-wide set. The handler struct is not copied – it must outlive the socket, which is why it is usually static const.

Parameters
handlersHandler set, or NULL to clear
ctxContext passed to these handlers on NetEvent.ctx

Definition at line 291 of file socket.h.

◆ netsocketSetHandlersObj

#define netsocketSetHandlersObj (   self,
  handlers,
  ctx 
)    NetSocket_setHandlersObj(NetSocket(self), handlers, ObjInst(ctx))

void netsocketSetHandlersObj(NetSocket* self, const NetHandlers* handlers, ObjInst* ctx);

Register per-socket handler overrides, with an object as the context

Same as setHandlers(), except ctx is held weakly rather than borrowed.

Parameters
handlersHandler set, or NULL to clear
ctxObject passed to these handlers on NetEvent.ctx, held weakly; NULL to clear

Definition at line 302 of file socket.h.

◆ netsocketSetRecvInfo

#define netsocketSetRecvInfo (   self,
  enable 
)    NetSocket_setRecvInfo(NetSocket(self), enable)

bool netsocketSetRecvInfo(NetSocket* self, bool enable);

Ask the OS to report the local address and ECN mark of each received datagram

While enabled, every NetMessage delivered from this socket carries them on NetMessage::info. Call it after bind(): the options are per address family, and a socket has no family until it is bound.

Parameters
enabletrue to start reporting, false to stop
Returns
true if the platform can report them, false if it cannot – in which case NetMessage::info stays empty and a caller that needed ECN should not mark its sends

Definition at line 266 of file socket.h.

Typedef Documentation

◆ NetSocket

typedef struct NetSocket NetSocket

Network Socket This is a base class; the actual socket implemention will be a derived class provided by the OS abstraction layer.

Definition at line 24 of file socket.h.

◆ socketRecvCB

typedef bool(* socketRecvCB) (NetSocket *sock, NetMessage *msg, void *ctx)

Callback for receiving messages from a socket.

The callback receives ownership of the buffer in the NetMessage. To keep the buffer, set msg->buf to NULL before returning; otherwise it will be automatically destroyed.

Parameters
sockSocket the message was received from
msgMessage containing data buffer and source address (for datagrams)
ctxUser-defined context pointer
Returns
true to continue receiving more messages, false to stop

Definition at line 46 of file socket.h.