Change init to return ptr, some error handling

This commit is contained in:
Stephen Seo 2019-01-29 11:53:39 +09:00
parent a27ffa8413
commit 32e2503bd0
5 changed files with 131 additions and 78 deletions

View file

@ -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
View 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
View 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

View file

@ -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)

View file

@ -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