| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- #pragma once
- #include "Baselib_ErrorState.h"
- #include "Baselib_Memory.h"
- #include "Baselib_NetworkAddress.h"
- #include "Internal/Baselib_EnumSizeCheck.h"
- #include <stdint.h>
- #ifdef __cplusplus
- BASELIB_C_INTERFACE
- {
- #endif
- // ------------------------------------------------------------------------------------------------
- // Network buffers
- // Implementation defined internal buffer id.
- typedef void* Baselib_RegisteredNetwork_Buffer_Id;
- static const Baselib_RegisteredNetwork_Buffer_Id Baselib_RegisteredNetwork_Buffer_Id_Invalid = 0;
- // Network buffer structure.
- // One buffer can contain multiple packets and endpoints.
- typedef struct Baselib_RegisteredNetwork_Buffer
- {
- Baselib_RegisteredNetwork_Buffer_Id id;
- Baselib_Memory_PageAllocation allocation;
- } Baselib_RegisteredNetwork_Buffer;
- // Create a network buffer from a set of previously allocated memory pages.
- //
- // Possible error codes:
- // - InvalidAddressRange: if pageAllocation is invalid
- //
- // \returns A network buffer. If registration fails, then buffer id is set to Baselib_RegisteredNetwork_Buffer_Id_Invalid.
- BASELIB_API Baselib_RegisteredNetwork_Buffer Baselib_RegisteredNetwork_Buffer_Register(
- Baselib_Memory_PageAllocation pageAllocation,
- Baselib_ErrorState* errorState
- );
- // Deregister network buffer. Disassociate memory pages and buffer representation.
- //
- // Allocated pages will stay allocated and can now be used for something else.
- // Passing an invalid buffer results in a no-op.
- BASELIB_API void Baselib_RegisteredNetwork_Buffer_Deregister(
- Baselib_RegisteredNetwork_Buffer buffer
- );
- // ------------------------------------------------------------------------------------------------
- // Network buffers slices
- // Slice of a network buffer.
- typedef struct Baselib_RegisteredNetwork_BufferSlice
- {
- Baselib_RegisteredNetwork_Buffer_Id id;
- void* data; // data of the slice
- uint32_t size; // size of the slice in bytes
- uint32_t offset; // offset in main buffer
- } Baselib_RegisteredNetwork_BufferSlice;
- // Creates slice from network buffer
- //
- // \param buffer Buffer to create slice from.
- // \param offset Offset in buffer in bytes.
- // \param size Size of the slice in bytes.
- BASELIB_API Baselib_RegisteredNetwork_BufferSlice Baselib_RegisteredNetwork_BufferSlice_Create(
- Baselib_RegisteredNetwork_Buffer buffer,
- uint32_t offset,
- uint32_t size
- );
- // Create empty slice that doesn't point to anything
- //
- // Guaranteed to reference Baselib_RegisteredNetwork_Buffer_Id_Invalid and have all other values zeroed out.
- BASELIB_API Baselib_RegisteredNetwork_BufferSlice Baselib_RegisteredNetwork_BufferSlice_Empty(void);
- // ------------------------------------------------------------------------------------------------
- // Network endpoints are platform defined representation (sockaddr_in-like) of network address (family, ip, port).
- typedef struct Baselib_RegisteredNetwork_Endpoint { Baselib_RegisteredNetwork_BufferSlice slice; } Baselib_RegisteredNetwork_Endpoint;
- static const uint32_t Baselib_RegisteredNetwork_Endpoint_MaxSize = 28; // in bytes
- // Place network address into the network buffer.
- //
- // Destination must be able to accommodate Baselib_RegisteredNetwork_Endpoint_MaxSize bytes.
- //
- // \param srcAddress Network address to use, pass nullptr to create an empty endpoint.
- // \param dstSlice Where to write encoded data.
- //
- // Possible error codes:
- // - InvalidArgument: if dstSlice is invalid
- // - InvalidBufferSize: if dstSlice is smaller than Baselib_RegisteredNetwork_Endpoint_MaxSize
- //
- // \returns Endpoint or Endpoint_Empty in case of failure.
- BASELIB_API Baselib_RegisteredNetwork_Endpoint Baselib_RegisteredNetwork_Endpoint_Create(
- const Baselib_NetworkAddress* srcAddress,
- Baselib_RegisteredNetwork_BufferSlice dstSlice,
- Baselib_ErrorState* errorState
- );
- // Return empty endpoint that doesn't point to anything
- //
- // Guaranteed to contain Baselib_RegisteredNetwork_BufferSlice_Empty
- BASELIB_API Baselib_RegisteredNetwork_Endpoint Baselib_RegisteredNetwork_Endpoint_Empty(void);
- // Decode endpoint.
- //
- // \param endpoint Endpoint to be converted.
- // \param dstAddress Pointer to address to write data to.
- //
- // Possible error codes:
- // - InvalidArgument: if endpoint is invalid or dstAddress is null
- BASELIB_API void Baselib_RegisteredNetwork_Endpoint_GetNetworkAddress(
- Baselib_RegisteredNetwork_Endpoint endpoint,
- Baselib_NetworkAddress* dstAddress,
- Baselib_ErrorState* errorState
- );
- // ------------------------------------------------------------------------------------------------
- // Request & Completion
- // Send/receive request.
- typedef struct Baselib_RegisteredNetwork_Request
- {
- Baselib_RegisteredNetwork_BufferSlice payload;
- // for sending: remote address to which the payload is sent (required for UDP)
- // for receiving: address from which the data was sent (optional)
- Baselib_RegisteredNetwork_Endpoint remoteEndpoint;
- // TODO: Not support yet. (We would also need to support this in Baselib_Socket first)
- // for sending: unused
- // for receiving: local address on which the data was received (optional)
- //Baselib_RegisteredNetwork_Endpoint localEndpoint;
- void* requestUserdata;
- } Baselib_RegisteredNetwork_Request;
- // Success or failure of a Baselib_RegisteredNetwork_CompletionResult.
- typedef enum Baselib_RegisteredNetwork_CompletionStatus
- {
- // Networking request failed.
- Baselib_RegisteredNetwork_CompletionStatus_Failed = 0,
- // Networking request successfully finished.
- Baselib_RegisteredNetwork_CompletionStatus_Success = 1,
- } Baselib_RegisteredNetwork_CompletionStatus;
- BASELIB_ENUM_ENSURE_ABI_COMPATIBILITY(Baselib_RegisteredNetwork_CompletionStatus);
- // Result of a previously scheduled send/receive
- //
- // When a networking request is completed, this is placed into an internal completion queue.
- typedef struct Baselib_RegisteredNetwork_CompletionResult
- {
- Baselib_RegisteredNetwork_CompletionStatus status;
- uint32_t bytesTransferred;
- void* requestUserdata;
- } Baselib_RegisteredNetwork_CompletionResult;
- // ------------------------------------------------------------------------------------------------
- // UDP connectionless socket.
- typedef struct Baselib_RegisteredNetwork_Socket_UDP { struct Baselib_RegisteredNetwork_Socket_UDP_Impl* handle; } Baselib_RegisteredNetwork_Socket_UDP;
- static const Baselib_RegisteredNetwork_Socket_UDP Baselib_RegisteredNetwork_Socket_UDP_Invalid = { NULL };
- // Creates an UDP socket with internal request and completion queues.
- //
- // \param bindAddress Address to bind socket to, in connectionless UDP every socket has to be bound.
- // \param endpointReuse Allows multiple sockets to be bound to the same address/port if set to AddressReuse_Allow,
- // All sockets bound to the same address/port need to have this flag set.
- // \param sendQueueSize Send queue size in amount of entries.
- // \param recvQueueSize Receive queue size in amount of entries.
- //
- // Known issues (behavior may change in the future):
- // - Some platforms do not support sending zero sized UDP packets.
- //
- // Possible error codes:
- // - InvalidArgument: if bindAddress pointer is null or incompatible or both sendQueueSize and recvQueueSize are zero
- // - EndpointInUse: endpoint is already in use
- // - AddressFamilyNotSupported: if the requested address family is not available.
- // - OutOfSystemResources: if network session limit was exceeded
- //
- // \returns A UDP socket. If socket creation fails, socket holds a Baselib_RegisteredNetwork_Socket_UDP_InvalidHandle.
- BASELIB_API Baselib_RegisteredNetwork_Socket_UDP Baselib_RegisteredNetwork_Socket_UDP_Create(
- const Baselib_NetworkAddress* bindAddress,
- Baselib_NetworkAddress_AddressReuse endpointReuse,
- uint32_t sendQueueSize,
- uint32_t recvQueueSize,
- Baselib_ErrorState* errorState
- );
- // Schedules receive requests.
- //
- // \param socket Socket to be used.
- // \param requests Array of pointers to requests. No-op if null.
- // Request objects can be freed after the function call.
- // \param requestsCount Amount of requests in the array. No-op if zero.
- //
- // If requests is null or requestsCount is zero, this operation is a no-op.
- // Note that actual receiving may be deferred until you call Baselib_RegisteredNetwork_Socket_UDP_ProcessRecv.
- // UDP message data that doesn't fit a message buffer is silently discarded.
- //
- // Known issues (behavior may change in the future):
- // - Some platforms does not support receiving zero sized UDP packets.
- //
- // Possible error codes:
- // - InvalidArgument: if socket is invalid
- //
- // \returns The number of scheduled items. If scheduling fails this function return zero.
- BASELIB_API uint32_t Baselib_RegisteredNetwork_Socket_UDP_ScheduleRecv(
- Baselib_RegisteredNetwork_Socket_UDP socket,
- const Baselib_RegisteredNetwork_Request* requests,
- uint32_t requestsCount,
- Baselib_ErrorState* errorState
- );
- // Schedules send requests.
- //
- // \param socket Socket to be used.
- // \param requests Array of pointers to requests. No-op if null.
- // Request objects can be freed after the function call.
- // \param requestsCount Amount of requests in the array. No-op if zero.
- //
- // If requests is null or requestsCount is zero, this operation is a no-op.
- // Note that actual receiving may be deferred until you call Baselib_RegisteredNetwork_Socket_UDP_ProcessSend.
- //
- // Possible error codes:
- // - InvalidArgument: if socket is invalid
- //
- // \returns The number of scheduled items. If scheduling fails this function return zero.
- BASELIB_API uint32_t Baselib_RegisteredNetwork_Socket_UDP_ScheduleSend(
- Baselib_RegisteredNetwork_Socket_UDP socket,
- const Baselib_RegisteredNetwork_Request* requests,
- uint32_t requestsCount,
- Baselib_ErrorState* errorState
- );
- // Status of processing send/recv.
- typedef enum Baselib_RegisteredNetwork_ProcessStatus
- {
- // No further items to process.
- //
- // Note that this does not imply that all requests have been fully processed at any moment in time.
- Baselib_RegisteredNetwork_ProcessStatus_NonePendingImmediately = 0,
- // deprecated, same as Baselib_RegisteredNetwork_ProcessStatus_NonePendingImmediately
- Baselib_RegisteredNetwork_ProcessStatus_Done
- COMPILER_DEPRECATED_ENUM_VALUE("Use Baselib_RegisteredNetwork_ProcessStatus_NonePendingImmediately instead (equivalent)") = 0,
- // Should call again, there is more workload to process.
- Baselib_RegisteredNetwork_ProcessStatus_Pending = 1,
- } Baselib_RegisteredNetwork_ProcessStatus;
- BASELIB_ENUM_ENSURE_ABI_COMPATIBILITY(Baselib_RegisteredNetwork_ProcessStatus);
- // Processes the receive queue on a socket.
- //
- // Needs to be called periodically to ensure requests are processed.
- // You should call this in loop until either your time budget is exceed or the function returns false.
- //
- // Platforms emulating RIO behavior with sockets, perform one receive per call until there are no more receive requests in the queue.
- // Requests failed due to empty socket receive buffer are requeued and processed at the next call to Baselib_RegisteredNetwork_Socket_UDP_ProcessRecv.
- // In that case Baselib_RegisteredNetwork_ProcessStatus_NonePendingImmediately is returned since an immediate retry will not have any effect.
- //
- // Possible error codes:
- // - InvalidArgument: if socket is invalid
- //
- // \returns Baselib_RegisteredNetwork_ProcessStatus_Pending if there is more workload to process immediately, Baselib_RegisteredNetwork_ProcessStatus_NonePendingImmediately if otherwise
- BASELIB_API Baselib_RegisteredNetwork_ProcessStatus Baselib_RegisteredNetwork_Socket_UDP_ProcessRecv(
- Baselib_RegisteredNetwork_Socket_UDP socket,
- Baselib_ErrorState* errorState
- );
- // Processes the send queue on a socket.
- //
- // Needs to be called periodically to ensure requests are processed.
- // You should call this in loop until either your time budget is exceed or the function returns false.
- //
- // Platforms emulating RIO behavior with sockets, perform one send per call until there are no more send requests in the queue.
- // Requests failed due to full socket send buffer are requeued processed at the next call to Baselib_RegisteredNetwork_Socket_UDP_ProcessSend.
- // In that case Baselib_RegisteredNetwork_ProcessStatus_NonePendingImmediately is returned since an immediate retry will not have any effect.
- //
- // Possible error codes:
- // - InvalidArgument: if socket is invalid
- //
- // \returns Baselib_RegisteredNetwork_ProcessStatus_Pending if there is more workload to process immediately, Baselib_RegisteredNetwork_ProcessStatus_NonePendingImmediately if otherwise
- BASELIB_API Baselib_RegisteredNetwork_ProcessStatus Baselib_RegisteredNetwork_Socket_UDP_ProcessSend(
- Baselib_RegisteredNetwork_Socket_UDP socket,
- Baselib_ErrorState* errorState
- );
- // Status of a recv/send completion queue.
- typedef enum Baselib_RegisteredNetwork_CompletionQueueStatus
- {
- // No results are ready for dequeing.
- Baselib_RegisteredNetwork_CompletionQueueStatus_NoResultsAvailable = 0,
- // Results are available for dequeing.
- Baselib_RegisteredNetwork_CompletionQueueStatus_ResultsAvailable = 1,
- } Baselib_RegisteredNetwork_CompletionQueueStatus;
- BASELIB_ENUM_ENSURE_ABI_COMPATIBILITY(Baselib_RegisteredNetwork_CompletionQueueStatus);
- // Wait until results appears for a previously scheduled receive.
- //
- // \param timeoutInMilliseconds Wait timeout.
- //
- // Possible error codes:
- // - InvalidArgument: if socket is invalid
- //
- // \returns Baselib_RegisteredNetwork_CompletionQueueStatus_ResultsAvailable if results are available for dequeue, Baselib_RegisteredNetwork_CompletionQueueStatus_NoResultsAvailable otherwise
- BASELIB_API Baselib_RegisteredNetwork_CompletionQueueStatus Baselib_RegisteredNetwork_Socket_UDP_WaitForCompletedRecv(
- Baselib_RegisteredNetwork_Socket_UDP socket,
- uint32_t timeoutInMilliseconds,
- Baselib_ErrorState* errorState
- );
- // Wait until results appears for a previously scheduled send.
- //
- // \param timeoutInMilliseconds Wait timeout.
- //
- // Possible error codes:
- // - InvalidArgument: if socket is invalid
- //
- // \returns Baselib_RegisteredNetwork_CompletionQueueStatus_ResultsAvailable if results are available for dequeue, Baselib_RegisteredNetwork_CompletionQueueStatus_NoResultsAvailable otherwise
- BASELIB_API Baselib_RegisteredNetwork_CompletionQueueStatus Baselib_RegisteredNetwork_Socket_UDP_WaitForCompletedSend(
- Baselib_RegisteredNetwork_Socket_UDP socket,
- uint32_t timeoutInMilliseconds,
- Baselib_ErrorState* errorState
- );
- // Dequeue receive result.
- //
- // \param results Results array. No-op if null.
- // \param resultsCount Amount of elements in results array. No-op if zero.
- //
- // If you're calling this method on multiple threads for the same completion queue in parallel, it may spuriously return 0.
- //
- // Possible error codes:
- // - InvalidArgument: if socket is invalid
- //
- // \returns number of dequeued entries
- BASELIB_API uint32_t Baselib_RegisteredNetwork_Socket_UDP_DequeueRecv(
- Baselib_RegisteredNetwork_Socket_UDP socket,
- Baselib_RegisteredNetwork_CompletionResult results[],
- uint32_t resultsCount,
- Baselib_ErrorState* errorState
- );
- // Dequeue send result.
- //
- // \param results Results array. No-op if null.
- // \param resultsCount Amount of elements in results array. No-op if zero.
- //
- // If you're calling this method on multiple threads for the same completion queue in parallel, it may spuriously return 0.
- //
- // Possible error codes:
- // - InvalidArgument: if socket is invalid
- //
- // \returns number of dequeued entries
- BASELIB_API uint32_t Baselib_RegisteredNetwork_Socket_UDP_DequeueSend(
- Baselib_RegisteredNetwork_Socket_UDP socket,
- Baselib_RegisteredNetwork_CompletionResult results[],
- uint32_t resultsCount,
- Baselib_ErrorState* errorState
- );
- // Get bind address of udp socket.
- //
- // \param socket Socket to be used.
- // \param dstAddress Pointer to address to write data to.
- //
- // Possible error codes:
- // - InvalidArgument: if socket is invalid or if dstAddress is null
- BASELIB_API void Baselib_RegisteredNetwork_Socket_UDP_GetNetworkAddress(
- Baselib_RegisteredNetwork_Socket_UDP socket,
- Baselib_NetworkAddress* dstAddress,
- Baselib_ErrorState* errorState
- );
- // Closes UDP socket.
- //
- // Passing an invalid socket handle result in a no-op.
- //
- // \param socket Socket to be closed.
- BASELIB_API void Baselib_RegisteredNetwork_Socket_UDP_Close(
- Baselib_RegisteredNetwork_Socket_UDP socket
- );
- // ------------------------------------------------------------------------------------------------
- #ifdef __cplusplus
- }
- #endif
|