--- /dev/null
+build*/
+compile_commands.json
+*.o
--- /dev/null
+cmake_minimum_required(VERSION 3.7)
+project(UDPConnection)
+
+set(UDPConnection_VERSION 1.0)
+
+set(UDPConnection_SOURCES
+ src/UDPConnection.cpp
+)
+
+set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wpedantic -Wno-missing-braces")
+set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
+set(CMAKE_CXX_FLAGS_RELEASE "-O3 -D NDEBUG")
+
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+ message(STATUS "Setting build type to 'Debug', none was specified.")
+ set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE)
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release")
+endif()
+
+add_library(UDPConnection ${UDPConnection_SOURCES})
+
+set_target_properties(UDPConnection PROPERTIES VERSION ${UDPConnection_VERSION})
+
+target_compile_features(UDPConnection PUBLIC cxx_std_11)
+target_link_libraries(UDPConnection PUBLIC pthread)
+
+if(CMAKE_BUILD_TYPE MATCHES "Debug")
+ set(UDPC_UnitTest_SOURCES
+ src/test/UDPC_UnitTest.cpp)
+ add_executable(UnitTest ${UDPC_UnitTest_SOURCES})
+ target_link_libraries(UnitTest PUBLIC UDPConnection)
+ target_include_directories(UnitTest PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
+
+ set(UDPC_NetworkTest_SOURCES
+ src/test/UDPC_NetworkTest.cpp)
+ add_executable(NetworkTest ${UDPC_NetworkTest_SOURCES})
+ target_link_libraries(NetworkTest PUBLIC UDPConnection)
+ target_include_directories(NetworkTest PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
+endif()
+
+install(TARGETS UDPConnection DESTINATION lib)
+install(FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/UDPConnection.h
+ DESTINATION include)
--- /dev/null
+#ifndef UDPC_DEFINES_HPP
+#define UDPC_DEFINES_HPP
+
+#define UDPC_CONTEXT_IDENTIFIER 0x902F4DB3
+
+#include <cstdint>
+#include <bitset>
+#include <atomic>
+
+#include "UDPConnection.h"
+
+namespace UDPC {
+
+struct Context {
+ Context(bool isThreaded);
+
+ uint_fast32_t _contextIdentifier;
+ /*
+ * 0 - isThreaded
+ */
+ std::bitset<32> flags;
+ std::atomic_bool isAcceptNewConnections;
+ std::atomic_uint32_t protocolID;
+ std::atomic_uint_fast8_t loggingType;
+ char atostrBuf[16];
+}; // struct Context
+
+bool VerifyContext(void *ctx);
+
+} // namespace UDPC
+
+#endif
--- /dev/null
+#include "UDPConnection.h"
+#include "UDPC_Defines.hpp"
+
+UDPC::Context::Context(bool isThreaded) :
+_contextIdentifier(UDPC_CONTEXT_IDENTIFIER),
+flags(),
+isAcceptNewConnections(true),
+protocolID(UDPC_DEFAULT_PROTOCOL_ID),
+#ifndef NDEBUG
+loggingType(INFO)
+#else
+loggingType(WARNING)
+#endif
+{
+ if(isThreaded) {
+ flags.set(0);
+ } else {
+ flags.reset(0);
+ }
+}
+
+bool UDPC::VerifyContext(void *ctx) {
+ if(ctx == nullptr) {
+ return false;
+ }
+ UDPC::Context* c = (UDPC::Context*) ctx;
+ if(c->_contextIdentifier == UDPC_CONTEXT_IDENTIFIER) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void* UDPC_init(uint16_t listenPort, uint32_t listenAddr, int isClient) {
+ UDPC::Context *ctx = new UDPC::Context(false);
+
+ return ctx;
+}
+
+void* UDPC_init_threaded_update(uint16_t listenPort, uint32_t listenAddr, int isClient) {
+ UDPC::Context *ctx = new UDPC::Context(true);
+
+ return ctx;
+}
+
+void UDPC_destroy(void *ctx) {
+ if (UDPC::VerifyContext(ctx)) {
+ delete (UDPC::Context*)ctx;
+ }
+}
+
+void UDPC_update(void *ctx) {
+ if(!UDPC::VerifyContext(ctx)) {
+ return;
+ }
+ UDPC::Context *c = (UDPC::Context*)ctx;
+ if(c->flags.test(0)) {
+ // is threaded, update should not be called
+ return;
+ }
+
+ // TODO impl
+}
+
+int UDPC_get_queue_send_available(void *ctx, uint32_t addr) {
+ if(!UDPC::VerifyContext(ctx)) {
+ return 0;
+ }
+ UDPC::Context *c = (UDPC::Context*)ctx;
+ // TODO impl
+ return 0;
+}
+
+void UDPC_queue_send(void *ctx, uint32_t destAddr, uint16_t destPort, uint32_t isChecked, void *data, uint32_t size) {
+ if(!UDPC::VerifyContext(ctx)) {
+ return;
+ }
+ UDPC::Context *c = (UDPC::Context*)ctx;
+ // TODO impl
+}
+
+int UDPC_set_accept_new_connections(void *ctx, int isAccepting) {
+ if(!UDPC::VerifyContext(ctx)) {
+ return 0;
+ }
+ UDPC::Context *c = (UDPC::Context*)ctx;
+ return c->isAcceptNewConnections.exchange(isAccepting == 0 ? false : true);
+}
+
+int UDPC_drop_connection(void *ctx, uint32_t addr, uint16_t port) {
+ if(!UDPC::VerifyContext(ctx)) {
+ return 0;
+ }
+ UDPC::Context *c = (UDPC::Context*)ctx;
+ // TODO impl
+ return 0;
+}
+
+uint32_t UDPC_set_protocol_id(void *ctx, uint32_t id) {
+ if(!UDPC::VerifyContext(ctx)) {
+ return 0;
+ }
+ UDPC::Context *c = (UDPC::Context*)ctx;
+ return c->protocolID.exchange(id);
+}
+
+UDPC_LoggingType set_logging_type(void *ctx, UDPC_LoggingType loggingType) {
+ if(!UDPC::VerifyContext(ctx)) {
+ return static_cast<UDPC_LoggingType>(0);
+ }
+ UDPC::Context *c = (UDPC::Context*)ctx;
+ return static_cast<UDPC_LoggingType>(c->loggingType.exchange(loggingType));
+}
+
+PacketInfo UDPC_get_received(void *ctx) {
+ if(!UDPC::VerifyContext(ctx)) {
+ return PacketInfo{{0}, 0, 0, 0, 0, 0};
+ }
+ UDPC::Context *c = (UDPC::Context*)ctx;
+ // TODO impl
+ return PacketInfo{{0}, 0, 0, 0, 0, 0};
+}
+
+const char* UDPC_atostr(void *ctx, uint32_t addr) {
+ if(!UDPC::VerifyContext(ctx)) {
+ return nullptr;
+ }
+ UDPC::Context *c = (UDPC::Context*)ctx;
+ int index = 0;
+ for(int x = 0; x < 4; ++x)
+ {
+ unsigned char temp = (addr >> (x * 8)) & 0xFF;
+
+ if(temp >= 100)
+ {
+ c->atostrBuf[index++] = '0' + temp / 100;
+ }
+ if(temp >= 10)
+ {
+ c->atostrBuf[index++] = '0' + ((temp / 10) % 10);
+ }
+ c->atostrBuf[index++] = '0' + temp % 10;
+
+ if(x < 3)
+ {
+ c->atostrBuf[index++] = '.';
+ }
+ }
+ c->atostrBuf[index] = 0;
+
+ return c->atostrBuf;
+}
+
+uint32_t UDPC_strtoa(const char *addrStr) {
+ uint32_t addr = 0;
+ uint32_t temp = 0;
+ uint32_t index = 0;
+ while(*addrStr != 0)
+ {
+ if(*addrStr >= '0' && *addrStr <= '9')
+ {
+ temp *= 10;
+ temp += *addrStr - '0';
+ }
+ else if(*addrStr == '.' && temp <= 0xFF && index < 3)
+ {
+ addr |= (temp << (8 * index++));
+ temp = 0;
+ }
+ else
+ {
+ return 0;
+ }
+ ++addrStr;
+ }
+
+ if(index == 3 && temp <= 0xFF)
+ {
+ addr |= temp << 24;
+ return addr;
+ }
+ else
+ {
+ return 0;
+ }
+}
--- /dev/null
+#ifndef UDPC_CONNECTION_H
+#define UDPC_CONNECTION_H
+
+// 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
+
+// OS-based networking macros
+#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
+ #include <winsock2.h>
+
+ #define CleanupSocket(x) closesocket(x)
+#elif UDPC_PLATFORM == UDPC_PLATFORM_MAC || UDPC_PLATFORM == UDPC_PLATFORM_LINUX
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+
+ #define CleanupSocket(x) close(x)
+#else
+ #define CleanupSocket(x) ((void)0)
+#endif
+
+// other defines
+#define UDPC_PACKET_MAX_SIZE 8192
+#define UDPC_DEFAULT_PROTOCOL_ID 1357924680
+
+#ifdef __cplusplus
+# include <cstdint>
+extern "C" {
+#else
+# include <stdint.h>
+#endif
+
+typedef enum {
+ SILENT,
+ ERROR,
+ WARNING,
+ VERBOSE,
+ INFO
+} UDPC_LoggingType;
+
+typedef struct {
+ char data[UDPC_PACKET_MAX_SIZE];
+ uint16_t dataSize; // zero if invalid
+ uint32_t sender;
+ uint32_t receiver;
+ uint16_t senderPort;
+ uint16_t receiverPort;
+} PacketInfo;
+
+void* UDPC_init(uint16_t listenPort, uint32_t listenAddr, int isClient);
+void* UDPC_init_threaded_update(uint16_t listenPort, uint32_t listenAddr, int isClient);
+
+void UDPC_destroy(void *ctx);
+
+void UDPC_update(void *ctx);
+
+int UDPC_get_queue_send_available(void *ctx, uint32_t addr);
+
+void UDPC_queue_send(void *ctx, uint32_t destAddr, uint16_t destPort, uint32_t isChecked, void *data, uint32_t size);
+
+int UDPC_set_accept_new_connections(void *ctx, int isAccepting);
+
+int UDPC_drop_connection(void *ctx, uint32_t addr, uint16_t port);
+
+uint32_t UDPC_set_protocol_id(void *ctx, uint32_t id);
+
+UDPC_LoggingType set_logging_type(void *ctx, UDPC_LoggingType loggingType);
+
+PacketInfo UDPC_get_received(void *ctx);
+
+const char* UDPC_atostr(void *ctx, uint32_t addr);
+
+uint32_t UDPC_strtoa(const char *addrStr);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null
+int main() {
+}
--- /dev/null
+int main() {
+}