/*! * \mainpage UDPConnection * \ref UDPC.h * * To use this library, it must be compiled. Only the \ref UDPC.h header is * necessary as UDPC_Defines.hpp is only meant to be used internally by UDPC. */ /*! * \file UDPC.h * \brief Public API for UDPConnection * * Note that all functions are thread-safe unless mentioned otherwise in the * function's documentation. */ #ifndef UDPC_CONNECTION_H #define UDPC_CONNECTION_H #ifndef DOXYGEN_SHOULD_SKIP_THIS // Determine platform macros # define UDPC_PLATFORM_WINDOWS 1 # define UDPC_PLATFORM_MAC 2 # define UDPC_PLATFORM_LINUX 3 # define UDPC_PLATFORM_UNKNOWN 0 # if defined _WIN32 # define UDPC_PLATFORM UDPC_PLATFORM_WINDOWS # elif defined __APPLE__ # define UDPC_PLATFORM UDPC_PLATFORM_MAC # elif defined __linux__ # define UDPC_PLATFORM UDPC_PLATFORM_LINUX # else # define UDPC_PLATFORM UDPC_PLATFORM_UNKNOWN # endif #endif // DOXYGEN_SHOULD_SKIP_THIS // OS-based networking macros #if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS # include # ifdef UDPC_PLATFORM_MINGW # include # include # else # include # include # endif # ifndef DOXYGEN_SHOULD_SKIP_THIS # define UDPC_CLEANUPSOCKET(x) closesocket(x) # define UDPC_SOCKETTYPE SOCKET # define UDPC_IPV6_SOCKADDR_TYPE SOCKADDR_IN6 # define UDPC_IPV6_ADDR_TYPE IN6_ADDR # define UDPC_IPV6_ADDR_SUB(addr) addr.u.Byte # define UDPC_SOCKET_RETURN_ERROR(socket) (socket == INVALID_SOCKET) # endif // DOXYGEN_SHOULD_SKIP_THIS #elif UDPC_PLATFORM == UDPC_PLATFORM_MAC || UDPC_PLATFORM == UDPC_PLATFORM_LINUX # include # include # include # include # ifndef DOXYGEN_SHOULD_SKIP_THIS # define UDPC_CLEANUPSOCKET(x) close(x) # define UDPC_SOCKETTYPE int # define UDPC_IPV6_SOCKADDR_TYPE struct sockaddr_in6 # define UDPC_IPV6_ADDR_TYPE struct in6_addr # define UDPC_IPV6_ADDR_SUB(addr) addr.s6_addr # define UDPC_SOCKET_RETURN_ERROR(socket) (socket <= 0) # endif // DOXYGEN_SHOULD_SKIP_THIS #else # ifndef DOXYGEN_SHOULD_SKIP_THIS # define UDPC_CLEANUPSOCKET(x) ((void)0) # endif // DOXYGEN_SHOULD_SKIP_THIS #endif // other defines /// The maximum size of a UDP packet #define UDPC_PACKET_MAX_SIZE 8192 #define UDPC_DEFAULT_PROTOCOL_ID 1357924680 // 0x50f04948 #ifndef DOXYGEN_SHOULD_SKIP_THIS // other defines continued # ifndef UDPC_LIBSODIUM_ENABLED # ifndef crypto_sign_PUBLICKEYBYTES # define crypto_sign_PUBLICKEYBYTES 1 # endif # ifndef crypto_sign_SECRETKEYBYTES # define crypto_sign_SECRETKEYBYTES 1 # endif # ifndef crypto_sign_BYTES # define crypto_sign_BYTES 1 # endif # endif # if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS # define UDPC_EXPORT __declspec(dllexport) # else # define UDPC_EXPORT # endif #endif // DOXYGEN_SHOULD_SKIP_THIS #ifdef __cplusplus # include extern "C" { #else # include #endif /// Opaque struct handle to Context struct UDPC_Context; typedef struct UDPC_Context *UDPC_HContext; typedef enum UDPC_EXPORT UDPC_LoggingType { /// Does not log anything UDPC_SILENT, /// Only log errors UDPC_ERROR, /// Log errors and warnings UDPC_WARNING, /// Log errors, warnings, and info UDPC_INFO, /// Log errors, warning, info, and verbose UDPC_VERBOSE, /// Log all possible types of messages UDPC_DEBUG } UDPC_LoggingType; /// Note auth policy will only take effect if public key verification of packets /// is enabled (if libsodium is enabled). typedef enum UDPC_EXPORT UDPC_AuthPolicy { /// All peers will not be denied regardless of use of public key verification UDPC_AUTH_POLICY_FALLBACK=0, /// Only peers with public key verification will be allowed UDPC_AUTH_POLICY_STRICT, // Used internally to get max size of enum UDPC_AUTH_POLICY_SIZE } UDPC_AuthPolicy; /*! * \brief Data identifying a peer via addr, port, and scope_id * * This struct needn't be used directly; use UDPC_create_id(), * UDPC_create_id_full(), UDPC_create_id_anyaddr(), or UDPC_create_id_easy() to * create one. This struct does not hold dynamic data, so there is no need to * free it. */ typedef struct UDPC_EXPORT UDPC_ConnectionId { UDPC_IPV6_ADDR_TYPE addr; uint32_t scope_id; uint16_t port; } UDPC_ConnectionId; /*! * \brief Data representing a received/sent packet * * If \ref data is NULL or \ref dataSize is 0, then this packet is invalid. * * \warning This struct must be free'd with a call to * \ref UDPC_free_PacketInfo_ptr or \ref UDPC_free_PacketInfo to avoid a memory * leak. */ typedef struct UDPC_EXPORT UDPC_PacketInfo { /*! * A char array of size \ref dataSize. Will be NULL if this UDPC_PacketInfo * is invalid. */ // id is stored at offset 8, size 4 (uint32_t) even for "empty" PktInfos char *data; /*! * \brief Flags indication some additional information about the received * packet. * * The following list indicates what each used bit in \p flags refers to. * - 0x1: Is an initiate-connection packet * - 0x2: Is a ping packet * - 0x4: Is a packet that will not be re-sent if not received * - 0x8: Is a packet that was re-sent */ uint32_t flags; /*! * \brief The packet's id. * * Packets start with id = 0, and will wrap around. * This can be used to determine specifically how out of order a packet may * be. */ uint32_t id; /*! * \brief The size in bytes of the received packet's data inside the \ref data * pointer member variable. * * UDPC does not return an empty packet when calling UDPC_get_received(), so * in such a packet dataSize shouldn't be zero. (UDPC only stores received * packets that do have a payload.) This means that if this variable is 0, * then this UDPC_PacketInfo is invalid. */ uint16_t dataSize; uint16_t rtt; /// The \ref UDPC_ConnectionId of the sender UDPC_ConnectionId sender; /// The \ref UDPC_ConnectionId of the receiver UDPC_ConnectionId receiver; } UDPC_PacketInfo; /*! * \brief An enum describing the type of event. * * Note that only the following values will be presented when using * UDPC_get_event() * - UDPC_ET_NONE: No events have ocurred * - UDPC_ET_CONNECTED: A peer has initiated a connection * - UDPC_ET_DISCONNECTED: A peer has disconnected * - UDPC_ET_FAIL_CONNECT: Failed to establish a connection to server peer * - UDPC_ET_GOOD_MODE: The connection has switched to "good mode" * - UDPC_ET_BAD_MODE: The connection has switched to "bad mode" * * The other unmentioned enum values are used internally, and should never be * returned in a call to UDPC_get_event(). * * All events returned by UDPC_get_event() will have set the member variable * \p conId in the UDPC_Event which refers to the peer with which the event * ocurred. */ typedef enum UDPC_EXPORT UDPC_EventType { UDPC_ET_NONE, UDPC_ET_REQUEST_CONNECT, UDPC_ET_REQUEST_DISCONNECT, UDPC_ET_CONNECTED, UDPC_ET_DISCONNECTED, UDPC_ET_FAIL_CONNECT, UDPC_ET_GOOD_MODE, UDPC_ET_BAD_MODE } UDPC_EventType; /*! * \brief A struct containing information related to the type of event * * Note that instances of this struct received from a call to UDPC_get_event() * will not store any useful data in its union member variable \p v (it will * only be used internally). * Thus, all events received through a call to UDPC_get_event() will contain a * valid UDPC_ConnectionId \p conId that identifies the peer that the event is * referring to. */ typedef struct UDPC_EXPORT UDPC_Event { UDPC_EventType type; UDPC_ConnectionId conId; union Value { int dropAllWithAddr; int enableLibSodium; } v; } UDPC_Event; /*! * \brief Creates an UDPC_ConnectionId with the given addr and port * * port should be in native byte order (not network/big-endian). This means that * there is no need to convert the 16-bit value to network byte order, this will * be done automatically by this library when necessary (without modifying the * value in the used UDPC_ConnectionId). * * \return An initialized UDPC_ConnectionId */ UDPC_EXPORT UDPC_ConnectionId UDPC_create_id(UDPC_IPV6_ADDR_TYPE addr, uint16_t port); /*! * \brief Creates an UDPC_ConnectionId with the given addr, scope_id, and port * * port should be in native byte order (not network/big-endian). * * \return An initialized UDPC_ConnectionId */ UDPC_EXPORT UDPC_ConnectionId UDPC_create_id_full(UDPC_IPV6_ADDR_TYPE addr, uint32_t scope_id, uint16_t port); /*! * \brief Creates an UDPC_ConnectionId with the given port * * The address contained in the returned UDPC_ConnectionId will be zeroed out * (the "anyaddr" address). * port should be in native byte order (not network/big-endian). * * \return An initialized UDPC_ConnectionId */ UDPC_EXPORT UDPC_ConnectionId UDPC_create_id_anyaddr(uint16_t port); /*! * \brief Creates an UDPC_ConnectionId with the given addr string and port * * The address string should be a valid ipv6 or ipv4 address. (If an ipv4 * address is given, the internal address of the returned UDPC_ConnectionId will * be ipv4-mapped ipv6 address.) * port should be in native byte order (not network/big-endian). * * \return An initialized UDPC_ConnectionId */ UDPC_EXPORT UDPC_ConnectionId UDPC_create_id_easy(const char *addrString, uint16_t port); UDPC_EXPORT UDPC_ConnectionId UDPC_create_id_hostname(const char *hostname, uint16_t port); /*! * \brief Creates an UDPC_HContext that holds state for connections * * \param listenId The addr and port to listen on (contained in a * UDPC_ConnectionId) * \param isClient Whether or not this instance is a client or a server * \param isUsingLibsodium Set to non-zero if libsodium verification of packets * should be enabled (fails if libsodium support was not compiled) * * UDPC_is_valid_context() may be used to check if the context was successfully * created. * * \warning The received UDPC_HContext must be freed with a call to UDPC_destroy(). * * \note This function creates a context that does not use a separate thread to * call update periodically. You must call \ref UDPC_update() periodically, * enable threaded update with \ref UDPC_enable_threaded_update or \ref * UDPC_enable_threaded_update_ms, or use \ref UDPC_init_threaded_update or * \ref UDPC_init_threaded_update_ms instead of \ref UDPC_init . * * \return A UDPC context */ UDPC_EXPORT UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient, int isUsingLibsodium); /*! * \brief Creates an UDPC_HContext that holds state for connections that * auto-updates via a thread. * * By default, the update interval is set to 8 milliseconds. * * \param listenId The addr and port to listen on (contained in a * UDPC_ConnectionId) * \param isClient Whether or not this instance is a client or a server * \param isUsingLibsodium Set to non-zero if libsodium verification of packets * should be enabled (fails if libsodium support was not compiled) * * UDPC_is_valid_context() may be used to check if the context was successfully * created. * * \warning The received UDPC_HContext must be freed with a call to UDPC_destroy(). * * \return A UDPC context */ UDPC_EXPORT UDPC_HContext UDPC_init_threaded_update( UDPC_ConnectionId listenId, int isClient, int isUsingLibsodium); /*! * \brief Creates an UDPC_HContext that holds state for connections that * auto-updates via a thread at a specified interval. * * \param listenId The addr and port to listen on (contained in a * UDPC_ConnectionId) * \param isClient Whether or not this instance is a client or a server * \param updateMS The interval to update at in milliseconds (clamped at a * minimum of 4 ms and a maximum of 333 ms) * \param isUsingLibsodium Set to non-zero if libsodium verification of packets * should be enabled (fails if libsodium support was not compiled) * * UDPC_is_valid_context() may be used to check if the context was successfully * created. * * \warning The received UDPC_HContext must be freed with a call to UDPC_destroy(). * * \return A UDPC context */ UDPC_EXPORT UDPC_HContext UDPC_init_threaded_update_ms( UDPC_ConnectionId listenId, int isClient, int updateMS, int isUsingLibsodium); /*! * \brief Enables auto updating on a separate thread for the given UDPC_HContext * * By default, the update interval is set to 8 milliseconds. * * \param ctx The context to enable auto updating for * \return non-zero if auto updating is enabled. If the context already had auto * updating enabled, this function will return zero. */ UDPC_EXPORT int UDPC_enable_threaded_update(UDPC_HContext ctx); /*! * \brief Enables auto updating on a separate thread for the given UDPC_HContext * with the specified update interval * * \param ctx The context to enable auto updating for * \param updateMS The interval to update at in milliseconds (clamped at a * minimum of 4 ms and a maximum of 333 ms) * \return non-zero if auto updating is enabled. If the context already had auto * updating enabled, this function will return zero. */ UDPC_EXPORT int UDPC_enable_threaded_update_ms(UDPC_HContext ctx, int updateMS); /*! * \brief Disables auto updating on a separate thread for the given * UDPC_HContext * * \param ctx The context to disable auto updating for * \return non-zero if auto updating is disabled. If the context already had * auto updating disabled, this function will return zero. */ UDPC_EXPORT int UDPC_disable_threaded_update(UDPC_HContext ctx); /*! * \brief Checks if the given UDPC_HContext is valid (successfully initialized) * * \return non-zero if the given context is valid */ UDPC_EXPORT int UDPC_is_valid_context(UDPC_HContext ctx); /*! * \brief Cleans up the UDPC_HContext * * If auto updating was enabled for the given context, it will gracefully stop * the thread before cleaning up the context. * * \warning This function must be called after a UDPC_HContext is no longer used * to avoid memory leaks. */ UDPC_EXPORT void UDPC_destroy(UDPC_HContext ctx); /*! * \brief Updates the context * * Updating consists of: * - Checking if peers have timed out * - Handling requests to connect to server peers as a client * - Sending packets to connected peers * - Receiving packets from connected peers * - Calculating round-trip-time (RTT) to peers * - Checking if a peer has not received a packet and queuing that packet to be * resent (this is done by using an ack) * * If auto updating was enabled for the context, then there is no need to call * this function. * * Previously, update would only receive one packet per call to update. Now, * each individual call to update will process all packets that have been * received but haven't been processed yet. */ UDPC_EXPORT void UDPC_update(UDPC_HContext ctx); /*! * \brief Initiate a connection to a server peer * * Note that this function does nothing on a server context. * * \param ctx The context to initiate a connection from * \param connectionId The server peer to initiate a connection to * \param enableLibSodium If packet headers should be verified with the server * peer (Fails if UDPC was not compiled with libsodium support) */ UDPC_EXPORT void UDPC_client_initiate_connection( UDPC_HContext ctx, UDPC_ConnectionId connectionId, int enableLibSodium); /*! * \brief Queues a packet to be sent to the specified peer * * Note that there must already be an established connection with the peer. If * a packet is queued for a peer that is not connected, it will be dropped and * logged with log-level warning. A client can establish a connection to a * server peer via a call to UDPC_client_initiate_connection() or * UDPC_client_initiate_connection_pk(). A server must receive an * initiate-connection-packet from a client to establish a connection (sent by * previously mentioned UDPC_client_initiate_* functions). * * \param ctx The context to send a packet on * \param destinationId The peer to send a packet to * \param isChecked Set to non-zero if the packet should be re-sent if the peer * doesn't receive it * \param data A pointer to data to be sent in a packet * \param size The size in bytes of the data to be sent */ UDPC_EXPORT void UDPC_queue_send(UDPC_HContext ctx, UDPC_ConnectionId destinationId, int isChecked, const void *data, uint32_t size); /*! * \brief Gets the size of the data structure holding queued packets * * Note that a UDPC context holds a different data structure per established * connection that holds a limited amount of packets to send. If a connection's * queue is full, it will not be removed from the main queue that this function * (and UDPC_queue_send()) uses. The queue that this function refers to does not * have an imposed limit as it is implemented as a thread-safe linked list (data * is dynamically stored on the heap) and access to this data structure is * faster than accessing a connection's internal queue. Also note that this * queue holds packets for all connections this context maintains. Thus if one * connection has free space, then it may partially remove packets only destined * for that connection from the queue this function refers to. * * \return The size of the queue */ UDPC_EXPORT unsigned long UDPC_get_queue_send_current_size(UDPC_HContext ctx); /*! * \brief Gets the size of a connection's queue of queued packets * * Note that a UDPC context holds a queue per established connection that holds * a limited amount of packets to send. This function checks a connection's * internal queue, but must do so after locking an internal mutex (a call to * UDPC_update() will lock this mutex, regardless of whether or not the context * is using threaded update). * * If \p exists is a non-null pointer to an \p int, and a connection to a peer * identified by \p id exists, then the value of \p exists will be set to * non-zero, otherwise a non-existing peer will set the value of \p exists to * zero. * * \return The size of a connection's queue */ UDPC_EXPORT unsigned long UDPC_get_queued_size(UDPC_HContext ctx, UDPC_ConnectionId id, int *exists); /*! * \brief Gets the size limit of a connection's queue of queued packets * * Note that a call to this function does not use any locks, as the limit is * known at compile time and is the same for all UDPC connections. * * \return The size limit of a connection's queue */ UDPC_EXPORT unsigned long UDPC_get_max_queued_size(); /*! * \brief Set whether or not the UDPC context will accept new connections * \param ctx The UDPC context * \param isAccepting Set to non-zero to accept connections * \return The previous setting (1 if accepting, 0 if not) */ UDPC_EXPORT int UDPC_set_accept_new_connections(UDPC_HContext ctx, int isAccepting); /*! * \brief Drops an existing connection to a peer * * Note that UDPC will send a disconnect packet to the peer before removing * the internal connection data handling the connection to that peer. * * \param ctx The UDPC context * \param connectionId The identifier of the peer to disconnect from * \param dropAllWithAddr Set to non-zero to drop all peers with the ip address * specified in \p connectionId */ UDPC_EXPORT void UDPC_drop_connection(UDPC_HContext ctx, UDPC_ConnectionId connectionId, int dropAllWithAddr); /*! * \brief Checks if a connection exists to the peer identified by the given * \p connectionId * * \param ctx The UDPC context * \param connectionId The identifier for a peer * * \return non-zero if a connection to the peer exists */ UDPC_EXPORT int UDPC_has_connection(UDPC_HContext ctx, UDPC_ConnectionId connectionId); /*! * \brief Gets a dynamically allocated array of connected peers' identifiers * * Note that an additional element is appended to the array that is initialized * with all fields to zero. * * \warning One must call UDPC_free_list_connected() with the returned array to * clean up data to avoid a memory leak * * \param ctx The UDPC context * \param size Pointer to an unsigned int to set the size of the returned array * (set to NULL to not get a size) * \return A dynamically allocated array of identifiers */ UDPC_EXPORT UDPC_ConnectionId* UDPC_get_list_connected(UDPC_HContext ctx, unsigned int *size); /*! * \brief Cleans up a dynamically allocated array of connected peers' identifiers * \param list The array to clean up */ UDPC_EXPORT void UDPC_free_list_connected(UDPC_ConnectionId *list); /*! * \brief Gets the protocol id of the UDPC context * * UDPC uses the protocol id by prefixing every sent packet with it. Other UDPC * instances will only accept packets with the same protocol id. * * One can use UDPC_set_protocol_id() to change it. * * \param ctx The UDPC context * \return The protocol id of the given UDPC context */ UDPC_EXPORT uint32_t UDPC_get_protocol_id(UDPC_HContext ctx); /*! * \brief Sets the protocol id of the UDPC context * * UDPC uses the protocol id by prefixing every sent packet with it. Other UDPC * instances will only accept packets with the same protocol id. * * \param ctx The UDPC context * \param id The new id to use as the protocol id * \return The previous protocol id of the UDPC context */ UDPC_EXPORT uint32_t UDPC_set_protocol_id(UDPC_HContext ctx, uint32_t id); /*! * \brief Gets the logging type of the UDPC context * * See \ref UDPC_LoggingType for possible values. * * \param ctx The UDPC context * \return The logging type of the UDPC context */ UDPC_EXPORT UDPC_LoggingType UDPC_get_logging_type(UDPC_HContext ctx); /*! * \brief Sets the logging type of the UDPC context * * See \ref UDPC_LoggingType for possible values. * * \param ctx The UDPC context * \param loggingType The logging type to set to * \return The previously set logging type */ UDPC_EXPORT UDPC_LoggingType UDPC_set_logging_type(UDPC_HContext ctx, UDPC_LoggingType loggingType); /*! * \brief Returns non-zero if the UDPC context will record events * * Events that have ocurred can by polled by calling UDPC_get_event() * * \param ctx The UDPC context * \return non-zero if receiving events */ UDPC_EXPORT int UDPC_get_receiving_events(UDPC_HContext ctx); /*! * \brief Sets whether or not UDPC will record events * * Events that have ocurred can by polled by calling UDPC_get_event() * * \param ctx The UDPC context * \param isReceivingEvents Set to non-zero to receive events * \return non-zero if UDPC was previously receiving events */ UDPC_EXPORT int UDPC_set_receiving_events(UDPC_HContext ctx, int isReceivingEvents); /*! * \brief Gets a recorded event * * See \ref UDPC_EventType for possible types of a UDPC_Event. * * \param ctx The UDPC context * \param remaining Pointer to set the number of remaining events that can be * returned * \return An UDPC_Event (will be of type UDPC_ET_NONE if there are no more * events) */ UDPC_EXPORT UDPC_Event UDPC_get_event(UDPC_HContext ctx, unsigned long *remaining); /*! * \brief Get a received packet from a given UDPC context. * * \warning The received packet (if valid) must be free'd with a call to * \ref UDPC_free_PacketInfo_ptr or \ref UDPC_free_PacketInfo to avoid a memory * leak. */ UDPC_EXPORT UDPC_PacketInfo UDPC_get_received(UDPC_HContext ctx, unsigned long *remaining); /*! * \brief Frees a UDPC_PacketInfo. * * Internally, the member variable \ref UDPC_PacketInfo::data will be free'd. * \ref UDPC_free_PacketInfo_ptr is safer to use than this function, as it * also zeros out the relevant data to avoid double frees. */ UDPC_EXPORT void UDPC_free_PacketInfo(UDPC_PacketInfo pInfo); /*! * \brief Frees a UDPC_PacketInfo. * * This is a safer alternative to \ref UDPC_free_PacketInfo because it * internally zeroes out the internal pointer and size variables, making it * safe to pass the same ptr multiple times to this function as it avoids a * double free. * * Usage: * \code{.c} * UDPC_PacketInfo pinfo = UDPC_get_received(ctx, NULL); * UDPC_free_PacketInfo_ptr(&pinfo); * UDPC_free_PacketInfo_ptr(&pinfo); // This is safe, no double free. * \endcode */ UDPC_EXPORT void UDPC_free_PacketInfo_ptr(UDPC_PacketInfo *pInfoPtr); /*! * \brief Sets public/private keys used for packet verification * * If keys are not set and packet verification is enabled, for each new * connection new keys will be generated then used. The auto-generated keys * used will be unique per connection. Conversely if keys are set, then new * connections will use the given keys. * * Note that connections established before calling this function will not use * the given keys. * * Note that public key verification will not occur if it is not enabled during * the call to UDPC_init(). * * \return Non-zero if keys were successfully set, zero if context is invalid or * libsodium is not enabled */ UDPC_EXPORT int UDPC_set_libsodium_keys(UDPC_HContext ctx, const unsigned char *sk, const unsigned char *pk); /*! * \brief Sets the public/private keys used for packet verification * * This function is almost identical with UDPC_set_libsodium_keys, except it * will utilize libsodium to generate the associated public key with the given * private key. * * Note that public key verification will not occur if it is not enabled during * the call to UDPC_init(). * * \return Non-zero if keys were successfully set, zero if context is invalid or * libsodium is not enabled */ UDPC_EXPORT int UDPC_set_libsodium_key_easy(UDPC_HContext ctx, const unsigned char *sk); /*! * \brief Removes set keys if any used for packet verification * * Note that public key verification will not occur if it is not enabled during * the call to UDPC_init(). * * \return Zero if context is invalid or libsodium is not enabled */ UDPC_EXPORT int UDPC_unset_libsodium_keys(UDPC_HContext ctx); /*! * \brief Adds a public key to the whitelist * * By default the whitelist is empty and any peer regardless of key will not be * denied connection. * * This function adds one public key to the whitelist. If the whitelist is not * empty, then all peers that do not have the matching public key will be * denied connection. * * Note that public key verification will not occur if it is not enabled during * the call to UDPC_init(). * * \return The size of the whitelist on success, zero otherwise */ UDPC_EXPORT int UDPC_add_whitelist_pk(UDPC_HContext ctx, const unsigned char *pk); /*! * \brief Checks if a public key is in the whitelist * * Note that public key verification will not occur if it is not enabled during * the call to UDPC_init(). * * \return Non-zero if the given public key is in the whitelist */ UDPC_EXPORT int UDPC_has_whitelist_pk(UDPC_HContext ctx, const unsigned char *pk); /*! * \brief Removes a public key from the whitelist * * Note that public key verification will not occur if it is not enabled during * the call to UDPC_init(). * * \return Non-zero if a public key was removed */ UDPC_EXPORT int UDPC_remove_whitelist_pk(UDPC_HContext ctx, const unsigned char *pk); /*! * \brief Clears the public key whitelist * * If the whitelist is empty, then no connections will be denied. * * If there are keys in the whitelist, then new connections will only be allowed * if the peer uses a public key in the whitelist. * * Note that public key verification will not occur if it is not enabled during * the call to UDPC_init(). * * \return Zero if the context is invalid or libsodium is not enabled, non-zero * if the whitelist was successfully cleared */ UDPC_EXPORT int UDPC_clear_whitelist(UDPC_HContext ctx); /*! * \brief Gets how peers are handled regarding public key verification * * If libsodium is enabled and the auth policy is "strict", then peers * attempting to connect will be denied if they do not have public key * verification enabled. Otherwise if the auth policy is "fallback", then peers * will not be denied a connection regardless of whether or not they use * public key verification of packets. * * Note that public key verification will not occur if it is not enabled during * the call to UDPC_init(). * * \return The current auth policy (see \ref UDPC_AuthPolicy) , or zero on fail */ UDPC_EXPORT int UDPC_get_auth_policy(UDPC_HContext ctx); /*! * \brief Sets how peers are handled regarding public key verification * * If libsodium is enabled and the auth policy is "strict", then peers * attempting to connect will be denied if they do not have public key * verification enabled. Otherwise if the auth policy is "fallback", then peers * will not be denied a connection regardless of whether or not they use * public key verification of packets. * * Note that public key verification will not occur if it is not enabled during * the call to UDPC_init(). * * \return The previous auth policy (see \ref UDPC_AuthPolicy), or zero on fail */ UDPC_EXPORT int UDPC_set_auth_policy(UDPC_HContext ctx, int value); /*! * \brief Returns the result of UDPC_atostr() with the addr data inside the * given UDPC_ConnectionId instance. */ UDPC_EXPORT const char *UDPC_atostr_cid(UDPC_HContext ctx, UDPC_ConnectionId connectionId); /*! * \brief Returns a pointer to a null-terminated address string derived from * the given address. * * \warning You must NOT free the pointer returned by this function, as it * refers to a buffer allocated by the UDPC Context specifically to hold address * strings. * * The current implementation uses a buffer that can hold up to 32 address * strings at once. When this function is called, an internal counter is used * to pick the next spot in the buffer to store the address string and return * its pointer. This buffer is used like a "ring-buffer"; when the end of the * buffer is reached, the counter wraps-around to the beginning of the buffer, * which has the effect of overwriting the oldest addr-string entry on every * invocation (if this function was called more than 32 times). * * This function is mostly thread-safe. If this function is called more than 32 * times at once in parallel, some of the strings in the buffer may be * clobbered by other invocations of this function as a race-condition, and may * be considered undefined behavior. * * It may be easier to use UDPC_atostr_cid(). * * UDPC internally uses UDPC_atostr() for logging. This means that while UDPC * is running, a string created with UDPC_atostr() may be overwritten * eventually by UDPC. To avoid this situation, UDPC_atostr_unsafe() or * UDPC_atostr_unsafe_cid() may be used as the ptr returned by it will not be * overwritten by UDPC as time passes. */ UDPC_EXPORT const char *UDPC_atostr(UDPC_HContext ctx, UDPC_IPV6_ADDR_TYPE addr); /*! * \brief Similar to UPDC_atostr(), but the returned ptr must be free'd. * * \warning The returned pointer must be freed with free(), or * UDPC_atostr_unsafe_free(), or UDPC_atostr_unsafe_free_ptr(). * * UDPC internally uses UDPC_atostr() for logging. This means that while UDPC * is running, a string created with UDPC_atostr() may be overwritten * eventually by UDPC. To avoid this situation, UDPC_atostr_unsafe() or * UDPC_atostr_unsafe_cid() may be used as the ptr returned by it will not be * overwritten by UDPC as time passes. * * It may be easier to use UDPC_atostr_unsafe_cid(). */ UDPC_EXPORT const char *UDPC_atostr_unsafe(UDPC_IPV6_ADDR_TYPE addr); /*! * \brief Similar to UPDC_atostr(), but the returned ptr must be free'd. * * \warning The returned pointer must be freed with free(), or * UDPC_atostr_unsafe_free(), or UDPC_atostr_unsafe_free_ptr(). * * UDPC internally uses UDPC_atostr() for logging. This means that while UDPC * is running, a string created with UDPC_atostr() may be overwritten * eventually by UDPC. To avoid this situation, UDPC_atostr_unsafe() or * UDPC_atostr_unsafe_cid() may be used as the ptr returned by it will not be * overwritten by UDPC as time passes. */ UDPC_EXPORT const char *UDPC_atostr_unsafe_cid(UDPC_ConnectionId cid); /*! * \brief Free an addr string created with UDPC_atostr_unsafe(). */ UDPC_EXPORT void UDPC_atostr_unsafe_free(const char *addrBuf); /*! * \brief Free an addr string created with UDPC_atostr_unsafe() and zeroes the * pointer. * * \code{.c} * UDPC_ConnectionId aConnectionId = ...; * const char *addrString = UDPC_atostr_unsafe_cid(aConnectionId); * // Use addrString somewhere... * UDPC_atostr_unsafe_free_ptr(&addrString); * \endcode */ UDPC_EXPORT void UDPC_atostr_unsafe_free_ptr(const char **addrBuf); // ============================================================================= // Helpers /// addrStr must be a valid ipv6 address or a valid ipv4 address UDPC_EXPORT UDPC_IPV6_ADDR_TYPE UDPC_strtoa(const char *addrStr); UDPC_EXPORT UDPC_IPV6_ADDR_TYPE UDPC_strtoa_link(const char *addrStr, uint32_t *linkId_out); UDPC_EXPORT UDPC_IPV6_ADDR_TYPE UDPC_a4toa6(uint32_t a4_be); UDPC_EXPORT int UDPC_is_big_endian(); /*! * \brief Converts a 16-bit int into/from network byte order (big endian). * * Typically, if one is sending integers/floats through UDPC, it is strongly * recommended to use the UDPC_no* family of functions to convert to/back from * network byte order. In other words, the integers/floats should be converted * to network byte order prior to writing it into the buffer to send, and it * should be converted back to native byte order when reading it from the * received buffer. * * Note that on big-endian systems, this function has no effect. However, it is * recommended to use this function as shown so that the endianness of the * system is not a problem. * * \code{.c} * // Sending * uint16_t send_value = 13; * char buffer[2]; * // to network byte order * send_value = UDPC_no16i(send_value); * memcpy(buffer, &value, 2); * // send buffer * * // Receiving * uint16_t receive_value; * memcpy(&receive_value, buffer, 2); * // to local byte order * receive_value = UDPC_no16i(receive_value); * // use receive_value * \endcode * * When using a signed integer: * * \code{.c} * int16_t send_value = 15000; * // network byte order * uint16_t *ptr = (uint16_t*)&send_value; * *ptr = UDPC_no16i(*ptr); * \endcode */ UDPC_EXPORT uint16_t UDPC_no16i(uint16_t i); /*! * \brief Converts a 32-bit int into/from network byte order (big endian). * * Typically, if one is sending integers/floats through UDPC, it is strongly * recommended to use the UDPC_no* family of functions to convert to/back from * network byte order. In other words, the integers/floats should be converted * to network byte order prior to writing it into the buffer to send, and it * should be converted back to native byte order when reading it from the * received buffer. * * Note that on big-endian systems, this function has no effect. However, it is * recommended to use this function as shown so that the endianness of the * system is not a problem. * * \code{.c} * // Sending * uint32_t send_value = 123456; * char buffer[4]; * // to network byte order * send_value = UDPC_no32i(send_value); * memcpy(buffer, &value, 4); * // send buffer * * // Receiving * uint32_t receive_value; * memcpy(&receive_value, buffer, 4); * // to local byte order * receive_value = UDPC_no32i(receive_value); * // use receive_value * \endcode * * When using a signed integer: * * \code{.c} * int32_t send_value = 123456; * // network byte order * uint32_t *ptr = (uint32_t*)&send_value; * *ptr = UDPC_no32i(*ptr); * \endcode */ UDPC_EXPORT uint32_t UDPC_no32i(uint32_t i); /*! * \brief Converts a 64-bit int into/from network byte order (big endian). * * Typically, if one is sending integers/floats through UDPC, it is strongly * recommended to use the UDPC_no* family of functions to convert to/back from * network byte order. In other words, the integers/floats should be converted * to network byte order prior to writing it into the buffer to send, and it * should be converted back to native byte order when reading it from the * received buffer. * * Note that on big-endian systems, this function has no effect. However, it is * recommended to use this function as shown so that the endianness of the * system is not a problem. * * \code{.c} * // Sending * uint64_t send_value = 0xABCDEFABCDEFAAAA; * char buffer[8]; * // to network byte order * send_value = UDPC_no64i(send_value); * memcpy(buffer, &value, 8); * // send buffer * * // Receiving * uint64_t receive_value; * memcpy(&receive_value, buffer, 8); * // to local byte order * receive_value = UDPC_no64i(receive_value); * // use receive_value * \endcode * * When using a signed integer: * * \code{.c} * int64_t send_value = 0x1111222233334444; * // network byte order * uint64_t *ptr = (uint64_t*)&send_value; * *ptr = UDPC_no64i(*ptr); * \endcode */ UDPC_EXPORT uint64_t UDPC_no64i(uint64_t i); /*! * \brief Converts a 32-bit float into/from network byte order (big endian). * * Typically, if one is sending integers/floats through UDPC, it is strongly * recommended to use the UDPC_no* family of functions to convert to/back from * network byte order. In other words, the integers/floats should be converted * to network byte order prior to writing it into the buffer to send, and it * should be converted back to native byte order when reading it from the * received buffer. * * Note that on big-endian systems, this function has no effect. However, it is * recommended to use this function as shown so that the endianness of the * system is not a problem. * * \code{.c} * // Sending * float send_value = 0.123F; * char buffer[4]; * // to network byte order * send_value = UDPC_no32f(send_value); * memcpy(buffer, &value, 4); * // send buffer * * // Receiving * float receive_value; * memcpy(&receive_value, buffer, 4); * // to local byte order * receive_value = UDPC_no32f(receive_value); * // use receive_value * \endcode */ UDPC_EXPORT float UDPC_no32f(float f); /*! * \brief Converts a 64-bit float into/from network byte order (big endian). * * Typically, if one is sending integers/floats through UDPC, it is strongly * recommended to use the UDPC_no* family of functions to convert to/back from * network byte order. In other words, the integers/floats should be converted * to network byte order prior to writing it into the buffer to send, and it * should be converted back to native byte order when reading it from the * received buffer. * * Note that on big-endian systems, this function has no effect. However, it is * recommended to use this function as shown so that the endianness of the * system is not a problem. * * \code{.c} * // Sending * double send_value = 0.123456; * char buffer[8]; * // to network byte order * send_value = UDPC_no64f(send_value); * memcpy(buffer, &value, 8); * // send buffer * * // Receiving * double receive_value; * memcpy(&receive_value, buffer, 8); * // to local byte order * receive_value = UDPC_no64f(receive_value); * // use receive_value * \endcode */ UDPC_EXPORT double UDPC_no64f(double f); #ifdef __cplusplus } #endif #endif