--- /dev/null
+#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;
+ }
+ }
+}
--- /dev/null
+#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
#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;
DWORD nonblocking = 1;
if(ioctlsocket(context.socketHandle, FIONBIO, &nonblocking) != 0)
{
+#else
+ {
#endif
context.error = UDPCON_ERR_SOCKETNONBF;
CleanupSocket(context.socketHandle);
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);
#include <stdio.h>
#include <threads.h>
+#include <time.h>
+#include <stdint.h>
#define UDPC_PLATFORM_WINDOWS 1
#define UDPC_PLATFORM_MAC 2
#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;
- int socketHandle;
- struct sockaddr_in socketInfo;
- thrd_t threadHandle;
- mtx_t tCVMtx;
- mtx_t tflagsMtx;
- cnd_t threadCV;
/*
* 0x1 - is threaded
*/
- int flags;
+ uint32_t flags;
/*
* 0x1 - thread should stop
*/
- int threadFlags;
+ uint32_t threadFlags;
+ uint32_t error;
+ int socketHandle;
+ struct sockaddr_in socketInfo;
+ thrd_t threadHandle;
+ mtx_t tCVMtx;
+ mtx_t tflagsMtx;
+ cnd_t threadCV;
} 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);