diff --git a/src/UDPConnection.c b/src/UDPConnection.c index 4debe47..c5fae0e 100644 --- a/src/UDPConnection.c +++ b/src/UDPConnection.c @@ -2,6 +2,8 @@ #include #include +#include +#include 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; +} diff --git a/src/UDPConnection.h b/src/UDPConnection.h index d6ae457..ee32a3d 100644 --- a/src/UDPConnection.h +++ b/src/UDPConnection.h @@ -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