#include "UDPConnection.h"
-UDPC_Context UDPC_init(uint16_t listenPort)
+#include <stdlib.h>
+
+UDPC_Context* UDPC_init(uint16_t listenPort)
{
- UDPC_Context context;
- context.error = 0;
- context.flags = 0;
- context.threadFlags = 0;
+ UDPC_Context *context = malloc(sizeof(UDPC_Context));
+ context->error = UDPC_SUCCESS;
+ context->flags = 0;
+ context->threadFlags = 0;
// create socket
- context.socketHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if(context.socketHandle <= 0)
+ context->socketHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if(context->socketHandle <= 0)
{
- context.socketHandle = 0;
- context.error = UDPCON_ERR_SOCKETFAIL;
+ context->socketHandle = 0;
+ context->error = UDPC_ERR_SOCKETFAIL;
fprintf(stderr, "Failed to create socket\n");
return context;
}
// bind socket
- context.socketInfo.sin_family = AF_INET;
- context.socketInfo.sin_addr.s_addr = INADDR_ANY;
- context.socketInfo.sin_port = listenPort;
+ context->socketInfo.sin_family = AF_INET;
+ context->socketInfo.sin_addr.s_addr = INADDR_ANY;
+ context->socketInfo.sin_port = listenPort;
if(bind(
- context.socketHandle,
- (const struct sockaddr*) &context.socketInfo,
+ context->socketHandle,
+ (const struct sockaddr*) &context->socketInfo,
sizeof(struct sockaddr_in)
) < 0)
{
- context.error = UDPCON_ERR_SOCKETBINDF;
- CleanupSocket(context.socketHandle);
- context.socketHandle = 0;
+ context->error = UDPC_ERR_SOCKETBINDF;
+ CleanupSocket(context->socketHandle);
+ context->socketHandle = 0;
fprintf(stderr, "Failed to bind socket\n");
return context;
}
// set nonblocking on socket
#if UDPC_PLATFORM == UDPC_PLATFORM_MAC || UDPC_PLATFORM == UDPC_PLATFORM_LINUX
int nonblocking = 1;
- if(fcntl(context.socketHandle, F_SETFL, O_NONBLOCK, nonblocking) == -1)
+ if(fcntl(context->socketHandle, F_SETFL, O_NONBLOCK, nonblocking) == -1)
{
#elif UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
DWORD nonblocking = 1;
- if(ioctlsocket(context.socketHandle, FIONBIO, &nonblocking) != 0)
+ if(ioctlsocket(context->socketHandle, FIONBIO, &nonblocking) != 0)
{
#else
{
#endif
- context.error = UDPCON_ERR_SOCKETNONBF;
- CleanupSocket(context.socketHandle);
- context.socketHandle = 0;
+ context->error = UDPC_ERR_SOCKETNONBF;
+ CleanupSocket(context->socketHandle);
+ context->socketHandle = 0;
fprintf(stderr, "Failed to set non-blocking on socket\n");
return context;
}
return context;
}
-UDPC_Context UDPC_init_threaded_update(uint16_t listenPort)
+UDPC_Context* UDPC_init_threaded_update(uint16_t listenPort)
{
- UDPC_Context context = UDPC_init(listenPort);
+ UDPC_Context *context = UDPC_init(listenPort);
- context.error = mtx_init(&context.tCVMtx, mtx_timed);
- if(context.error != thrd_success)
+ context->error = mtx_init(&context->tCVMtx, mtx_timed);
+ if(context->error != thrd_success)
{
- CleanupSocket(context.socketHandle);
- context.socketHandle = 0;
+ CleanupSocket(context->socketHandle);
+ context->socketHandle = 0;
fprintf(stderr, "Failed to create mutex\n");
- context.error = UDPCON_ERR_MTXFAIL;
+ context->error = UDPC_ERR_MTXFAIL;
}
- context.error = 0;
+ context->error = UDPC_SUCCESS;
- context.error = mtx_init(&context.tflagsMtx, mtx_timed);
- if(context.error != thrd_success)
+ context->error = mtx_init(&context->tflagsMtx, mtx_timed);
+ if(context->error != thrd_success)
{
- CleanupSocket(context.socketHandle);
- context.socketHandle = 0;
- mtx_destroy(&context.tCVMtx);
+ CleanupSocket(context->socketHandle);
+ context->socketHandle = 0;
+ mtx_destroy(&context->tCVMtx);
fprintf(stderr, "Failed to create mutex\n");
- context.error = UDPCON_ERR_MTXFAIL;
+ context->error = UDPC_ERR_MTXFAIL;
return context;
}
- context.error = 0;
+ context->error = UDPC_SUCCESS;
- context.error = cnd_init(&context.threadCV);
- if(context.error != thrd_success)
+ context->error = cnd_init(&context->threadCV);
+ if(context->error != thrd_success)
{
- CleanupSocket(context.socketHandle);
- context.socketHandle = 0;
- mtx_destroy(&context.tCVMtx);
- mtx_destroy(&context.tflagsMtx);
+ CleanupSocket(context->socketHandle);
+ context->socketHandle = 0;
+ mtx_destroy(&context->tCVMtx);
+ mtx_destroy(&context->tflagsMtx);
fprintf(stderr, "Failed to create condition variable\n");
- context.error = UDPCON_ERR_CVFAIL;
+ context->error = UDPC_ERR_CVFAIL;
return context;
}
- context.error = 0;
+ context->error = UDPC_SUCCESS;
- context.error = thrd_create(
- &context.threadHandle, UDPC_INTERNAL_threadfn, &context);
- if(context.error != thrd_success)
+ context->error = thrd_create(
+ &context->threadHandle, UDPC_INTERNAL_threadfn, &context);
+ if(context->error != thrd_success)
{
- CleanupSocket(context.socketHandle);
- context.socketHandle = 0;
- mtx_destroy(&context.tCVMtx);
- mtx_destroy(&context.tflagsMtx);
- cnd_destroy(&context.threadCV);
+ CleanupSocket(context->socketHandle);
+ context->socketHandle = 0;
+ mtx_destroy(&context->tCVMtx);
+ mtx_destroy(&context->tflagsMtx);
+ cnd_destroy(&context->threadCV);
fprintf(stderr, "Failed to create thread\n");
- context.error = UDPCON_ERR_THREADFAIL;
+ context->error = UDPC_ERR_THREADFAIL;
return context;
}
- context.error = 0;
+ context->error = UDPC_SUCCESS;
return context;
}
mtx_destroy(&ctx->tflagsMtx);
cnd_destroy(&ctx->threadCV);
}
+
+ free(ctx);
+}
+
+uint32_t UDPC_get_error(UDPC_Context *ctx)
+{
+ uint32_t error = ctx->error;
+ ctx->error = 0;
+ return error;
+}
+
+const char* UDPC_get_error_str(uint32_t error)
+{
+ switch(error)
+ {
+ case UDPC_SUCCESS: return "No error";
+ case UDPC_ERR_SOCKETFAIL: return UDPC_ERR_SOCKETFAIL_STR;
+ case UDPC_ERR_SOCKETBINDF: return UDPC_ERR_SOCKETBINDF_STR;
+ case UDPC_ERR_SOCKETNONBF: return UDPC_ERR_SOCKETNONBF_STR;
+ case UDPC_ERR_MTXFAIL: return UDPC_ERR_MTXFAIL_STR;
+ case UDPC_ERR_CVFAIL: return UDPC_ERR_CVFAIL_STR;
+ case UDPC_ERR_THREADFAIL: return UDPC_ERR_THREADFAIL_STR;
+ default: return "Unknown error";
+ }
}
int UDPC_INTERNAL_threadfn(void *context)
#include <time.h>
#include <stdint.h>
-#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
+#include "UDPC_Defines.h"
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
#include <winsock2.h>
#define CleanupSocket(x) close(x)
#endif
-#define UDPCON_ERR_SOCKETFAIL 1 // failed to create socket
-#define UDPCON_ERR_SOCKETBINDF 2 // failed to bind socket
-#define UDPCON_ERR_SOCKETNONBF 3 // failed to set non-blocking on socket
-#define UDPCON_ERR_MTXFAIL 4 // failed to create mutex
-#define UDPCON_ERR_CVFAIL 5 // failed to create condition variable
-#define UDPCON_ERR_THREADFAIL 6 // failed to create thread
-
// This struct should not be used outside of this library
typedef struct
{
cnd_t threadCV;
} UDPC_Context;
-UDPC_Context UDPC_init(uint16_t listenPort);
+UDPC_Context* UDPC_init(uint16_t listenPort);
-UDPC_Context UDPC_init_threaded_update(uint16_t listenPort);
+UDPC_Context* UDPC_init_threaded_update(uint16_t listenPort);
void UDPC_destroy(UDPC_Context *ctx);
+uint32_t UDPC_get_error(UDPC_Context *ctx);
+
+const char* UDPC_get_error_str(uint32_t error);
+
int UDPC_INTERNAL_threadfn(void *context); // internal usage only
#endif