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 <time.h>
|
||||
|
||||
UDPC_Context UDPC_init(unsigned short listenPort)
|
||||
UDPC_Context UDPC_init(uint16_t listenPort)
|
||||
{
|
||||
UDPC_Context context;
|
||||
context.error = 0;
|
||||
|
@ -45,6 +43,8 @@ UDPC_Context UDPC_init(unsigned short listenPort)
|
|||
DWORD nonblocking = 1;
|
||||
if(ioctlsocket(context.socketHandle, FIONBIO, &nonblocking) != 0)
|
||||
{
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
context.error = UDPCON_ERR_SOCKETNONBF;
|
||||
CleanupSocket(context.socketHandle);
|
||||
|
@ -56,7 +56,7 @@ UDPC_Context UDPC_init(unsigned short listenPort)
|
|||
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);
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <threads.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define UDPC_PLATFORM_WINDOWS 1
|
||||
#define UDPC_PLATFORM_MAC 2
|
||||
|
@ -39,29 +41,69 @@
|
|||
#define UDPCON_ERR_CVFAIL 5 // failed to create condition variable
|
||||
#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
|
||||
typedef struct
|
||||
{
|
||||
int error;
|
||||
/*
|
||||
* 0x1 - is threaded
|
||||
*/
|
||||
uint32_t flags;
|
||||
/*
|
||||
* 0x1 - thread should stop
|
||||
*/
|
||||
uint32_t threadFlags;
|
||||
uint32_t error;
|
||||
int socketHandle;
|
||||
struct sockaddr_in socketInfo;
|
||||
thrd_t threadHandle;
|
||||
mtx_t tCVMtx;
|
||||
mtx_t tflagsMtx;
|
||||
cnd_t threadCV;
|
||||
/*
|
||||
* 0x1 - is threaded
|
||||
*/
|
||||
int flags;
|
||||
/*
|
||||
* 0x1 - thread should stop
|
||||
*/
|
||||
int threadFlags;
|
||||
} 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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue