2023-11-09 18:02:59 (UTC-03:00)
Marcel Rodrigues <marcelgmr@gmail.com>
add basic ENet support
diff --git a/lib/arco.lua b/lib/arco.lua index 60b1491..8d2522e 100644 --- a/lib/arco.lua +++ b/lib/arco.lua @@ -1,3 +1,4 @@ local arco = {} arco.sdl = require "arco.sdl2" +arco.net = require "arco.enet" return arco diff --git a/lib/arco/cdef_enet.h b/lib/arco/cdef_enet.h new file mode 100644 index 0000000..430efd7 --- /dev/null +++ b/lib/arco/cdef_enet.h @@ -0,0 +1,292 @@ +/* API defs from enet enet 1.3.17 */ + +typedef uint8_t enet_uint8; +typedef uint16_t enet_uint16; +typedef uint32_t enet_uint32; +typedef enet_uint32 ENetVersion; +typedef struct _ENetAddress +{ + enet_uint32 host; + enet_uint16 port; +} ENetAddress; +typedef struct ENetHost ENetHost; +/* +typedef struct _ENetHost +{ + ENetSocket socket; + ENetAddress address; + enet_uint32 incomingBandwidth; + enet_uint32 outgoingBandwidth; + enet_uint32 bandwidthThrottleEpoch; + enet_uint32 mtu; + enet_uint32 randomSeed; + int recalculateBandwidthLimits; + ENetPeer * peers; + size_t peerCount; + size_t channelLimit; + enet_uint32 serviceTime; + ENetList dispatchQueue; + int continueSending; + size_t packetSize; + enet_uint16 headerFlags; + ENetProtocol commands [ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS]; + size_t commandCount; + ENetBuffer buffers [ENET_BUFFER_MAXIMUM]; + size_t bufferCount; + ENetChecksumCallback checksum; + ENetCompressor compressor; + enet_uint8 packetData [2][ENET_PROTOCOL_MAXIMUM_MTU]; + ENetAddress receivedAddress; + enet_uint8 * receivedData; + size_t receivedDataLength; + enet_uint32 totalSentData; + enet_uint32 totalSentPackets; + enet_uint32 totalReceivedData; + enet_uint32 totalReceivedPackets; + ENetInterceptCallback intercept; + size_t connectedPeers; + size_t bandwidthLimitedPeers; + size_t duplicatePeers; + size_t maximumPacketSize; + size_t maximumWaitingData; +} ENetHost; +*/ +typedef struct _ENetListNode +{ + struct _ENetListNode * next; + struct _ENetListNode * previous; +} ENetListNode; +typedef ENetListNode * ENetListIterator; +typedef struct _ENetList +{ + ENetListNode sentinel; +} ENetList; +typedef enum _ENetPeerState +{ + ENET_PEER_STATE_DISCONNECTED = 0, + ENET_PEER_STATE_CONNECTING = 1, + ENET_PEER_STATE_ACKNOWLEDGING_CONNECT = 2, + ENET_PEER_STATE_CONNECTION_PENDING = 3, + ENET_PEER_STATE_CONNECTION_SUCCEEDED = 4, + ENET_PEER_STATE_CONNECTED = 5, + ENET_PEER_STATE_DISCONNECT_LATER = 6, + ENET_PEER_STATE_DISCONNECTING = 7, + ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 8, + ENET_PEER_STATE_ZOMBIE = 9 +} ENetPeerState; +enum +{ + ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024, + ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024, + ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000, + ENET_HOST_DEFAULT_MTU = 1400, + ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024, + ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024, + + 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_ACCELERATION = 2, + ENET_PEER_PACKET_THROTTLE_DECELERATION = 2, + ENET_PEER_PACKET_THROTTLE_INTERVAL = 5000, + ENET_PEER_PACKET_LOSS_SCALE = (1 << 16), + ENET_PEER_PACKET_LOSS_INTERVAL = 10000, + ENET_PEER_WINDOW_SIZE_SCALE = 64 * 1024, + ENET_PEER_TIMEOUT_LIMIT = 32, + ENET_PEER_TIMEOUT_MINIMUM = 5000, + ENET_PEER_TIMEOUT_MAXIMUM = 30000, + ENET_PEER_PING_INTERVAL = 500, + ENET_PEER_UNSEQUENCED_WINDOWS = 64, + ENET_PEER_UNSEQUENCED_WINDOW_SIZE = 1024, + ENET_PEER_FREE_UNSEQUENCED_WINDOWS = 32, + ENET_PEER_RELIABLE_WINDOWS = 16, + ENET_PEER_RELIABLE_WINDOW_SIZE = 0x1000, + ENET_PEER_FREE_RELIABLE_WINDOWS = 8 +}; +typedef struct _ENetChannel +{ + enet_uint16 outgoingReliableSequenceNumber; + enet_uint16 outgoingUnreliableSequenceNumber; + enet_uint16 usedReliableWindows; + enet_uint16 reliableWindows [ENET_PEER_RELIABLE_WINDOWS]; + enet_uint16 incomingReliableSequenceNumber; + enet_uint16 incomingUnreliableSequenceNumber; + ENetList incomingReliableCommands; + ENetList incomingUnreliableCommands; +} ENetChannel; +typedef struct _ENetPeer +{ + ENetListNode dispatchList; + ENetHost * host; + enet_uint16 outgoingPeerID; + enet_uint16 incomingPeerID; + enet_uint32 connectID; + enet_uint8 outgoingSessionID; + enet_uint8 incomingSessionID; + ENetAddress address; + void * data; + ENetPeerState state; + ENetChannel * channels; + size_t channelCount; + enet_uint32 incomingBandwidth; + enet_uint32 outgoingBandwidth; + enet_uint32 incomingBandwidthThrottleEpoch; + enet_uint32 outgoingBandwidthThrottleEpoch; + enet_uint32 incomingDataTotal; + enet_uint32 outgoingDataTotal; + enet_uint32 lastSendTime; + enet_uint32 lastReceiveTime; + enet_uint32 nextTimeout; + enet_uint32 earliestTimeout; + enet_uint32 packetLossEpoch; + enet_uint32 packetsSent; + enet_uint32 packetsLost; + enet_uint32 packetLoss; + enet_uint32 packetLossVariance; + enet_uint32 packetThrottle; + enet_uint32 packetThrottleLimit; + enet_uint32 packetThrottleCounter; + enet_uint32 packetThrottleEpoch; + enet_uint32 packetThrottleAcceleration; + enet_uint32 packetThrottleDeceleration; + enet_uint32 packetThrottleInterval; + enet_uint32 pingInterval; + enet_uint32 timeoutLimit; + enet_uint32 timeoutMinimum; + enet_uint32 timeoutMaximum; + enet_uint32 lastRoundTripTime; + enet_uint32 lowestRoundTripTime; + enet_uint32 lastRoundTripTimeVariance; + enet_uint32 highestRoundTripTimeVariance; + enet_uint32 roundTripTime; + enet_uint32 roundTripTimeVariance; + enet_uint32 mtu; + enet_uint32 windowSize; + enet_uint32 reliableDataInTransit; + enet_uint16 outgoingReliableSequenceNumber; + ENetList acknowledgements; + ENetList sentReliableCommands; + ENetList sentUnreliableCommands; + ENetList outgoingCommands; + ENetList dispatchedCommands; + enet_uint16 flags; + enet_uint16 reserved; + enet_uint16 incomingUnsequencedGroup; + enet_uint16 outgoingUnsequencedGroup; + enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32]; + enet_uint32 eventData; + size_t totalWaitingData; +} ENetPeer; +typedef enum _ENetEventType +{ + ENET_EVENT_TYPE_NONE = 0, + ENET_EVENT_TYPE_CONNECT = 1, + ENET_EVENT_TYPE_DISCONNECT = 2, + ENET_EVENT_TYPE_RECEIVE = 3 +} ENetEventType; +typedef struct _ENetPacket +{ + size_t referenceCount; + enet_uint32 flags; + enet_uint8 * data; + size_t dataLength; + ENetPacketFreeCallback freeCallback; + void * userData; +} ENetPacket; +typedef struct _ENetEvent +{ + ENetEventType type; + ENetPeer * peer; + enet_uint8 channelID; + enet_uint32 data; + ENetPacket * packet; +} ENetEvent; + +typedef enum _ENetSocketType +{ + ENET_SOCKET_TYPE_STREAM = 1, + ENET_SOCKET_TYPE_DATAGRAM = 2 +} ENetSocketType; +typedef enum _ENetSocketOption +{ + ENET_SOCKOPT_NONBLOCK = 1, + ENET_SOCKOPT_BROADCAST = 2, + ENET_SOCKOPT_RCVBUF = 3, + ENET_SOCKOPT_SNDBUF = 4, + ENET_SOCKOPT_REUSEADDR = 5, + ENET_SOCKOPT_RCVTIMEO = 6, + ENET_SOCKOPT_SNDTIMEO = 7, + ENET_SOCKOPT_ERROR = 8, + ENET_SOCKOPT_NODELAY = 9 +} ENetSocketOption; +typedef enum _ENetSocketShutdown +{ + ENET_SOCKET_SHUTDOWN_READ = 0, + ENET_SOCKET_SHUTDOWN_WRITE = 1, + ENET_SOCKET_SHUTDOWN_READ_WRITE = 2 +} ENetSocketShutdown; + +int enet_initialize (void); +int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits); +void enet_deinitialize (void); +ENetVersion enet_linked_version (void); + +enet_uint32 enet_time_get (void); +void enet_time_set (enet_uint32); + +ENetSocket enet_socket_create (ENetSocketType); +int enet_socket_bind (ENetSocket, const ENetAddress *); +int enet_socket_get_address (ENetSocket, ENetAddress *); +int enet_socket_listen (ENetSocket, int); +ENetSocket enet_socket_accept (ENetSocket, ENetAddress *); +int enet_socket_connect (ENetSocket, const ENetAddress *); +int enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t); +int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t); +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 *); +int enet_socket_shutdown (ENetSocket, ENetSocketShutdown); +void enet_socket_destroy (ENetSocket); +/* FIXME: ENetSocketSet is fd_set which is platform-dependent (see unix.h vs win32.h) + We only need pointers so let's give a stub definition for now */ +typedef struct ENetSocketSet ENetSocketSet; +int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSocketSet *, enet_uint32); + +int enet_address_set_host_ip (ENetAddress * address, const char * hostName); +int enet_address_set_host (ENetAddress * address, const char * hostName); +int enet_address_get_host_ip (const ENetAddress * address, char * hostName, size_t nameLength); +int enet_address_get_host (const ENetAddress * address, char * hostName, size_t nameLength); + +ENetPacket * enet_packet_create (const void *, size_t, enet_uint32); +void enet_packet_destroy (ENetPacket *); +int enet_packet_resize (ENetPacket *, size_t); +enet_uint32 enet_crc32 (const ENetBuffer *, size_t); + +ENetHost * enet_host_create (const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32); +void enet_host_destroy (ENetHost *); +ENetPeer * enet_host_connect (ENetHost *, const ENetAddress *, size_t, enet_uint32); +int enet_host_check_events (ENetHost *, ENetEvent *); +int enet_host_service (ENetHost *, ENetEvent *, enet_uint32); +void enet_host_flush (ENetHost *); +void enet_host_broadcast (ENetHost *, enet_uint8, ENetPacket *); +void enet_host_compress (ENetHost *, const ENetCompressor *); +int enet_host_compress_with_range_coder (ENetHost * host); +void enet_host_channel_limit (ENetHost *, size_t); +void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32); + +int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *); +ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID); +void enet_peer_ping (ENetPeer *); +void enet_peer_ping_interval (ENetPeer *, enet_uint32); +void enet_peer_timeout (ENetPeer *, enet_uint32, enet_uint32, enet_uint32); +void enet_peer_reset (ENetPeer *); +void enet_peer_disconnect (ENetPeer *, enet_uint32); +void enet_peer_disconnect_now (ENetPeer *, enet_uint32); +void enet_peer_disconnect_later (ENetPeer *, enet_uint32); +void enet_peer_throttle_configure (ENetPeer *, enet_uint32, enet_uint32, enet_uint32); + +void * enet_range_coder_create (void); +void enet_range_coder_destroy (void *); +size_t enet_range_coder_compress (void *, const ENetBuffer *, size_t, size_t, enet_uint8 *, size_t); +size_t enet_range_coder_decompress (void *, const enet_uint8 *, size_t, enet_uint8 *, size_t); diff --git a/lib/arco/enet.lua b/lib/arco/enet.lua new file mode 100644 index 0000000..1b0fa43 --- /dev/null +++ b/lib/arco/enet.lua @@ -0,0 +1,62 @@ +local ffi = require "ffi" + +cdefs_callbacks = [[ +struct _ENetPacket; +typedef void (__cdecl * ENetPacketFreeCallback) (struct _ENetPacket *); +typedef struct _ENetCallbacks +{ + void * (__cdecl * malloc) (size_t size); + void (__cdecl * free) (void * memory); + void (__cdecl * no_memory) (void); +} ENetCallbacks; +typedef struct _ENetCompressor +{ + void * context; + size_t (__cdecl * compress) (void * context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, uint8_t * outData, size_t outLimit); + size_t (__cdecl * decompress) (void * context, const uint8_t * inData, size_t inLimit, uint8_t * outData, size_t outLimit); + void (__cdecl * destroy) (void * context); +} ENetCompressor; +]] +if ffi.os == "Windows" then + ffi.cdef[[ + typedef SOCKET ENetSocket; + typedef struct + { + size_t dataLength; + void * data; + } ENetBuffer; + ]] +else + ffi.cdef[[ + typedef int ENetSocket; + typedef struct + { + void * data; + size_t dataLength; + } ENetBuffer; + ]] + cdefs_callbacks = cdefs_callbacks:gsub("__cdecl", "") +end +ffi.cdef(cdefs_callbacks) + +local here = debug.getinfo(1).source:match("@?(.*/)") or "" +local cdefs = io.open(here.."cdef_enet.h", "r"):read("*a") +ffi.cdef(cdefs) + +local enet = ffi.load("enet") + +local consts = { + ENET_HOST_ANY = 0, + ENET_HOST_BROADCAST = 0xFFFFFFFF, + ENET_PORT_ANY = 0, +} + +return setmetatable(consts, { + __index = function (t, k) + local ok, obj = pcall(function () return enet["enet_"..k] end) + if not ok then + obj = enet[k] + end + return obj + end +})