Change init to return ptr, some error handling
This commit is contained in:
parent
a27ffa8413
commit
32e2503bd0
5 changed files with 131 additions and 78 deletions
|
@ -4,6 +4,7 @@ project(UDPConnection)
|
||||||
set(UDPConnection_SOURCES
|
set(UDPConnection_SOURCES
|
||||||
src/UDPConnection.c
|
src/UDPConnection.c
|
||||||
src/UDPC_Deque.c
|
src/UDPC_Deque.c
|
||||||
|
src/UDPC_Defines.c
|
||||||
)
|
)
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS "-Wall -Wno-missing-braces")
|
set(CMAKE_C_FLAGS "-Wall -Wno-missing-braces")
|
||||||
|
|
8
src/UDPC_Defines.c
Normal file
8
src/UDPC_Defines.c
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include "UDPC_Defines.h"
|
||||||
|
|
||||||
|
static const char *UDPC_ERR_SOCKETFAIL_STR = "Failed to create socket";
|
||||||
|
static const char *UDPC_ERR_SOCKETBINDF_STR = "Failed to bind socket";
|
||||||
|
static const char *UDPC_ERR_SOCKETNONBF_STR = "Failed to set non-blocking on socket";
|
||||||
|
static const char *UDPC_ERR_MTXFAIL_STR = "Failed to create mutex";
|
||||||
|
static const char *UDPC_ERR_CVFAIL_STR = "Failed to create condition variable";
|
||||||
|
static const char *UDPC_ERR_THREADFAIL_STR = "Failed to create thread";
|
34
src/UDPC_Defines.h
Normal file
34
src/UDPC_Defines.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef UDPC_DEFINES_H
|
||||||
|
#define UDPC_DEFINES_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
|
||||||
|
|
||||||
|
#define UDPC_SUCCESS 0
|
||||||
|
#define UDPC_ERR_SOCKETFAIL 1 // failed to create socket
|
||||||
|
#define UDPC_ERR_SOCKETBINDF 2 // failed to bind socket
|
||||||
|
#define UDPC_ERR_SOCKETNONBF 3 // failed to set non-blocking on socket
|
||||||
|
#define UDPC_ERR_MTXFAIL 4 // failed to create mutex
|
||||||
|
#define UDPC_ERR_CVFAIL 5 // failed to create condition variable
|
||||||
|
#define UDPC_ERR_THREADFAIL 6 // failed to create thread
|
||||||
|
|
||||||
|
static const char *UDPC_ERR_SOCKETFAIL_STR;
|
||||||
|
static const char *UDPC_ERR_SOCKETBINDF_STR;
|
||||||
|
static const char *UDPC_ERR_SOCKETNONBF_STR;
|
||||||
|
static const char *UDPC_ERR_MTXFAIL_STR;
|
||||||
|
static const char *UDPC_ERR_CVFAIL_STR;
|
||||||
|
static const char *UDPC_ERR_THREADFAIL_STR;
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,35 +1,37 @@
|
||||||
#include "UDPConnection.h"
|
#include "UDPConnection.h"
|
||||||
|
|
||||||
UDPC_Context UDPC_init(uint16_t listenPort)
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
UDPC_Context* UDPC_init(uint16_t listenPort)
|
||||||
{
|
{
|
||||||
UDPC_Context context;
|
UDPC_Context *context = malloc(sizeof(UDPC_Context));
|
||||||
context.error = 0;
|
context->error = UDPC_SUCCESS;
|
||||||
context.flags = 0;
|
context->flags = 0;
|
||||||
context.threadFlags = 0;
|
context->threadFlags = 0;
|
||||||
|
|
||||||
// create socket
|
// create socket
|
||||||
context.socketHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
context->socketHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
if(context.socketHandle <= 0)
|
if(context->socketHandle <= 0)
|
||||||
{
|
{
|
||||||
context.socketHandle = 0;
|
context->socketHandle = 0;
|
||||||
context.error = UDPCON_ERR_SOCKETFAIL;
|
context->error = UDPC_ERR_SOCKETFAIL;
|
||||||
fprintf(stderr, "Failed to create socket\n");
|
fprintf(stderr, "Failed to create socket\n");
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
// bind socket
|
// bind socket
|
||||||
context.socketInfo.sin_family = AF_INET;
|
context->socketInfo.sin_family = AF_INET;
|
||||||
context.socketInfo.sin_addr.s_addr = INADDR_ANY;
|
context->socketInfo.sin_addr.s_addr = INADDR_ANY;
|
||||||
context.socketInfo.sin_port = listenPort;
|
context->socketInfo.sin_port = listenPort;
|
||||||
if(bind(
|
if(bind(
|
||||||
context.socketHandle,
|
context->socketHandle,
|
||||||
(const struct sockaddr*) &context.socketInfo,
|
(const struct sockaddr*) &context->socketInfo,
|
||||||
sizeof(struct sockaddr_in)
|
sizeof(struct sockaddr_in)
|
||||||
) < 0)
|
) < 0)
|
||||||
{
|
{
|
||||||
context.error = UDPCON_ERR_SOCKETBINDF;
|
context->error = UDPC_ERR_SOCKETBINDF;
|
||||||
CleanupSocket(context.socketHandle);
|
CleanupSocket(context->socketHandle);
|
||||||
context.socketHandle = 0;
|
context->socketHandle = 0;
|
||||||
fprintf(stderr, "Failed to bind socket\n");
|
fprintf(stderr, "Failed to bind socket\n");
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
@ -37,18 +39,18 @@ UDPC_Context UDPC_init(uint16_t listenPort)
|
||||||
// set nonblocking on socket
|
// set nonblocking on socket
|
||||||
#if UDPC_PLATFORM == UDPC_PLATFORM_MAC || UDPC_PLATFORM == UDPC_PLATFORM_LINUX
|
#if UDPC_PLATFORM == UDPC_PLATFORM_MAC || UDPC_PLATFORM == UDPC_PLATFORM_LINUX
|
||||||
int nonblocking = 1;
|
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
|
#elif UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
||||||
DWORD nonblocking = 1;
|
DWORD nonblocking = 1;
|
||||||
if(ioctlsocket(context.socketHandle, FIONBIO, &nonblocking) != 0)
|
if(ioctlsocket(context->socketHandle, FIONBIO, &nonblocking) != 0)
|
||||||
{
|
{
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
context.error = UDPCON_ERR_SOCKETNONBF;
|
context->error = UDPC_ERR_SOCKETNONBF;
|
||||||
CleanupSocket(context.socketHandle);
|
CleanupSocket(context->socketHandle);
|
||||||
context.socketHandle = 0;
|
context->socketHandle = 0;
|
||||||
fprintf(stderr, "Failed to set non-blocking on socket\n");
|
fprintf(stderr, "Failed to set non-blocking on socket\n");
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
@ -56,59 +58,59 @@ UDPC_Context UDPC_init(uint16_t listenPort)
|
||||||
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);
|
context->error = mtx_init(&context->tCVMtx, mtx_timed);
|
||||||
if(context.error != thrd_success)
|
if(context->error != thrd_success)
|
||||||
{
|
{
|
||||||
CleanupSocket(context.socketHandle);
|
CleanupSocket(context->socketHandle);
|
||||||
context.socketHandle = 0;
|
context->socketHandle = 0;
|
||||||
fprintf(stderr, "Failed to create mutex\n");
|
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);
|
context->error = mtx_init(&context->tflagsMtx, mtx_timed);
|
||||||
if(context.error != thrd_success)
|
if(context->error != thrd_success)
|
||||||
{
|
{
|
||||||
CleanupSocket(context.socketHandle);
|
CleanupSocket(context->socketHandle);
|
||||||
context.socketHandle = 0;
|
context->socketHandle = 0;
|
||||||
mtx_destroy(&context.tCVMtx);
|
mtx_destroy(&context->tCVMtx);
|
||||||
fprintf(stderr, "Failed to create mutex\n");
|
fprintf(stderr, "Failed to create mutex\n");
|
||||||
context.error = UDPCON_ERR_MTXFAIL;
|
context->error = UDPC_ERR_MTXFAIL;
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
context.error = 0;
|
context->error = UDPC_SUCCESS;
|
||||||
|
|
||||||
context.error = cnd_init(&context.threadCV);
|
context->error = cnd_init(&context->threadCV);
|
||||||
if(context.error != thrd_success)
|
if(context->error != thrd_success)
|
||||||
{
|
{
|
||||||
CleanupSocket(context.socketHandle);
|
CleanupSocket(context->socketHandle);
|
||||||
context.socketHandle = 0;
|
context->socketHandle = 0;
|
||||||
mtx_destroy(&context.tCVMtx);
|
mtx_destroy(&context->tCVMtx);
|
||||||
mtx_destroy(&context.tflagsMtx);
|
mtx_destroy(&context->tflagsMtx);
|
||||||
fprintf(stderr, "Failed to create condition variable\n");
|
fprintf(stderr, "Failed to create condition variable\n");
|
||||||
context.error = UDPCON_ERR_CVFAIL;
|
context->error = UDPC_ERR_CVFAIL;
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
context.error = 0;
|
context->error = UDPC_SUCCESS;
|
||||||
|
|
||||||
context.error = thrd_create(
|
context->error = thrd_create(
|
||||||
&context.threadHandle, UDPC_INTERNAL_threadfn, &context);
|
&context->threadHandle, UDPC_INTERNAL_threadfn, &context);
|
||||||
if(context.error != thrd_success)
|
if(context->error != thrd_success)
|
||||||
{
|
{
|
||||||
CleanupSocket(context.socketHandle);
|
CleanupSocket(context->socketHandle);
|
||||||
context.socketHandle = 0;
|
context->socketHandle = 0;
|
||||||
mtx_destroy(&context.tCVMtx);
|
mtx_destroy(&context->tCVMtx);
|
||||||
mtx_destroy(&context.tflagsMtx);
|
mtx_destroy(&context->tflagsMtx);
|
||||||
cnd_destroy(&context.threadCV);
|
cnd_destroy(&context->threadCV);
|
||||||
fprintf(stderr, "Failed to create thread\n");
|
fprintf(stderr, "Failed to create thread\n");
|
||||||
context.error = UDPCON_ERR_THREADFAIL;
|
context->error = UDPC_ERR_THREADFAIL;
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
context.error = 0;
|
context->error = UDPC_SUCCESS;
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
@ -130,6 +132,30 @@ void UDPC_destroy(UDPC_Context *ctx)
|
||||||
mtx_destroy(&ctx->tflagsMtx);
|
mtx_destroy(&ctx->tflagsMtx);
|
||||||
cnd_destroy(&ctx->threadCV);
|
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)
|
int UDPC_INTERNAL_threadfn(void *context)
|
||||||
|
|
|
@ -6,20 +6,7 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define UDPC_PLATFORM_WINDOWS 1
|
#include "UDPC_Defines.h"
|
||||||
#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
|
|
||||||
|
|
||||||
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
@ -34,13 +21,6 @@
|
||||||
#define CleanupSocket(x) close(x)
|
#define CleanupSocket(x) close(x)
|
||||||
#endif
|
#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
|
// This struct should not be used outside of this library
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -101,12 +81,16 @@ typedef struct
|
||||||
cnd_t threadCV;
|
cnd_t threadCV;
|
||||||
} UDPC_Context;
|
} 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);
|
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
|
int UDPC_INTERNAL_threadfn(void *context); // internal usage only
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue