Add error logging capability
Need to test internal atostr function.
This commit is contained in:
parent
ff31b0f604
commit
faba06a2b6
2 changed files with 132 additions and 14 deletions
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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->flags = 0;
|
||||
context->threadFlags = 0;
|
||||
context->atostrBuf[UDPC_ATOSTR_BUF_SIZE - 1] = 0;
|
||||
if(isClient != 0) context->flags |= 0x2;
|
||||
|
||||
// create socket
|
||||
|
@ -65,6 +68,8 @@ UDPC_Context* UDPC_init(uint16_t listenPort, int isClient)
|
|||
|
||||
timespec_get(&context->lastUpdated, TIME_UTC);
|
||||
|
||||
context->flags |= (0x8 | 0x4);
|
||||
|
||||
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)
|
||||
{
|
||||
// get dt
|
||||
|
@ -189,7 +219,9 @@ void UDPC_update(UDPC_Context *ctx)
|
|||
if(UDPC_ts_diff_to_seconds(&tsNow, &cd->received) >= UDPC_TIMEOUT_SECONDS)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -199,7 +231,9 @@ void UDPC_update(UDPC_Context *ctx)
|
|||
if((cd->flags & 0x2) != 0 && (cd->flags & 0x4) == 0)
|
||||
{
|
||||
// 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;
|
||||
if(cd->toggledTimer >= 10.0f)
|
||||
{
|
||||
|
@ -231,7 +265,8 @@ void UDPC_update(UDPC_Context *ctx)
|
|||
{
|
||||
cd->toggleTimer = 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;
|
||||
}
|
||||
}
|
||||
|
@ -275,11 +310,11 @@ void UDPC_update(UDPC_Context *ctx)
|
|||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
long int sentBytes = sendto(
|
||||
ctx->socketHandle,
|
||||
|
@ -290,7 +325,8 @@ void UDPC_update(UDPC_Context *ctx)
|
|||
sizeof(struct sockaddr_in));
|
||||
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
|
||||
{
|
||||
|
@ -322,12 +358,12 @@ void UDPC_update(UDPC_Context *ctx)
|
|||
UDPC_INTERNAL_PacketInfo *pinfo = UDPC_Deque_get_front_ptr(
|
||||
cd->sendPktQueue, sizeof(UDPC_INTERNAL_PacketInfo));
|
||||
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);
|
||||
|
||||
struct sockaddr_in destinationInfo;
|
||||
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);
|
||||
long int sentBytes = sendto(
|
||||
ctx->socketHandle,
|
||||
|
@ -338,7 +374,8 @@ void UDPC_update(UDPC_Context *ctx)
|
|||
sizeof(struct sockaddr_in));
|
||||
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
|
||||
{
|
||||
|
@ -347,7 +384,7 @@ void UDPC_update(UDPC_Context *ctx)
|
|||
UDPC_INTERNAL_PacketInfo sentInfo = {
|
||||
cd->addr,
|
||||
cd->lseq - 1,
|
||||
pinfo->flags & 0x2,
|
||||
0x2,
|
||||
data,
|
||||
20 + pinfo->size,
|
||||
tsNow
|
||||
|
@ -473,7 +510,6 @@ void UDPC_INTERNAL_prepare_pkt(
|
|||
uint32_t rseq,
|
||||
uint32_t ack,
|
||||
uint32_t *seqID,
|
||||
uint32_t addr,
|
||||
int flags)
|
||||
{
|
||||
char *d = data;
|
||||
|
@ -504,3 +540,59 @@ void UDPC_INTERNAL_prepare_pkt(
|
|||
temp = htonl(ack);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -24,11 +24,12 @@
|
|||
#define CleanupSocket(x) ((void)0)
|
||||
#endif
|
||||
|
||||
#define UDPC_ATOSTR_BUF_SIZE 16
|
||||
|
||||
/// This struct should not be used outside of this library
|
||||
typedef struct
|
||||
{
|
||||
uint32_t addr;
|
||||
uint32_t addr; // in network order (big-endian)
|
||||
uint32_t id;
|
||||
/*
|
||||
* 0x1 - is resending
|
||||
|
@ -58,7 +59,7 @@ typedef struct
|
|||
float toggleT;
|
||||
float toggleTimer;
|
||||
float toggledTimer;
|
||||
uint32_t addr;
|
||||
uint32_t addr; // in network order (big-endian)
|
||||
uint16_t port;
|
||||
UDPC_Deque *sentPkts;
|
||||
UDPC_Deque *sendPktQueue;
|
||||
|
@ -73,6 +74,10 @@ typedef struct
|
|||
/*
|
||||
* 0x1 - is threaded
|
||||
* 0x2 - is client
|
||||
* 0x4 - log errors
|
||||
* 0x8 - log warnings
|
||||
* 0x10 - log info
|
||||
* 0x20 - log verbose
|
||||
*/
|
||||
uint32_t flags;
|
||||
/*
|
||||
|
@ -88,6 +93,7 @@ typedef struct
|
|||
cnd_t threadCV;
|
||||
UDPC_Deque *connected;
|
||||
struct timespec lastUpdated;
|
||||
char atostrBuf[UDPC_ATOSTR_BUF_SIZE];
|
||||
} UDPC_Context;
|
||||
|
||||
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);
|
||||
|
||||
/*!
|
||||
* 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
|
||||
void UDPC_update(UDPC_Context *ctx);
|
||||
|
||||
|
@ -118,7 +135,16 @@ void UDPC_INTERNAL_prepare_pkt(
|
|||
uint32_t rseq,
|
||||
uint32_t ack,
|
||||
uint32_t *seqID,
|
||||
uint32_t addr,
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue