Some more work on UDPC, WIP Deque

This commit is contained in:
Stephen Seo 2019-01-26 19:11:12 +09:00
parent bc79efa20f
commit b76df86a4f
4 changed files with 327 additions and 15 deletions

203
src/Deque.c Normal file
View file

@ -0,0 +1,203 @@
#include "Deque.h"
#include <stdlib.h>
#include <string.h>
void UDPC_Deque_init(UDPC_Deque *deque, uint32_t alloc_size)
{
deque->head = 0;
deque->tail = 0;
deque->size = 0;
deque->alloc_size = alloc_size;
deque->buf = malloc(alloc_size);
}
int UDPC_Deque_push_back(UDPC_Deque *deque, const char *data, uint32_t size)
{
if(deque->size + size > deque->alloc_size)
{
return 0;
}
else if(deque->tail + size <= deque->alloc_size)
{
memcpy(&deque->buf[deque->tail], data, size);
deque->tail += size;
if(deque->tail == deque->alloc_size)
{
deque->tail = 0;
}
deque->size += size;
return 1;
}
uint32_t temp;
if(deque->tail < deque->alloc_size)
{
memcpy(&deque->buf[deque->tail], data, deque->alloc_size - deque->tail);
temp = deque->alloc_size - deque->tail;
deque->size += temp;
size -= temp;
deque->tail = 0;
}
if(size > 0)
{
memcpy(&deque->buf[deque->tail], &data[temp], size);
deque->tail += size;
deque->size += size;
}
return 1;
}
int UDPC_Deque_push_front(UDPC_Deque *deque, const char *data, uint32_t size)
{
if(deque->size + size > deque->alloc_size)
{
return 0;
}
else if(size <= deque->head)
{
memcpy(&deque->buf[deque->head - size], data, size);
deque->head -= size;
deque->size += size;
return 1;
}
if(deque->head > 0)
{
memcpy(deque->buf, &data[size - deque->head], deque->head);
deque->size += deque->head;
size -= deque->head;
deque->head = 0;
}
if(size > 0)
{
memcpy(&deque->buf[deque->alloc_size - size], data, size);
deque->head = deque->alloc_size - size;
deque->size += size;
}
return 1;
}
uint32_t UDPC_Deque_get_available(UDPC_Deque *deque)
{
return deque->alloc_size - deque->size;
}
int UDPC_Deque_get_back(UDPC_Deque *deque, char **data, uint32_t *size)
{
int returnValue = 1;
if(deque->size == 0)
{
*size = 0;
return 0;
}
else if(*size > deque->size)
{
*size = deque->size;
returnValue = 0;
}
*data = malloc(*size);
if(deque->tail < *size)
{
memcpy(data[*size - deque->tail], deque->buf, deque->tail);
memcpy(
*data,
&deque->buf[deque->alloc_size - (*size - deque->tail)],
*size - deque->tail);
return returnValue;
}
memcpy(*data, &deque->buf[deque->tail - *size], *size);
return returnValue;
}
int UDPC_Deque_get_front(UDPC_Deque *deque, char **data, uint32_t *size)
{
int returnValue = 1;
if(deque->size == 0)
{
*size = 0;
return 0;
}
else if(*size > deque->size)
{
*size = deque->size;
returnValue = 0;
}
*data = malloc(*size);
if(deque->head + *size > deque->alloc_size)
{
memcpy(*data, &deque->buf[deque->head], deque->alloc_size - deque->head);
memcpy(
data[deque->alloc_size - deque->head],
deque->buf,
*size - (deque->alloc_size - deque->head));
return returnValue;
}
memcpy(*data, &deque->buf[deque->head], *size);
return returnValue;
}
void UDPC_Deque_pop_back(UDPC_Deque *deque, uint32_t size)
{
if(deque->size == 0)
{
return;
}
else if(deque->size <= size)
{
deque->head = 0;
deque->tail = 0;
deque->size = 0;
return;
}
deque->size -= size;
if(deque->tail < size)
{
deque->tail = deque->alloc_size - (size - deque->tail);
}
else
{
deque->tail -= size;
}
}
void UDPC_Deque_pop_front(UDPC_Deque *deque, uint32_t size)
{
if(deque->size == 0)
{
return;
}
else if(deque->size <= size)
{
deque->head = 0;
deque->tail = 0;
deque->size = 0;
return;
}
deque->size -= size;
if(deque->head + size > deque->alloc_size)
{
deque->head = deque->head + size - deque->alloc_size;
}
else
{
deque->head += size;
if(deque->head == deque->alloc_size)
{
deque->head = 0;
}
}
}

67
src/Deque.h Normal file
View file

@ -0,0 +1,67 @@
#ifndef UDPC_DEQUE_H
#define UDPC_DEQUE_H
#include <stdint.h>
typedef struct
{
uint32_t head;
uint32_t tail;
uint32_t size;
uint32_t alloc_size;
char *buf;
} UDPC_Deque;
void UDPC_Deque_init(UDPC_Deque *deque, uint32_t alloc_size);
/*!
* If there was not enough space in the Deque, then no data is inserted at all.
* \return non-zero on success (there was enough size to insert data)
*/
int UDPC_Deque_push_back(UDPC_Deque *deque, const char *data, uint32_t size);
/*!
* If there was not enough space in the Deque, then no data is inserted at all.
* \return non-zero on success (there was enough size to insert data)
*/
int UDPC_Deque_push_front(UDPC_Deque *deque, const char *data, uint32_t size);
uint32_t UDPC_Deque_get_available(UDPC_Deque *deque);
/*!
* \brief Get data from back of deque
* Data must be free'd after use as it was allocated with malloc.
* When size is greater than deque size, partial data is allocated, size is
* updated to allocated amount. If deque is empty, no data is allocated.
* \return non-zero if full requested size was returned
*/
int UDPC_Deque_get_back(UDPC_Deque *deque, char **data, uint32_t *size);
/*!
* \brief Get data from front of deque
* Data must be free'd after use as it was allocated with malloc.
* When size is greater than deque size, partial data is allocated, size is
* updated to allocated amount. If deque is empty, no data is allocated.
* \return non-zero if full requested size was returned
*/
int UDPC_Deque_get_front(UDPC_Deque *deque, char **data, uint32_t *size);
/*!
* \brief "free" data from the back of the deque
* If size is greater than data used, then all data will be "free"d.
* Note that this doesn't actually deallocate data, but changes internal values
* that keep track of data positions in the internal buffer. The data will only
* actually be removed when it is overwritten or the Deque is free'd.
*/
void UDPC_Deque_pop_back(UDPC_Deque *deque, uint32_t size);
/*!
* \brief "free" data from the front of the deque
* If size is greater than data used, then all data will be "free"d.
* Note that this doesn't actually deallocate data, but changes internal values
* that keep track of data positions in the internal buffer. The data will only
* actually be removed when it is overwritten or the Deque is free'd.
*/
void UDPC_Deque_pop_front(UDPC_Deque *deque, uint32_t size);
#endif

View file

@ -1,8 +1,6 @@
#include "UDPConnection.h" #include "UDPConnection.h"
#include <time.h> UDPC_Context UDPC_init(uint16_t listenPort)
UDPC_Context UDPC_init(unsigned short listenPort)
{ {
UDPC_Context context; UDPC_Context context;
context.error = 0; context.error = 0;
@ -45,6 +43,8 @@ UDPC_Context UDPC_init(unsigned short listenPort)
DWORD nonblocking = 1; DWORD nonblocking = 1;
if(ioctlsocket(context.socketHandle, FIONBIO, &nonblocking) != 0) if(ioctlsocket(context.socketHandle, FIONBIO, &nonblocking) != 0)
{ {
#else
{
#endif #endif
context.error = UDPCON_ERR_SOCKETNONBF; context.error = UDPCON_ERR_SOCKETNONBF;
CleanupSocket(context.socketHandle); CleanupSocket(context.socketHandle);
@ -56,7 +56,7 @@ UDPC_Context UDPC_init(unsigned short listenPort)
return context; return context;
} }
UDPC_Context UDPC_init_threaded_update(unsigned short listenPort) UDPC_Context UDPC_init_threaded_update(uint16_t listenPort)
{ {
UDPC_Context context = UDPC_init(listenPort); UDPC_Context context = UDPC_init(listenPort);

View file

@ -3,6 +3,8 @@
#include <stdio.h> #include <stdio.h>
#include <threads.h> #include <threads.h>
#include <time.h>
#include <stdint.h>
#define UDPC_PLATFORM_WINDOWS 1 #define UDPC_PLATFORM_WINDOWS 1
#define UDPC_PLATFORM_MAC 2 #define UDPC_PLATFORM_MAC 2
@ -39,29 +41,69 @@
#define UDPCON_ERR_CVFAIL 5 // failed to create condition variable #define UDPCON_ERR_CVFAIL 5 // failed to create condition variable
#define UDPCON_ERR_THREADFAIL 6 // failed to create thread #define UDPCON_ERR_THREADFAIL 6 // failed to create thread
// This struct should not be used outside of this library
typedef struct
{
uint32_t addr;
uint32_t id;
/*
* 0x1 - is resending
* 0x2 - is not received checked
* 0x4 - has been re-sent
*/
uint32_t flags;
char *data;
struct timespec sent;
} UDPC_INTERNAL_PacketInfo;
// This struct should not be used outside of this library
typedef struct
{
/*
* 0x1 - trigger send
* 0x2 - is good mode
* 0x4 - is good rtt
*/
uint32_t flags;
uint32_t id;
uint32_t lseq;
uint32_t rseq;
uint32_t ack;
float timer;
float toggleT;
float toggleTimer;
float toggledTimer;
uint16_t port;
UDPC_INTERNAL_PacketInfo *sentPkts;
UDPC_INTERNAL_PacketInfo *sendPktQueue;
struct timespec received;
struct timespec sent;
struct timespec rtt;
} UDPC_INTERNAL_ConnectionData;
// This struct should not be modified, only passed to functions that require it // This struct should not be modified, only passed to functions that require it
typedef struct typedef struct
{ {
int error; /*
* 0x1 - is threaded
*/
uint32_t flags;
/*
* 0x1 - thread should stop
*/
uint32_t threadFlags;
uint32_t error;
int socketHandle; int socketHandle;
struct sockaddr_in socketInfo; struct sockaddr_in socketInfo;
thrd_t threadHandle; thrd_t threadHandle;
mtx_t tCVMtx; mtx_t tCVMtx;
mtx_t tflagsMtx; mtx_t tflagsMtx;
cnd_t threadCV; cnd_t threadCV;
/*
* 0x1 - is threaded
*/
int flags;
/*
* 0x1 - thread should stop
*/
int threadFlags;
} UDPC_Context; } UDPC_Context;
UDPC_Context UDPC_init(unsigned short listenPort); UDPC_Context UDPC_init(uint16_t listenPort);
UDPC_Context UDPC_init_threaded_update(unsigned short listenPort); UDPC_Context UDPC_init_threaded_update(uint16_t listenPort);
void UDPC_destroy(UDPC_Context *ctx); void UDPC_destroy(UDPC_Context *ctx);