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

View file

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