Skip to main content

Module socket

Module socket 

Source
Expand description

Socket construction with pre-bind options: the one place in the workspace that opens a socket, sets the address-reuse/broadcast options a protocol needs, and only then binds or connects it.

§Why this exists, and why here

socket2 — the obvious way to set an option on an unbound socket — does not build for armv7-rtems-eabihf or the *-wrs-vxworks* triples (20 compile errors on the former: ip_mreqn, IovLen, and friends are Linux shapes the target’s libc has no equivalent for). So every reactor-free driver that needed a pre-bind option grew its own raw-libc copy of the same twenty lines. At the time this module was written there were two, byte-for-byte alike in everything but their error strings:

  • epics-ca-rs::server::blocking::bind_udp_search_socket
  • epics-pva-rs::server_native::blocking’s UDP search responder

and asyn-rs’s IP drivers were about to be the third. epics-ca-rs does not depend on epics-pva-rs and must not, and asyn-rs depends on neither, so there is exactly one crate all three can reach: this one. A primitive promoted into any protocol crate is one the other two structurally cannot call — the same reasoning that put runtime::blocking_io here, for the same reason.

The second reason is coverage. epics-libcom-rs is the first entry in CRATES in both scripts/rtems-check.sh and scripts/vxworks-check.sh, so target-only unsafe placed here is compiled for both triples by the gates that already run. The same code in a crate outside those lists is compiled by nothing.

§Why the option must precede the bind

SO_REUSEPORT is what lets several IOCs share one UDP port and have the kernel fan each datagram out to all of them. The kernel only honours it on an unbound socket, so UdpSocket::bind() followed by a setsockopt is not a slower version of this — it is a version that silently does nothing. That ordering constraint is the whole reason std’s constructors are not enough and a raw socket()/setsockopt()/bind() sequence is.

§The C authority for each branch

Option selection follows EPICS base libcom/src/osi/os/default/osdSockAddrReuse.cpp: the datagram-fanout helper sets SO_REUSEPORT (where defined) and then SO_REUSEADDR; the time-wait helper sets SO_REUSEADDR alone. Both SO_REUSEPORT constants exist on the two embedded targets (0x0200 on newlib/RTEMS and on VxWorks), so neither takes the #ifndef SO_REUSEPORT fallback the C comment describes for older systems.

Connect behaviour follows asyn drvAsynIPPort.c, whose three branches this module reproduces exactly:

targetconnecttimeout honouredC authority
hostednon-blocking, then poll(POLLOUT)yes:511, :523, :544 under USE_POLL
VxWorksnon-blocking, then select() via FAKE_POLLyes:76, :139-164, :178
RTEMSblockingno:71-72__rtems__ takes USE_SOCKTIMEOUT, and both setNonBlock and the poll block sit inside #ifdef USE_POLL

The RTEMS row is not an omission. C genuinely has no connect timeout there; it bounds the transfer instead, with SO_RCVTIMEO/SO_SNDTIMEO (:652-664, :778-790). Honouring the deadline there anyway would be a deviation invented by the port, so tcp_connect documents the difference rather than papering over it.

Structs§

SocketOptions
Options applied to a fresh socket before it is bound or connected.

Functions§

tcp_connect
Open a TCP socket, apply opts, optionally bind it to local, and connect it to remote within timeout.
tcp_listener
Open a TCP socket, apply opts, bind it to local, and start listening.
udp_socket
Open a UDP socket, apply opts, and bind it to local.