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
|
||||
src/UDPConnection.c
|
||||
src/UDPC_Deque.c
|
||||
src/UDPC_Defines.c
|
||||
)
|
||||
|
||||
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"
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -37,18 +39,18 @@ UDPC_Context UDPC_init(uint16_t listenPort)
|
|||
// 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;
|
||||
}
|
||||
|
@ -56,59 +58,59 @@ UDPC_Context UDPC_init(uint16_t listenPort)
|
|||
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;
|
||||
}
|
||||
|
@ -130,6 +132,30 @@ void UDPC_destroy(UDPC_Context *ctx)
|
|||
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)
|
||||
|
|
|
@ -6,20 +6,7 @@
|
|||
#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>
|
||||
|
@ -34,13 +21,6 @@
|
|||
#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
|
||||
{
|
||||
|
@ -101,12 +81,16 @@ 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
|
||||
|
|
Loading…
Reference in a new issue