Skip to content

Commit

Permalink
implement BIO interface to support Network.framework
Browse files Browse the repository at this point in the history
  • Loading branch information
mman committed Mar 7, 2024
1 parent 51176b6 commit 0f6955e
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 35 deletions.
52 changes: 37 additions & 15 deletions host.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,33 @@
@{
*/

/** Creates a host for communicating to peers.
ENetHostBIO ENET_SOCKET_BIO = {
.context = NULL,
.enet_socket_create = &enet_socket_create,
.enet_socket_bind = &enet_socket_bind,
.enet_socket_send = &enet_socket_send,
.enet_socket_receive = &enet_socket_receive,
.enet_socket_wait = &enet_socket_wait,
.enet_socket_destroy = &enet_socket_destroy,
.enet_socket_set_option = &enet_socket_set_option,
.enet_socket_get_option = &enet_socket_get_option,
.enet_socket_get_address = &enet_socket_get_address,
};

void
enet_host_set_bio (ENetHost * host, ENetHostBIO bio)
{
host -> bio = bio;
}

/** Creates a host for communicating to peers.
@param address the address at which other peers may connect to this host. If NULL, then no peers may connect to the host.
@param peerCount the maximum number of peers that should be allocated for the host.
@param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
@param incomingBandwidth downstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
@param outgoingBandwidth upstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
@param bio basic input/output routines enet will use to setup/destroy socket and to send/receive data.
@returns the host on success and NULL on failure
Expand All @@ -26,7 +46,7 @@
at any given time.
*/
ENetHost *
enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth, ENetHostBIO bio)
{
ENetHost * host;
ENetPeer * currentPeer;
Expand All @@ -48,29 +68,31 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
}
memset (host -> peers, 0, peerCount * sizeof (ENetPeer));

host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM);
if( host -> socket > ENET_SOCKET_NULL ) {
enet_socket_set_option(host->socket, ENET_SOCKOPT_IPV6_V6ONLY, 0);
enet_socket_set_option(host->socket, ENET_SOCKOPT_IPV6_RECVPKTINFO, 1);
enet_socket_set_option(host->socket, ENET_SOCKOPT_REUSEADDR, 1);
host -> bio = bio;

host -> socket = (*host -> bio.enet_socket_create) (ENET_SOCKET_TYPE_DATAGRAM);
if (host -> socket > ENET_SOCKET_NULL) {
(*host -> bio.enet_socket_set_option)(host->socket, ENET_SOCKOPT_IPV6_V6ONLY, 0);
(*host -> bio.enet_socket_set_option)(host->socket, ENET_SOCKOPT_IPV6_RECVPKTINFO, 1);
(*host -> bio.enet_socket_set_option)(host->socket, ENET_SOCKOPT_REUSEADDR, 1);
}
if (host -> socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind (host -> socket, address) < 0))
if (host -> socket == ENET_SOCKET_NULL || (address != NULL && (*host -> bio.enet_socket_bind) (host -> socket, address) < 0))
{
if (host -> socket != ENET_SOCKET_NULL)
enet_socket_destroy (host -> socket);
(*host -> bio.enet_socket_destroy) (host -> socket);

enet_free (host -> peers);
enet_free (host);

return NULL;
}

enet_socket_set_option (host -> socket, ENET_SOCKOPT_NONBLOCK, 1);
enet_socket_set_option (host -> socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE);
enet_socket_set_option (host -> socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE);
enet_socket_set_option (host -> socket, ENET_SOCKOPT_QOS, 1);
(*host -> bio.enet_socket_set_option) (host -> socket, ENET_SOCKOPT_NONBLOCK, 1);
(*host -> bio.enet_socket_set_option) (host -> socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE);
(*host -> bio.enet_socket_set_option) (host -> socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE);
(*host -> bio.enet_socket_set_option) (host -> socket, ENET_SOCKOPT_QOS, 1);

if (address != NULL && enet_socket_get_address (host -> socket, & host -> address) < 0)
if (address != NULL && (*host -> bio.enet_socket_get_address) (host -> socket, & host -> address) < 0)
host -> address = * address;

if (! channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
Expand Down Expand Up @@ -150,7 +172,7 @@ enet_host_destroy (ENetHost * host)
if (host == NULL)
return;

enet_socket_destroy (host -> socket);
(*host -> bio.enet_socket_destroy) (host -> socket);

for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
Expand Down
38 changes: 32 additions & 6 deletions include/enet/enet.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,10 @@ typedef struct _ENetPeer
enet_uint32 connectID;
enet_uint8 outgoingSessionID;
enet_uint8 incomingSessionID;
ENetAddress myAddress; /**< Internet address the peer is using to talk to me */
ENetAddress localAddress; /**< Internet address the peer is using to talk to me */
ENetAddress peerAddress; /**< Internet address of the peer */
void * data; /**< Application private data, may be freely modified */
void * connection; /**< Application private data, may be freely modified */
ENetPeerState state;
ENetChannel * channels;
size_t channelCount; /**< Number of channels allocated for communication with peer */
Expand Down Expand Up @@ -353,7 +354,27 @@ typedef enet_uint32 (ENET_CALLBACK * ENetChecksumCallback) (const ENetBuffer * b

/** Callback for intercepting received raw UDP packets. Should return 1 to intercept, 0 to ignore, or -1 to propagate an error. */
typedef int (ENET_CALLBACK * ENetInterceptCallback) (struct _ENetHost * host, struct _ENetEvent * event);


/** An ENet structure to represent basic input/output routines for socket setup and sending/receiving data.
*/
typedef struct _ENetHistBIO
{
void * context;
ENetSocket (*enet_socket_create) (ENetSocketType);
int (*enet_socket_bind) (ENetSocket, const ENetAddress *);
int (*enet_socket_get_address) (ENetSocket, ENetAddress *);
int (*enet_socket_send) (void *, ENetSocket, const ENetAddress *, const ENetBuffer *, size_t, const ENetAddress *, void *);
int (*enet_socket_receive) (void *, ENetSocket, ENetAddress *, ENetBuffer *, size_t, ENetAddress *, void **);
int (*enet_socket_wait) (ENetSocket, enet_uint32 *, enet_uint32);
int (*enet_socket_set_option) (ENetSocket, ENetSocketOption, int);
int (*enet_socket_get_option) (ENetSocket, ENetSocketOption, int *);
void (*enet_socket_destroy) (ENetSocket);
} ENetHostBIO;

/** Default BSD socket based implementation of input/output routines for socket setup and sending/receiving data.
*/
extern ENetHostBIO ENET_SOCKET_BIO;

/** An ENet host for communicating with peers.
*
* No fields should be modified unless otherwise stated.
Expand All @@ -363,6 +384,7 @@ typedef int (ENET_CALLBACK * ENetInterceptCallback) (struct _ENetHost * host, st
@sa enet_host_connect()
@sa enet_host_service()
@sa enet_host_flush()
@sa enet_host_fetch()
@sa enet_host_broadcast()
@sa enet_host_compress()
@sa enet_host_compress_with_range_coder()
Expand Down Expand Up @@ -395,7 +417,7 @@ typedef struct _ENetHost
ENetChecksumCallback checksum; /**< callback the user can set to enable packet checksums for this host */
ENetCompressor compressor;
enet_uint8 packetData [2][ENET_PROTOCOL_MAXIMUM_MTU];
ENetAddress myAddress;
ENetAddress localAddress;
ENetAddress peerAddress;
enet_uint8 * receivedData;
size_t receivedDataLength;
Expand All @@ -409,6 +431,8 @@ typedef struct _ENetHost
size_t duplicatePeers; /**< optional number of allowed peers from duplicate IPs, defaults to ENET_PROTOCOL_MAXIMUM_PEER_ID */
size_t maximumPacketSize; /**< the maximum allowable packet size that may be sent or received on a peer */
size_t maximumWaitingData; /**< the maximum aggregate amount of buffer space a peer may use waiting for packets to be delivered */
ENetHostBIO bio;
void * connection;
} ENetHost;

/**
Expand Down Expand Up @@ -511,8 +535,8 @@ ENET_API int enet_socket_get_address (ENetSocket, ENetAddress *);
ENET_API int enet_socket_listen (ENetSocket, int);
ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *);
ENET_API int enet_socket_connect (ENetSocket, const ENetAddress *);
ENET_API int enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t, const ENetAddress *);
ENET_API int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t, ENetAddress *);
ENET_API int enet_socket_send (void *, ENetSocket, const ENetAddress *, const ENetBuffer *, size_t, const ENetAddress *, void *);
ENET_API int enet_socket_receive (void *, ENetSocket, ENetAddress *, ENetBuffer *, size_t, ENetAddress *, void **);
ENET_API int enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32);
ENET_API int enet_socket_set_option (ENetSocket, ENetSocketOption, int);
ENET_API int enet_socket_get_option (ENetSocket, ENetSocketOption, int *);
Expand Down Expand Up @@ -573,12 +597,13 @@ ENET_API void enet_packet_destroy (ENetPacket *);
ENET_API int enet_packet_resize (ENetPacket *, size_t);
ENET_API enet_uint32 enet_crc32 (const ENetBuffer *, size_t);

ENET_API ENetHost * enet_host_create (const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32);
ENET_API ENetHost * enet_host_create (const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32, ENetHostBIO);
ENET_API void enet_host_destroy (ENetHost *);
ENET_API ENetPeer * enet_host_connect (ENetHost *, const ENetAddress *, size_t, enet_uint32, enet_uint32);
ENET_API int enet_host_check_events (ENetHost *, ENetEvent *);
ENET_API int enet_host_service (ENetHost *, ENetEvent *, enet_uint32);
ENET_API void enet_host_flush (ENetHost *);
ENET_API void enet_host_fetch (ENetHost *);
ENET_API void enet_host_broadcast (ENetHost *, enet_uint8, ENetPacket *);
ENET_API void enet_host_compress (ENetHost *, const ENetCompressor *);
ENET_API int enet_host_compress_with_range_coder (ENetHost * host);
Expand All @@ -587,6 +612,7 @@ ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uin
extern void enet_host_bandwidth_throttle (ENetHost *);
extern enet_uint32 enet_host_random_seed (void);
extern enet_uint32 enet_host_random (ENetHost *);
ENET_API void enet_host_set_bio (ENetHost *, ENetHostBIO);

ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *);
ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID);
Expand Down
43 changes: 33 additions & 10 deletions protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,8 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT;
peer -> connectID = command -> connect.connectID;
peer -> peerAddress = host -> peerAddress;
peer -> myAddress = host -> myAddress;
peer -> localAddress = host -> localAddress;
peer -> connection = host -> connection;
peer -> mtu = host -> mtu;
peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID);
peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth);
Expand Down Expand Up @@ -1092,7 +1093,7 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
{
peer -> peerAddress.host = host -> peerAddress.host;
peer -> peerAddress.port = host -> peerAddress.port;
peer -> myAddress = host -> myAddress;
peer -> localAddress = host -> localAddress;
peer -> incomingDataTotal += host -> receivedDataLength;
}

Expand Down Expand Up @@ -1242,11 +1243,13 @@ enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
buffer.data = host -> packetData [0];
buffer.dataLength = sizeof (host -> packetData [0]);

receivedLength = enet_socket_receive (host -> socket,
& host -> peerAddress,
& buffer,
1,
& host -> myAddress);
receivedLength = (*host -> bio.enet_socket_receive) (host -> bio.context,
host -> socket,
& host -> peerAddress,
& buffer,
1,
& host -> localAddress,
&host -> connection);

if (receivedLength == -2)
continue;
Expand Down Expand Up @@ -1731,10 +1734,16 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
if (currentPeer -> state == ENET_PEER_STATE_CONNECTING && currentPeer -> packetsLost == 2) {
// Disable QoS tagging if we don't get a response to 2 connection requests in a row.
// Some networks drop QoS tagged packets, so let's try without it.
enet_socket_set_option (host -> socket, ENET_SOCKOPT_QOS, 0);
(*host -> bio.enet_socket_set_option) (host -> socket, ENET_SOCKOPT_QOS, 0);
}

sentLength = enet_socket_send (host -> socket, & currentPeer -> peerAddress, host -> buffers, host -> bufferCount, & currentPeer -> myAddress);
sentLength = (*host -> bio.enet_socket_send) (host -> bio.context,
host -> socket,
& currentPeer -> peerAddress,
host -> buffers,
host -> bufferCount,
& currentPeer -> localAddress,
currentPeer -> connection);

enet_protocol_remove_sent_unreliable_commands (currentPeer, & sentUnreliableCommands);

Expand Down Expand Up @@ -1766,6 +1775,20 @@ enet_host_flush (ENetHost * host)
enet_protocol_send_outgoing_commands (host, NULL, 0);
}

/** Receives any available packets from networking stack and queues events to be delivered to the host.
@param host host to fetch
@remarks this function need only be used in circumstances where one wishes to receive and parse packets available in networking stack earlier than in a call to enet_host_service().
@ingroup host
*/
void
enet_host_fetch (ENetHost * host)
{
host -> serviceTime = enet_time_get ();

enet_protocol_receive_incoming_commands (host, NULL);
}

/** Checks for any queued events on the host and dispatches one if available.
@param host host to check for events
Expand Down Expand Up @@ -1915,7 +1938,7 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout)

waitCondition = ENET_SOCKET_WAIT_RECEIVE | ENET_SOCKET_WAIT_INTERRUPT;

if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0)
if ((*host -> bio.enet_socket_wait) (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0)
return -1;
}
while (waitCondition & ENET_SOCKET_WAIT_INTERRUPT);
Expand Down
10 changes: 6 additions & 4 deletions unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -504,11 +504,12 @@ enet_socket_destroy (ENetSocket socket)
}

int
enet_socket_send (ENetSocket socket,
enet_socket_send (void * context, ENetSocket socket,
const ENetAddress * destinationAddress,
const ENetBuffer * buffers,
size_t bufferCount,
const ENetAddress * sourceAddress)
const ENetAddress * sourceAddress,
void * connection)
{
struct msghdr msgHdr;
struct sockaddr_in6 sin;
Expand Down Expand Up @@ -566,11 +567,12 @@ enet_socket_send (ENetSocket socket,
}

int
enet_socket_receive (ENetSocket socket,
enet_socket_receive (void * context, ENetSocket socket,
ENetAddress * sourceAddress,
ENetBuffer * buffers,
size_t bufferCount,
ENetAddress * destinationAddress)
ENetAddress * destinationAddress,
void ** connection)
{
struct msghdr msgHdr;
struct sockaddr_in6 sin;
Expand Down

0 comments on commit 0f6955e

Please sign in to comment.