2019-01-26 03:52:10 +00:00
|
|
|
#ifndef UDPCONNECTION_H
|
|
|
|
#define UDPCONNECTION_H
|
|
|
|
|
2019-01-26 07:22:31 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <threads.h>
|
2019-01-26 10:11:12 +00:00
|
|
|
#include <time.h>
|
|
|
|
#include <stdint.h>
|
2019-01-26 07:22:31 +00:00
|
|
|
|
2019-01-29 02:53:39 +00:00
|
|
|
#include "UDPC_Defines.h"
|
2019-01-30 06:46:52 +00:00
|
|
|
#include "UDPC_Deque.h"
|
2019-02-15 04:52:38 +00:00
|
|
|
#include "UDPC_HashMap.h"
|
2019-01-26 07:22:31 +00:00
|
|
|
|
2019-01-26 07:49:54 +00:00
|
|
|
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
2019-01-26 07:22:31 +00:00
|
|
|
#include <winsock2.h>
|
|
|
|
|
|
|
|
#define CleanupSocket(x) closesocket(x)
|
2019-01-26 07:49:54 +00:00
|
|
|
#elif UDPC_PLATFORM == UDPC_PLATFORM_MAC || UDPC_PLATFORM == UDPC_PLATFORM_LINUX
|
2019-01-26 07:22:31 +00:00
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#define CleanupSocket(x) close(x)
|
2019-01-31 03:16:01 +00:00
|
|
|
#else
|
|
|
|
#define CleanupSocket(x) ((void)0)
|
2019-01-26 07:22:31 +00:00
|
|
|
#endif
|
|
|
|
|
2019-02-01 10:22:04 +00:00
|
|
|
#define UDPC_ATOSTR_BUF_SIZE 16
|
2019-01-30 06:46:52 +00:00
|
|
|
|
2019-02-20 06:13:57 +00:00
|
|
|
/// (void *userData, uint32_t address)
|
|
|
|
/*!
|
|
|
|
* Note address is in network byte order (usually big-endian)
|
|
|
|
*/
|
|
|
|
typedef void (*UDPC_callback_connected)(void*, uint32_t);
|
|
|
|
|
|
|
|
/// (void *userData, uint32_t address)
|
|
|
|
/*!
|
|
|
|
* Note address is in network byte order (usually big-endian)
|
|
|
|
*/
|
|
|
|
typedef void (*UDPC_callback_disconnected)(void*, uint32_t);
|
|
|
|
|
|
|
|
/// (void *userData, char *packetData, uint32_t packetSize)
|
|
|
|
/*!
|
|
|
|
* The data pointed to by the packetData argument is to data internally managed
|
|
|
|
* by the UDPC_Context. It will change every time this callback is called so do
|
|
|
|
* not depend on it persisting. This means you should copy the data out of it
|
|
|
|
* when the callback is invoked and work with the copied data.
|
|
|
|
*/
|
|
|
|
typedef void (*UDPC_callback_received)(void*, char*, uint32_t);
|
|
|
|
|
2019-01-31 03:16:01 +00:00
|
|
|
/// This struct should not be used outside of this library
|
2019-02-04 08:21:49 +00:00
|
|
|
typedef struct {
|
2019-02-01 10:22:04 +00:00
|
|
|
uint32_t addr; // in network order (big-endian)
|
2019-01-26 10:11:12 +00:00
|
|
|
uint32_t id;
|
|
|
|
/*
|
|
|
|
* 0x1 - is resending
|
2019-01-31 10:44:32 +00:00
|
|
|
* 0x2 - is check received packet
|
2019-01-26 10:11:12 +00:00
|
|
|
* 0x4 - has been re-sent
|
|
|
|
*/
|
|
|
|
uint32_t flags;
|
2019-02-20 06:13:57 +00:00
|
|
|
char *data; // no-header in sendPktQueue and receivedPackets, header in sentPkts
|
2019-01-31 10:44:32 +00:00
|
|
|
uint32_t size;
|
2019-01-26 10:11:12 +00:00
|
|
|
struct timespec sent;
|
|
|
|
} UDPC_INTERNAL_PacketInfo;
|
|
|
|
|
2019-01-31 03:16:01 +00:00
|
|
|
/// This struct should not be used outside of this library
|
2019-02-04 08:21:49 +00:00
|
|
|
typedef struct {
|
2019-01-26 10:11:12 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
2019-02-01 10:22:04 +00:00
|
|
|
uint32_t addr; // in network order (big-endian)
|
2019-01-26 10:11:12 +00:00
|
|
|
uint16_t port;
|
2019-01-30 06:46:52 +00:00
|
|
|
UDPC_Deque *sentPkts;
|
|
|
|
UDPC_Deque *sendPktQueue;
|
2019-01-26 10:11:12 +00:00
|
|
|
struct timespec received;
|
|
|
|
struct timespec sent;
|
2019-02-18 07:32:50 +00:00
|
|
|
float rtt;
|
2019-01-26 10:11:12 +00:00
|
|
|
} UDPC_INTERNAL_ConnectionData;
|
|
|
|
|
2019-02-19 04:28:16 +00:00
|
|
|
/// This struct should not be used externally, only passed to functions that require it
|
2019-02-04 08:21:49 +00:00
|
|
|
typedef struct {
|
2019-01-26 07:22:31 +00:00
|
|
|
/*
|
|
|
|
* 0x1 - is threaded
|
2019-01-30 06:46:52 +00:00
|
|
|
* 0x2 - is client
|
2019-02-01 10:22:04 +00:00
|
|
|
* 0x4 - log errors
|
|
|
|
* 0x8 - log warnings
|
|
|
|
* 0x10 - log info
|
|
|
|
* 0x20 - log verbose
|
2019-02-04 06:33:44 +00:00
|
|
|
* 0x40 - accept new connections
|
2019-01-26 07:22:31 +00:00
|
|
|
*/
|
2019-01-26 10:11:12 +00:00
|
|
|
uint32_t flags;
|
2019-01-26 07:22:31 +00:00
|
|
|
/*
|
|
|
|
* 0x1 - thread should stop
|
|
|
|
*/
|
2019-01-26 10:11:12 +00:00
|
|
|
uint32_t threadFlags;
|
|
|
|
uint32_t error;
|
|
|
|
int socketHandle;
|
|
|
|
struct sockaddr_in socketInfo;
|
|
|
|
thrd_t threadHandle;
|
|
|
|
mtx_t tCVMtx;
|
|
|
|
mtx_t tflagsMtx;
|
|
|
|
cnd_t threadCV;
|
2019-02-15 04:52:38 +00:00
|
|
|
UDPC_HashMap *conMap;
|
2019-01-31 03:16:01 +00:00
|
|
|
struct timespec lastUpdated;
|
2019-02-01 10:22:04 +00:00
|
|
|
char atostrBuf[UDPC_ATOSTR_BUF_SIZE];
|
2019-02-04 06:33:44 +00:00
|
|
|
char recvBuf[UDPC_PACKET_MAX_SIZE];
|
2019-02-21 06:40:30 +00:00
|
|
|
UDPC_Deque *connectedEvents;
|
|
|
|
UDPC_Deque *disconnectedEvents;
|
2019-02-20 06:13:57 +00:00
|
|
|
UDPC_Deque *receivedPackets;
|
|
|
|
|
|
|
|
UDPC_callback_connected callbackConnected;
|
|
|
|
void *callbackConnectedUserData;
|
|
|
|
UDPC_callback_disconnected callbackDisconnected;
|
|
|
|
void *callbackDisconnectedUserData;
|
|
|
|
UDPC_callback_received callbackReceived;
|
|
|
|
void *callbackReceivedUserData;
|
2019-01-26 07:22:31 +00:00
|
|
|
} UDPC_Context;
|
|
|
|
|
2019-02-15 04:52:38 +00:00
|
|
|
typedef struct {
|
|
|
|
struct timespec tsNow;
|
|
|
|
float dt;
|
|
|
|
UDPC_Deque *removedQueue;
|
|
|
|
UDPC_Context *ctx;
|
|
|
|
} UDPC_INTERNAL_update_struct;
|
|
|
|
|
2019-01-30 06:46:52 +00:00
|
|
|
UDPC_Context* UDPC_init(uint16_t listenPort, int isClient);
|
2019-01-26 07:22:31 +00:00
|
|
|
|
2019-01-30 06:46:52 +00:00
|
|
|
UDPC_Context* UDPC_init_threaded_update(uint16_t listenPort, int isClient);
|
2019-01-26 07:22:31 +00:00
|
|
|
|
|
|
|
void UDPC_destroy(UDPC_Context *ctx);
|
|
|
|
|
2019-02-18 03:31:42 +00:00
|
|
|
void UDPC_INTERNAL_destroy_conMap(void *unused, uint32_t addr, char *data);
|
2019-02-15 04:52:38 +00:00
|
|
|
|
2019-02-20 06:13:57 +00:00
|
|
|
void UDPC_set_callback_connected(
|
|
|
|
UDPC_Context *ctx, UDPC_callback_connected fptr, void *userData);
|
|
|
|
|
|
|
|
void UDPC_set_callback_disconnected(
|
|
|
|
UDPC_Context *ctx, UDPC_callback_disconnected fptr, void *userData);
|
|
|
|
|
|
|
|
void UDPC_set_callback_received(
|
|
|
|
UDPC_Context *ctx, UDPC_callback_received fptr, void *userData);
|
|
|
|
|
2019-02-21 06:40:30 +00:00
|
|
|
void UDPC_check_events(UDPC_Context *ctx);
|
2019-02-20 06:13:57 +00:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Queues a packet to send to a connected peer
|
|
|
|
* Note addr is expected to be in network-byte-order (big-endian).
|
|
|
|
* If isChecked is non-zero, UDPC will attempt to resend the packet if peer has
|
|
|
|
* not received it within UDPC_PACKET_TIMEOUT_SEC seconds.
|
|
|
|
* \return non-zero on success
|
|
|
|
*/
|
|
|
|
int UDPC_queue_send(
|
|
|
|
UDPC_Context *ctx, uint32_t addr, uint32_t isChecked, void *data, uint32_t size);
|
|
|
|
|
2019-02-21 06:40:30 +00:00
|
|
|
/*!
|
|
|
|
* \brief get the number of packets that can be queued to the addr
|
|
|
|
* \return number of queueable packets or 0 if connection has not been established
|
|
|
|
*/
|
|
|
|
int UDPC_get_queue_send_available(UDPC_Context *ctx, uint32_t addr);
|
|
|
|
|
2019-01-29 02:53:39 +00:00
|
|
|
uint32_t UDPC_get_error(UDPC_Context *ctx);
|
|
|
|
|
|
|
|
const char* UDPC_get_error_str(uint32_t error);
|
|
|
|
|
2019-02-01 10:22:04 +00:00
|
|
|
/*!
|
|
|
|
* 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);
|
|
|
|
|
2019-01-31 03:16:01 +00:00
|
|
|
/// If threaded, this function is called automatically
|
|
|
|
void UDPC_update(UDPC_Context *ctx);
|
|
|
|
|
2019-02-18 03:31:42 +00:00
|
|
|
void UDPC_INTERNAL_update_to_rtt_si(void *userData, uint32_t addr, char *data);
|
2019-02-15 04:52:38 +00:00
|
|
|
|
2019-02-18 03:31:42 +00:00
|
|
|
void UDPC_INTERNAL_update_send(void *userData, uint32_t addr, char *data);
|
2019-02-15 04:52:38 +00:00
|
|
|
|
2019-02-18 07:32:50 +00:00
|
|
|
void UDPC_INTERNAL_update_rtt(
|
|
|
|
UDPC_Context *ctx,
|
|
|
|
UDPC_INTERNAL_ConnectionData *cd,
|
|
|
|
uint32_t rseq,
|
|
|
|
struct timespec *tsNow);
|
|
|
|
|
|
|
|
void UDPC_INTERNAL_check_pkt_timeout(
|
2019-02-19 04:28:16 +00:00
|
|
|
UDPC_Context *ctx,
|
2019-02-18 07:32:50 +00:00
|
|
|
UDPC_INTERNAL_ConnectionData *cd,
|
|
|
|
uint32_t rseq,
|
|
|
|
uint32_t ack,
|
|
|
|
struct timespec *tsNow);
|
|
|
|
|
2019-02-20 06:13:57 +00:00
|
|
|
float UDPC_INTERNAL_ts_diff(struct timespec *ts0, struct timespec *ts1);
|
2019-01-31 03:16:01 +00:00
|
|
|
|
2019-02-20 06:13:57 +00:00
|
|
|
int UDPC_INTERNAL_threadfn(void *context);
|
2019-01-26 03:52:10 +00:00
|
|
|
|
2019-01-31 10:44:32 +00:00
|
|
|
/*
|
|
|
|
* 0x1 - is ping
|
|
|
|
* 0x2 - is resending
|
|
|
|
* 0x4 - is checked received packet
|
|
|
|
*/
|
|
|
|
void UDPC_INTERNAL_prepare_pkt(
|
|
|
|
void *data,
|
|
|
|
uint32_t conID,
|
|
|
|
uint32_t rseq,
|
|
|
|
uint32_t ack,
|
|
|
|
uint32_t *seqID,
|
|
|
|
int flags);
|
|
|
|
|
2019-02-01 10:22:04 +00:00
|
|
|
/*!
|
|
|
|
* 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);
|
|
|
|
|
2019-02-20 06:13:57 +00:00
|
|
|
uint32_t UDPC_INTERNAL_generate_id(UDPC_Context *ctx);
|
|
|
|
|
|
|
|
void UDPC_INTERNAL_check_ids(void *userData, uint32_t addr, char *data);
|
|
|
|
|
2019-01-26 03:52:10 +00:00
|
|
|
#endif
|