silk.net.datagram_native.
Nonblocking UDP sockets on the native system: send and receive whole datagrams.
When to use#
Use a NativeUdpSocket to send datagrams, such as DNS queries, from a native program. Every
socket is nonblocking: a send or a receive that cannot complete now returns WouldBlock and does
not wait. Call NativeUdpSocket.waitReadable to wait, or register
NativeUdpSocket.rawDescriptor with your own event loop.
Details#
A socket is IPv4 or IPv6, and is closed when it is dropped. A socket made for IPv6 does not
accept IPv4 traffic. After NativeUdpSocket.connect, the system drops datagrams from other
peers, and reports ConnectionRefused when the peer reports that its port is closed.
waitAny waits for any of several sockets.
The module supports Linux with GNU libc, macOS, and Windows on x86_64.
Examples#
Send a datagram to yourself#
import silk.core.effect { Effect }
import silk.net.address { Endpoint, IpAddress, Ipv4Address, Port }
import silk.net.datagram_native { DatagramError, Family, NativeUdpSocket, Received, Sent }
import silk.system.monotonic_clock { MonotonicClock }
import silk.system.monotonic_clock_native { OsMonotonicClock }
effect fn program() -> i32 ! DatagramError ? &mut MonotonicClock {
let loopback = IpAddress.V4 { value: Ipv4Address.fromOctets([127, 0, 0, 1]) }
let mut socket = run NativeUdpSocket.open(Family.V4)
run NativeUdpSocket.bind(&mut socket, Endpoint.make(loopback, Port.fromU16(0)))
let local = run NativeUdpSocket.localEndpoint(&socket)
match run NativeUdpSocket.sendTo(&mut socket, b"ping", local) {
Sent.Count { count } => {
if count != 4 { return 1 }
}
Sent.WouldBlock => { return 1 }
}
let now = run MonotonicClock.now()
if !(run NativeUdpSocket.waitReadable(&socket, MonotonicClock.deadlineAfter(&now, 1000000000))) {
return 1
}
let mut buffer: [u8; 16] = [0; 16]
return match run NativeUdpSocket.receive(&mut socket, &mut buffer) {
Received.Datagram { count, from } => {
if count != 4 || buffer[0] != 112 || !Endpoint.equals(&from, &local) { return 1 }
return 0
}
Received.WouldBlock => 1
}
}
effect fn failed<E>(error: E) -> i32 {
drop error
return 1
}
pub fn main() -> i32 {
let mut clock = OsMonotonicClock.make()
return run Effect.catchAll(program(), failed) |> Effect.provideMut<MonotonicClock>(&mut clock)
}Import as NativeUdpSocket with import silk.net.datagram_native { NativeUdpSocket }.
Public declarations: 9.
RawSocket#
pub type RawSocket = i32The type of a raw socket handle: a file descriptor.
Family#
pub enum FamilyThe address family of a socket.
V4#
V4IPv4.
V6#
V6IPv6.
MulticastInterface#
pub union MulticastInterfaceThe network interface for multicast traffic, in NativeUdpSocket.setMulticastInterface and
the group calls such as NativeUdpSocket.joinGroup.
Default#
DefaultThe interface that the system chooses.
V4#
V4The IPv4 interface with this local address. Use it with IPv4 groups.
Field address#
pub address: Ipv4AddressThe local address of the interface.
V6#
V6The IPv6 interface with this index, as if_nametoindex returns it. Use it with IPv6 groups.
Field index#
pub index: u32The index of the interface.
Implementation Copy for MulticastInterface#
impl Copy for MulticastInterfaceDatagramOperation#
pub enum DatagramOperationThe system call that failed.
Socket#
SocketMaking the socket.
Configure#
ConfigureMaking the socket nonblocking and not inherited by child processes.
Bind#
BindBinding a local address.
Connect#
ConnectConnecting to a peer.
Send#
SendSending a datagram.
Receive#
ReceiveReceiving a datagram.
LocalAddress#
LocalAddressReading the local address.
PeerAddress#
PeerAddressReading the address of the connected peer.
Disconnect#
DisconnectRemoving the connected peer.
Option#
OptionReading or setting a socket option, such as the TTL or a multicast group.
Wait#
WaitWaiting for a datagram.
Implementation Debug for DatagramOperation#
impl Debug for DatagramOperationOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
! WriterError
? &mut WriterWrites the name of the variant, such as Send.
DatagramError#
pub union DatagramErrorThe error from a UDP socket operation.
ConnectionRefused#
ConnectionRefusedThe peer reported that its port is closed. On Linux and macOS only a connected socket gets this; on Windows any socket can.
Field operation#
pub operation: DatagramOperationThe operation that saw the report.
AddressInUse#
AddressInUseThe local address is in use.
PermissionDenied#
PermissionDeniedThe system does not allow the operation, for example a bind to a privileged port.
NetworkUnreachable#
NetworkUnreachableThe network or host of the peer cannot be reached.
MessageTooLarge#
MessageTooLargeThe datagram is too long to send, or, on Windows, too long for the receive buffer.
FamilyUnsupported#
FamilyUnsupportedThe address family is not supported or not enabled.
InvalidNativeAddress#
InvalidNativeAddressThe system returned an address that is not IPv4 or IPv6.
NativeFailure#
NativeFailureAnother system error.
Field operation#
pub operation: DatagramOperationThe operation that failed.
Field code#
pub code: i32The errno value, or the Winsock error code on Windows.
Implementation Debug for DatagramError#
impl Debug for DatagramErrorOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
! WriterError
? &mut WriterWrites the name of the variant and its fields, such as NativeFailure { ... }.
Sent#
pub union SentThe result of a send.
Count#
CountThe system took the whole datagram.
Field count#
pub count: usizeThe number of bytes sent, which is the length of the datagram.
WouldBlock#
WouldBlockThe send buffer is full. Try again later.
Received#
pub union ReceivedThe result of a receive.
Datagram#
DatagramOne datagram is at the start of the buffer.
Field count#
pub count: usizeThe number of bytes of the datagram in the buffer. A longer datagram is cut to the buffer length on Linux and macOS.
Field from#
pub from: EndpointThe address that sent the datagram.
WouldBlock#
WouldBlockNo datagram is waiting. Try again later.
NativeUdpSocket#
pub struct NativeUdpSocketA nonblocking UDP socket. It is closed when it is dropped.
Implementation Drop for NativeUdpSocket#
impl Drop for NativeUdpSocketOperation drop#
fn drop(self: &mut NativeUdpSocket) -> ()Implementation NativeUdpSocket#
impl NativeUdpSocketAssociated function open#
pub effect fn open(family: Family) -> NativeUdpSocket
! DatagramErrorMakes an unbound UDP socket for family. It is nonblocking, and child processes do not get it.
Errors#
FamilyUnsupportedif the system has no support forfamily.Another
DatagramErrorif the system cannot make the socket.
Associated function adopt#
pub unsafe effect fn adopt(fd: RawSocket, family: Family) -> NativeUdpSocket
! DatagramErrorTakes an open UDP socket of family, such as one that another process sent, and makes it
nonblocking and kept from child processes. The returned socket owns fd and closes it when
it is dropped.
When to use#
Use it for a socket descriptor that this program did not make, as Node's dgram does for a
socket shared by a cluster primary. Use NativeUdpSocket.open for a new socket.
Safety#
fd must be an open UDP socket of family that nothing else closes.
Errors#
A
DatagramErrorwith operationConfigureif the system cannot set the socket flags. The socket is closed then.
Method family#
pub fn family(self: &Self) -> FamilyReturns the family of the socket.
Method rawDescriptor#
pub fn rawDescriptor(self: &Self) -> RawSocketReturns the raw handle of the socket, for example to register it with an event loop. The socket still owns it: do not close it.
Method bind#
pub effect fn bind(self: &mut Self, endpoint: Endpoint) -> ()
! DatagramErrorBinds the socket to the local address endpoint. Port 0 lets the system choose a free port.
Errors#
AddressInUse,PermissionDenied, or anotherDatagramErrorfrom the system.FamilyUnsupportedifendpointis not of the family of the socket.
Method connect#
pub effect fn connect(self: &mut Self, endpoint: Endpoint) -> ()
! DatagramErrorConnects the socket to endpoint: NativeUdpSocket.send then goes there, and the system
drops datagrams from other addresses.
Errors#
NetworkUnreachable, or anotherDatagramErrorfrom the system.FamilyUnsupportedifendpointis not of the family of the socket.
Method localEndpoint#
pub effect fn localEndpoint(self: &Self) -> Endpoint
! DatagramErrorReturns the local address of the socket, such as the port that the system chose.
Errors#
A
DatagramErrorfrom the system.
Method peerEndpoint#
pub effect fn peerEndpoint(self: &Self) -> Endpoint
! DatagramErrorReturns the address of the peer that NativeUdpSocket.connect set.
Errors#
A
DatagramErrorfrom the system, such asNativeFailurewith operationPeerAddressandENOTCONNwhen the socket is not connected.
Method disconnect#
pub effect fn disconnect(self: &mut Self) -> ()
! DatagramErrorRemoves the peer that NativeUdpSocket.connect set, so that the socket can send to and
receive from any address again. The socket stays bound to its local address.
Errors#
A
DatagramErrorfrom the system.
Method setIpv6Only#
pub effect fn setIpv6Only(self: &mut Self, enabled: bool) -> ()
! DatagramErrorSets whether an IPv6 socket takes only IPv6 traffic (IPV6_V6ONLY). NativeUdpSocket.open
turns it on. Turn it off before NativeUdpSocket.bind to take IPv4 traffic too, as
IPv4-mapped IPv6 addresses.
Errors#
FamilyUnsupportedfor an IPv4 socket.A
DatagramErrorfrom the system.
Method setReuseAddress#
pub effect fn setReuseAddress(self: &mut Self, enabled: bool) -> ()
! DatagramErrorSets whether other sockets can bind the same address and port, as several receivers of one
multicast group do. Call it before NativeUdpSocket.bind.
Details#
It sets SO_REUSEADDR. On macOS it also sets SO_REUSEPORT, which macOS needs to share a
port.
Errors#
A
DatagramErrorfrom the system.
Method setBroadcast#
pub effect fn setBroadcast(self: &mut Self, enabled: bool) -> ()
! DatagramErrorSets whether the socket can send to broadcast addresses (SO_BROADCAST).
Errors#
A
DatagramErrorfrom the system.
Method setTtl#
pub effect fn setTtl(self: &mut Self, hops: u8) -> ()
! DatagramErrorSets the hop limit of unicast datagrams: IP_TTL for an IPv4 socket and
IPV6_UNICAST_HOPS for an IPv6 socket.
Errors#
A
DatagramErrorfrom the system, such asNativeFailurewithEINVALfor 0 on some systems.
Method setMulticastTtl#
pub effect fn setMulticastTtl(self: &mut Self, hops: u8) -> ()
! DatagramErrorSets the hop limit of multicast datagrams: IP_MULTICAST_TTL for an IPv4 socket and
IPV6_MULTICAST_HOPS for an IPv6 socket. 0 keeps them on this host.
Errors#
A
DatagramErrorfrom the system.
Method setMulticastLoopback#
pub effect fn setMulticastLoopback(self: &mut Self, enabled: bool) -> ()
! DatagramErrorSets whether this host gets the multicast datagrams that the socket sends:
IP_MULTICAST_LOOP or IPV6_MULTICAST_LOOP.
Errors#
A
DatagramErrorfrom the system.
Method setMulticastInterface#
pub effect fn setMulticastInterface(self: &mut Self, via: MulticastInterface) -> ()
! DatagramErrorSets the interface that sends the multicast datagrams of the socket: IP_MULTICAST_IF or
IPV6_MULTICAST_IF. Default lets the system choose again.
Errors#
FamilyUnsupportedifviaisV4for an IPv6 socket, orV6for an IPv4 socket.A
DatagramErrorfrom the system, such asNativeFailurewithEADDRNOTAVAILwhen no interface has the address.
Method joinGroup#
pub effect fn joinGroup(self: &mut Self, group: IpAddress, via: MulticastInterface) -> ()
! DatagramErrorJoins the multicast group group on via, so that the socket gets its datagrams.
Details#
The family of group chooses the option: IP_ADD_MEMBERSHIP for IPv4 and IPV6_JOIN_GROUP
for IPv6. Bind the socket to the port of the group first.
Errors#
FamilyUnsupportedifviais of the other family thangroup.A
DatagramErrorfrom the system, such asNativeFailurewithEINVALwhengroupis not a multicast address, orEADDRINUSEwhen the socket is already a member.
Method leaveGroup#
pub effect fn leaveGroup(self: &mut Self, group: IpAddress, via: MulticastInterface) -> ()
! DatagramErrorLeaves the multicast group group on via, which NativeUdpSocket.joinGroup joined.
Errors#
FamilyUnsupportedifviais of the other family thangroup.A
DatagramErrorfrom the system, such asNativeFailurewithEADDRNOTAVAILwhen the socket is not a member.
Method joinSourceGroup#
pub effect fn joinSourceGroup(
self: &mut Self,
group: IpAddress,
source: IpAddress,
via: MulticastInterface,
) -> ()
! DatagramErrorJoins the multicast group group on via for datagrams from source only
(source-specific multicast).
Details#
IPv4 uses IP_ADD_SOURCE_MEMBERSHIP. IPv6 uses MCAST_JOIN_SOURCE_GROUP.
Errors#
FamilyUnsupportedifgroup,source, andviaare not all of one family.A
DatagramErrorfrom the system.
Method leaveSourceGroup#
pub effect fn leaveSourceGroup(
self: &mut Self,
group: IpAddress,
source: IpAddress,
via: MulticastInterface,
) -> ()
! DatagramErrorLeaves the source-specific group that NativeUdpSocket.joinSourceGroup joined.
Errors#
FamilyUnsupportedifgroup,source, andviaare not all of one family.A
DatagramErrorfrom the system.
Method receiveBufferSize#
pub effect fn receiveBufferSize(self: &Self) -> usize
! DatagramErrorReturns the size of the receive buffer of the socket in bytes (SO_RCVBUF).
Details#
Linux reports twice the size that NativeUdpSocket.setReceiveBufferSize set, because it
counts its bookkeeping.
Errors#
A
DatagramErrorfrom the system.
Method setReceiveBufferSize#
pub effect fn setReceiveBufferSize(self: &mut Self, size: usize) -> ()
! DatagramErrorAsks the system for a receive buffer of size bytes (SO_RCVBUF). The system can round or
cap it.
Errors#
NativeFailurewith operationOptionandEINVALifsizedoes not fit in anint.Another
DatagramErrorfrom the system.
Method sendBufferSize#
pub effect fn sendBufferSize(self: &Self) -> usize
! DatagramErrorReturns the size of the send buffer of the socket in bytes (SO_SNDBUF).
Details#
Linux reports twice the size that NativeUdpSocket.setSendBufferSize set, because it
counts its bookkeeping.
Errors#
A
DatagramErrorfrom the system.
Method setSendBufferSize#
pub effect fn setSendBufferSize(self: &mut Self, size: usize) -> ()
! DatagramErrorAsks the system for a send buffer of size bytes (SO_SNDBUF). The system can round or cap
it.
Errors#
NativeFailurewith operationOptionandEINVALifsizedoes not fit in anint.Another
DatagramErrorfrom the system.
Method send#
pub effect fn send(self: &mut Self, datagram: &[u8]) -> Sent
! DatagramErrorSends datagram to the connected peer.
Errors#
ConnectionRefusedif the peer reported a closed port for an earlier datagram.MessageTooLarge, or anotherDatagramErrorfrom the system.
Method sendTo#
pub effect fn sendTo(self: &mut Self, datagram: &[u8], endpoint: Endpoint) -> Sent
! DatagramErrorSends datagram to endpoint.
Errors#
FamilyUnsupportedifendpointis not of the family of the socket.MessageTooLarge,NetworkUnreachable, or anotherDatagramErrorfrom the system.
Method receive#
pub effect fn receive(self: &mut Self, buffer: &mut [u8]) -> Received
! DatagramErrorReceives one datagram into buffer, if one is waiting.
Details#
A datagram longer than buffer is cut to its length on Linux and macOS. Use a buffer of 65535
bytes to get every datagram whole.
Errors#
ConnectionRefusedif the socket is connected and the peer reported a closed port.MessageTooLargeon Windows, for a datagram longer thanbuffer.Another
DatagramErrorfrom the system.
Method waitReadable#
pub effect fn waitReadable(self: &Self, deadline: Instant) -> bool
! DatagramError
? &mut MonotonicClockWaits until a datagram or an error is waiting on the socket, or until deadline on the
MonotonicClock. Returns false if the deadline passed first.
When to use#
Use it in a program without an event loop. It blocks the thread.
Errors#
A
DatagramErrorfrom the system.
waitAny#
pub effect fn waitAny(sockets: &[NativeUdpSocket], deadline: Instant) -> bool
! DatagramError | OutOfMemoryError
? &mut MonotonicClock | &mut AllocatorWaits until a datagram or an error is waiting on any of sockets, or until deadline on the
MonotonicClock. Returns false if the deadline passed first.
When to use#
Use it in a program without an event loop, then call NativeUdpSocket.receive on each socket:
a socket that has nothing returns Received.WouldBlock. It blocks the thread.
Errors#
A
DatagramErrorfrom the system.OutOfMemoryErrorif theAllocatorcannot supply the list of sockets for the system.
Category: Networking.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2, wasm64-unknown-unknown.