Add error logging capability

Need to test internal atostr function.
This commit is contained in:
Stephen Seo 2019-02-01 19:22:04 +09:00
parent ff31b0f604
commit faba06a2b6
2 changed files with 132 additions and 14 deletions

View file

@ -2,6 +2,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdarg.h>
#include <stdio.h>
UDPC_Context* UDPC_init(uint16_t listenPort, int isClient) UDPC_Context* UDPC_init(uint16_t listenPort, int isClient)
{ {
@ -9,6 +11,7 @@ UDPC_Context* UDPC_init(uint16_t listenPort, int isClient)
context->error = UDPC_SUCCESS; context->error = UDPC_SUCCESS;
context->flags = 0; context->flags = 0;
context->threadFlags = 0; context->threadFlags = 0;
context->atostrBuf[UDPC_ATOSTR_BUF_SIZE - 1] = 0;
if(isClient != 0) context->flags |= 0x2; if(isClient != 0) context->flags |= 0x2;
// create socket // create socket
@ -65,6 +68,8 @@ UDPC_Context* UDPC_init(uint16_t listenPort, int isClient)
timespec_get(&context->lastUpdated, TIME_UTC); timespec_get(&context->lastUpdated, TIME_UTC);
context->flags |= (0x8 | 0x4);
return context; return context;
} }
@ -169,6 +174,31 @@ const char* UDPC_get_error_str(uint32_t error)
} }
} }
void UDPC_set_logging_type(UDPC_Context *ctx, uint32_t logType)
{
switch(logType)
{
case 0:
ctx->flags &= 0xFFFFFFC3;
break;
case 1:
ctx->flags &= 0xFFFFFFC7;
ctx->flags |= 0x4;
break;
case 2:
ctx->flags &= 0xFFFFFFCF;
ctx->flags |= (0x4 | 0x8);
break;
case 3:
ctx->flags &= 0xFFFFFFDF;
ctx->flags |= (0x4 | 0x8 | 0x10);
break;
default:
ctx->flags |= (0x4 | 0x8 | 0x10 | 0x20);
break;
}
}
void UDPC_update(UDPC_Context *ctx) void UDPC_update(UDPC_Context *ctx)
{ {
// get dt // get dt
@ -189,7 +219,9 @@ void UDPC_update(UDPC_Context *ctx)
if(UDPC_ts_diff_to_seconds(&tsNow, &cd->received) >= UDPC_TIMEOUT_SECONDS) if(UDPC_ts_diff_to_seconds(&tsNow, &cd->received) >= UDPC_TIMEOUT_SECONDS)
{ {
UDPC_Deque_push_back(removedQueue, &x, sizeof(int)); UDPC_Deque_push_back(removedQueue, &x, sizeof(int));
// TODO log timed out connection UDPC_INTERNAL_log(ctx, 2, "Connection timed out with addr %s port %d",
UDPC_INTERNAL_atostr(ctx, cd->addr),
cd->port);
continue; continue;
} }
@ -199,7 +231,9 @@ void UDPC_update(UDPC_Context *ctx)
if((cd->flags & 0x2) != 0 && (cd->flags & 0x4) == 0) if((cd->flags & 0x2) != 0 && (cd->flags & 0x4) == 0)
{ {
// good mode, bad rtt // good mode, bad rtt
// TODO log switching to bad mode UDPC_INTERNAL_log(ctx, 2, "Connection with %s switching to bad mode",
UDPC_INTERNAL_atostr(ctx, cd->addr));
cd->flags = cd->flags & 0xFFFFFFFD; cd->flags = cd->flags & 0xFFFFFFFD;
if(cd->toggledTimer >= 10.0f) if(cd->toggledTimer >= 10.0f)
{ {
@ -231,7 +265,8 @@ void UDPC_update(UDPC_Context *ctx)
{ {
cd->toggleTimer = 0.0f; cd->toggleTimer = 0.0f;
cd->toggledTimer = 0.0f; cd->toggledTimer = 0.0f;
// TODO log switching to good mode UDPC_INTERNAL_log(ctx, 2, "Connection with %s switching to good mode",
UDPC_INTERNAL_atostr(ctx, cd->addr));
cd->flags |= 0x2; cd->flags |= 0x2;
} }
} }
@ -275,11 +310,11 @@ void UDPC_update(UDPC_Context *ctx)
} }
char *data = malloc(20); char *data = malloc(20);
UDPC_INTERNAL_prepare_pkt(data, cd->id, cd->rseq, cd->ack, &cd->lseq, cd->addr, 0); UDPC_INTERNAL_prepare_pkt(data, cd->id, cd->rseq, cd->ack, &cd->lseq, 0);
struct sockaddr_in destinationInfo; struct sockaddr_in destinationInfo;
destinationInfo.sin_family = AF_INET; destinationInfo.sin_family = AF_INET;
destinationInfo.sin_addr.s_addr = htonl(cd->addr); destinationInfo.sin_addr.s_addr = cd->addr;
destinationInfo.sin_port = htons(cd->port); destinationInfo.sin_port = htons(cd->port);
long int sentBytes = sendto( long int sentBytes = sendto(
ctx->socketHandle, ctx->socketHandle,
@ -290,7 +325,8 @@ void UDPC_update(UDPC_Context *ctx)
sizeof(struct sockaddr_in)); sizeof(struct sockaddr_in));
if(sentBytes != 20) if(sentBytes != 20)
{ {
// TODO log fail send packet UDPC_INTERNAL_log(ctx, 0, "Failed to send packet to %s port %s",
UDPC_INTERNAL_atostr(ctx, cd->addr), cd->port);
} }
else else
{ {
@ -322,12 +358,12 @@ void UDPC_update(UDPC_Context *ctx)
UDPC_INTERNAL_PacketInfo *pinfo = UDPC_Deque_get_front_ptr( UDPC_INTERNAL_PacketInfo *pinfo = UDPC_Deque_get_front_ptr(
cd->sendPktQueue, sizeof(UDPC_INTERNAL_PacketInfo)); cd->sendPktQueue, sizeof(UDPC_INTERNAL_PacketInfo));
char *data = malloc(20 + pinfo->size); char *data = malloc(20 + pinfo->size);
UDPC_INTERNAL_prepare_pkt(data, cd->id, cd->rseq, cd->ack, &cd->lseq, cd->addr, ((pinfo->flags & 0x3) << 1)); UDPC_INTERNAL_prepare_pkt(data, cd->id, cd->rseq, cd->ack, &cd->lseq, ((pinfo->flags & 0x3) << 1));
memcpy(&data[20], pinfo->data, pinfo->size); memcpy(&data[20], pinfo->data, pinfo->size);
struct sockaddr_in destinationInfo; struct sockaddr_in destinationInfo;
destinationInfo.sin_family = AF_INET; destinationInfo.sin_family = AF_INET;
destinationInfo.sin_addr.s_addr = htonl(cd->addr); destinationInfo.sin_addr.s_addr = cd->addr;
destinationInfo.sin_port = htons(cd->port); destinationInfo.sin_port = htons(cd->port);
long int sentBytes = sendto( long int sentBytes = sendto(
ctx->socketHandle, ctx->socketHandle,
@ -338,7 +374,8 @@ void UDPC_update(UDPC_Context *ctx)
sizeof(struct sockaddr_in)); sizeof(struct sockaddr_in));
if(sentBytes != 20 + pinfo->size) if(sentBytes != 20 + pinfo->size)
{ {
// TODO log fail sent packet UDPC_INTERNAL_log(ctx, 0, "Failed to send packet to %s port %s",
UDPC_INTERNAL_atostr(ctx, cd->addr), cd->port);
} }
else else
{ {
@ -347,7 +384,7 @@ void UDPC_update(UDPC_Context *ctx)
UDPC_INTERNAL_PacketInfo sentInfo = { UDPC_INTERNAL_PacketInfo sentInfo = {
cd->addr, cd->addr,
cd->lseq - 1, cd->lseq - 1,
pinfo->flags & 0x2, 0x2,
data, data,
20 + pinfo->size, 20 + pinfo->size,
tsNow tsNow
@ -473,7 +510,6 @@ void UDPC_INTERNAL_prepare_pkt(
uint32_t rseq, uint32_t rseq,
uint32_t ack, uint32_t ack,
uint32_t *seqID, uint32_t *seqID,
uint32_t addr,
int flags) int flags)
{ {
char *d = data; char *d = data;
@ -504,3 +540,59 @@ void UDPC_INTERNAL_prepare_pkt(
temp = htonl(ack); temp = htonl(ack);
memcpy(&d[16], &temp, 4); memcpy(&d[16], &temp, 4);
} }
void UDPC_INTERNAL_log(UDPC_Context *ctx, uint32_t level, const char *msg, ...)
{
va_list args;
va_start(args, msg);
switch(level)
{
case 0:
default:
if((ctx->flags & 0x4) == 0) break;
fprintf(stderr, "ERR: ");
break;
case 1:
if((ctx->flags & 0x8) == 0) break;
fprintf(stderr, "WARN: ");
break;
case 2:
if((ctx->flags & 0x10) == 0) break;
fprintf(stderr, "INFO: ");
break;
case 3:
if((ctx->flags & 0x20) == 0) break;
fprintf(stderr, "VERBOSE: ");
break;
}
vfprintf(stderr, msg, args);
fprintf(stderr, "\n");
va_end(args);
}
char* UDPC_INTERNAL_atostr(UDPC_Context *ctx, uint32_t addr)
{
int index = 0;
for(int x = 0; x < 4; ++x)
{
unsigned char temp = (addr >> (24 - x * 8)) & 0xFF;
if(temp >= 100)
{
ctx->atostrBuf[index++] = '0' + temp / 100;
}
if(temp >= 10)
{
ctx->atostrBuf[index++] = '0' + ((temp / 10) % 10);
}
ctx->atostrBuf[index++] = '0' + temp % 10;
if(x < 3)
{
ctx->atostrBuf[index++] = '.';
}
}
ctx->atostrBuf[index] = 0;
return ctx->atostrBuf;
}

View file

@ -24,11 +24,12 @@
#define CleanupSocket(x) ((void)0) #define CleanupSocket(x) ((void)0)
#endif #endif
#define UDPC_ATOSTR_BUF_SIZE 16
/// This struct should not be used outside of this library /// This struct should not be used outside of this library
typedef struct typedef struct
{ {
uint32_t addr; uint32_t addr; // in network order (big-endian)
uint32_t id; uint32_t id;
/* /*
* 0x1 - is resending * 0x1 - is resending
@ -58,7 +59,7 @@ typedef struct
float toggleT; float toggleT;
float toggleTimer; float toggleTimer;
float toggledTimer; float toggledTimer;
uint32_t addr; uint32_t addr; // in network order (big-endian)
uint16_t port; uint16_t port;
UDPC_Deque *sentPkts; UDPC_Deque *sentPkts;
UDPC_Deque *sendPktQueue; UDPC_Deque *sendPktQueue;
@ -73,6 +74,10 @@ typedef struct
/* /*
* 0x1 - is threaded * 0x1 - is threaded
* 0x2 - is client * 0x2 - is client
* 0x4 - log errors
* 0x8 - log warnings
* 0x10 - log info
* 0x20 - log verbose
*/ */
uint32_t flags; uint32_t flags;
/* /*
@ -88,6 +93,7 @@ typedef struct
cnd_t threadCV; cnd_t threadCV;
UDPC_Deque *connected; UDPC_Deque *connected;
struct timespec lastUpdated; struct timespec lastUpdated;
char atostrBuf[UDPC_ATOSTR_BUF_SIZE];
} UDPC_Context; } UDPC_Context;
UDPC_Context* UDPC_init(uint16_t listenPort, int isClient); UDPC_Context* UDPC_init(uint16_t listenPort, int isClient);
@ -100,6 +106,17 @@ uint32_t UDPC_get_error(UDPC_Context *ctx);
const char* UDPC_get_error_str(uint32_t error); const char* UDPC_get_error_str(uint32_t error);
/*!
* 0 - log nothing
* 1 - log only errors
* 2 - log only errors and warnings
* 3 - log errors, warnings, and info
* 4+ - log everything
*
* By default, erros and warnings are logged.
*/
void UDPC_set_logging_type(UDPC_Context *ctx, uint32_t logType);
/// If threaded, this function is called automatically /// If threaded, this function is called automatically
void UDPC_update(UDPC_Context *ctx); void UDPC_update(UDPC_Context *ctx);
@ -118,7 +135,16 @@ void UDPC_INTERNAL_prepare_pkt(
uint32_t rseq, uint32_t rseq,
uint32_t ack, uint32_t ack,
uint32_t *seqID, uint32_t *seqID,
uint32_t addr,
int flags); int flags);
/*!
* 0 - error
* 1 - warning
* 2 - info
* 3 - verbose
*/
void UDPC_INTERNAL_log(UDPC_Context *ctx, uint32_t level, const char *msg, ...);
char* UDPC_INTERNAL_atostr(UDPC_Context *ctx, uint32_t addr);
#endif #endif