Some more work on UDPC, WIP Deque
This commit is contained in:
parent
bc79efa20f
commit
b76df86a4f
4 changed files with 327 additions and 15 deletions
203
src/Deque.c
Normal file
203
src/Deque.c
Normal 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
67
src/Deque.h
Normal 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
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue