Skip to content

Commit

Permalink
Prevent Polling from Blocking on 3DS (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
zoeyjodon authored Feb 2, 2024
1 parent 061ce30 commit a339bf5
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 39 deletions.
75 changes: 40 additions & 35 deletions include/enet/enet.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/**
@file enet.h
@brief ENet public header file
*/
Expand Down Expand Up @@ -75,7 +75,7 @@ typedef enum _ENetSocketShutdown
} ENetSocketShutdown;

/**
* Portable internet address structure.
* Portable internet address structure.
*/
typedef struct _ENetAddress
{
Expand All @@ -89,7 +89,7 @@ typedef struct _ENetAddress
* The host must be specified in network byte-order, and the port must be in
* host byte-order. The constant ENET_HOST_ANY may be used to specify the
* default server host.
@sa ENetPacket
*/
typedef enum _ENetPacketFlag
Expand All @@ -116,16 +116,16 @@ typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *);
/**
* ENet packet structure.
*
* An ENet data packet that may be sent to or received from a peer. The shown
* fields should only be read and never modified. The data field contains the
* allocated data for the packet. The dataLength fields specifies the length
* of the allocated data. The flags field is either 0 (specifying no flags),
* An ENet data packet that may be sent to or received from a peer. The shown
* fields should only be read and never modified. The data field contains the
* allocated data for the packet. The dataLength fields specifies the length
* of the allocated data. The flags field is either 0 (specifying no flags),
* or a bitwise-or of any combination of the following flags:
*
* ENET_PACKET_FLAG_RELIABLE - packet must be received by the target peer
* and resend attempts should be made until the packet is delivered
*
* ENET_PACKET_FLAG_UNSEQUENCED - packet will not be sequenced with other packets
* ENET_PACKET_FLAG_UNSEQUENCED - packet will not be sequenced with other packets
* (not supported for reliable packets)
*
* ENET_PACKET_FLAG_NO_ALLOCATE - packet will not allocate data, and user must supply it instead
Expand Down Expand Up @@ -169,7 +169,7 @@ typedef struct _ENetOutgoingCommand
} ENetOutgoingCommand;

typedef struct _ENetIncomingCommand
{
{
ENetListNode incomingCommandList;
enet_uint16 reliableSequenceNumber;
enet_uint16 unreliableSequenceNumber;
Expand All @@ -191,7 +191,7 @@ typedef enum _ENetPeerState
ENET_PEER_STATE_DISCONNECT_LATER = 6,
ENET_PEER_STATE_DISCONNECTING = 7,
ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 8,
ENET_PEER_STATE_ZOMBIE = 9
ENET_PEER_STATE_ZOMBIE = 9
} ENetPeerState;

#ifndef ENET_BUFFER_MAXIMUM
Expand All @@ -200,8 +200,13 @@ typedef enum _ENetPeerState

enum
{
#ifdef __3DS__
ENET_HOST_RECEIVE_BUFFER_SIZE = 0x20000,
ENET_HOST_SEND_BUFFER_SIZE = 0x20000,
#else
ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024,
ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024,
#endif
ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000,
ENET_HOST_DEFAULT_MTU = 900,
ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024,
Expand All @@ -210,7 +215,7 @@ enum
ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500,
ENET_PEER_DEFAULT_PACKET_THROTTLE = 32,
ENET_PEER_PACKET_THROTTLE_SCALE = 32,
ENET_PEER_PACKET_THROTTLE_COUNTER = 7,
ENET_PEER_PACKET_THROTTLE_COUNTER = 7,
ENET_PEER_PACKET_THROTTLE_ACCELERATION = 2,
ENET_PEER_PACKET_THROTTLE_DECELERATION = 2,
ENET_PEER_PACKET_THROTTLE_INTERVAL = 5000,
Expand Down Expand Up @@ -248,12 +253,12 @@ typedef enum _ENetPeerFlag
} ENetPeerFlag;

/**
* An ENet peer which data packets may be sent or received from.
* An ENet peer which data packets may be sent or received from.
*
* No fields should be modified unless otherwise specified.
* No fields should be modified unless otherwise specified.
*/
typedef struct _ENetPeer
{
{
ENetListNode dispatchList;
struct _ENetHost * host;
enet_uint16 outgoingPeerID;
Expand Down Expand Up @@ -312,7 +317,7 @@ typedef struct _ENetPeer
enet_uint16 reserved;
enet_uint16 incomingUnsequencedGroup;
enet_uint16 outgoingUnsequencedGroup;
enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32];
enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32];
enet_uint32 eventData;
size_t totalWaitingData;
} ENetPeer;
Expand All @@ -336,7 +341,7 @@ 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 host for communicating with peers.
*
* No fields should be modified unless otherwise stated.
Expand Down Expand Up @@ -399,21 +404,21 @@ typedef struct _ENetHost
typedef enum _ENetEventType
{
/** no event occurred within the specified time limit */
ENET_EVENT_TYPE_NONE = 0,
ENET_EVENT_TYPE_NONE = 0,

/** a connection request initiated by enet_host_connect has completed.
* The peer field contains the peer which successfully connected.
/** a connection request initiated by enet_host_connect has completed.
* The peer field contains the peer which successfully connected.
*/
ENET_EVENT_TYPE_CONNECT = 1,
ENET_EVENT_TYPE_CONNECT = 1,

/** a peer has disconnected. This event is generated on a successful
* completion of a disconnect initiated by enet_peer_disconnect, if
* a peer has timed out, or if a connection request intialized by
* enet_host_connect has timed out. The peer field contains the peer
* which disconnected. The data field contains user supplied data
/** a peer has disconnected. This event is generated on a successful
* completion of a disconnect initiated by enet_peer_disconnect, if
* a peer has timed out, or if a connection request intialized by
* enet_host_connect has timed out. The peer field contains the peer
* which disconnected. The data field contains user supplied data
* describing the disconnection, or 0, if none is available.
*/
ENET_EVENT_TYPE_DISCONNECT = 2,
ENET_EVENT_TYPE_DISCONNECT = 2,

/** a packet has been received from a peer. The peer field specifies the
* peer which sent the packet. The channelID field specifies the channel
Expand All @@ -426,10 +431,10 @@ typedef enum _ENetEventType

/**
* An ENet event as returned by enet_host_service().
@sa enet_host_service
*/
typedef struct _ENetEvent
typedef struct _ENetEvent
{
ENetEventType type; /**< type of the event */
ENetPeer * peer; /**< peer that generated a connect, disconnect or receive event */
Expand All @@ -439,17 +444,17 @@ typedef struct _ENetEvent
} ENetEvent;

/** @defgroup global ENet global functions
@{
@{
*/

/**
/**
Initializes ENet globally. Must be called prior to using any functions in
ENet.
@returns 0 on success, < 0 on failure
*/
ENET_API int enet_initialize (void);

/**
/**
Initializes ENet globally and supplies user-overridden callbacks. Must be called prior to using any functions in ENet. Do not use enet_initialize() if you use this variant. Make sure the ENetCallbacks structure is zeroed out so that any additional callbacks added in future versions will be properly ignored.
@param version the constant ENET_VERSION should be supplied so ENet knows which version of ENetCallbacks struct to use
Expand All @@ -458,15 +463,15 @@ ENET_API int enet_initialize (void);
*/
ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits);

/**
/**
Shuts down ENet globally. Should be called when a program that has
initialized ENet exits.
*/
ENET_API void enet_deinitialize (void);

/**
Gives the linked version of the ENet library.
@returns the version number
@returns the version number
*/
ENET_API ENetVersion enet_linked_version (void);

Expand Down Expand Up @@ -526,7 +531,7 @@ ENET_API ENetPacket * enet_packet_create (const void *, size_t, enet_uint32);
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 (int, const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32);
ENET_API void enet_host_destroy (ENetHost *);
ENET_API ENetPeer * enet_host_connect (ENetHost *, const ENetAddress *, size_t, enet_uint32);
Expand Down Expand Up @@ -567,7 +572,7 @@ ENET_API void * enet_range_coder_create (void);
ENET_API void enet_range_coder_destroy (void *);
ENET_API size_t enet_range_coder_compress (void *, const ENetBuffer *, size_t, size_t, enet_uint8 *, size_t);
ENET_API size_t enet_range_coder_decompress (void *, const enet_uint8 *, size_t, enet_uint8 *, size_t);

extern size_t enet_protocol_command_size (enet_uint8);

#ifdef __cplusplus
Expand Down
19 changes: 15 additions & 4 deletions unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,16 +226,16 @@ enet_address_make_v4mapped (ENetAddress * address)
ENetAddress oldAddress = *address;
struct sockaddr_in *sin = ((struct sockaddr_in *)&oldAddress.address);
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&address->address;

memset(sin6, 0, sizeof(*sin6));
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(*sin6);
sin6->sin6_port = sin->sin_port;

sin6->sin6_addr.s6_addr[10] = 0xFF;
sin6->sin6_addr.s6_addr[11] = 0xFF;
memcpy(&sin6->sin6_addr.s6_addr[12], &sin->sin_addr, 4);

address->addressLength = sizeof(*sin6);
}
#endif
Expand Down Expand Up @@ -768,7 +768,7 @@ enet_socket_receive (ENetSocket socket,

if (peerAddress != NULL) {
peerAddress -> addressLength = msgHdr.msg_namelen;

#ifdef __APPLE__
// HACK: Apple platforms return AF_INET addresses in msg_name from recvmsg() on dual-stack sockets
// instead of AF_INET6 addresses then rejects those same addresses when they are passed to sendmsg().
Expand Down Expand Up @@ -811,7 +811,18 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
if (* condition & ENET_SOCKET_WAIT_RECEIVE)
pollSocket.events |= POLLIN;

#if defined(__3DS__)
uint64_t poll_start = osGetTime();
for (uint64_t i = poll_start; (i - poll_start) < timeout; i = osGetTime()) {
pollCount = poll(& pollSocket, 1, 0); // need to do this on 3ds since poll will block even if socket is ready before
if (pollCount) {
break;
}
svcSleepThread(1000);
}
#else
pollCount = poll (& pollSocket, 1, timeout);
#endif

if (pollCount < 0)
{
Expand Down

0 comments on commit a339bf5

Please sign in to comment.