Some WIP impl of receiving packet handling

This commit is contained in:
Stephen Seo 2019-08-18 19:14:14 +09:00
parent bf27c328a6
commit 1e0f631ab2
2 changed files with 103 additions and 3 deletions

View file

@ -6,6 +6,7 @@
#define UDPC_GOOD_MODE_SEND_INTERVAL (1.0f / 30.0f) #define UDPC_GOOD_MODE_SEND_INTERVAL (1.0f / 30.0f)
#define UDPC_BAD_MODE_SEND_INTERVAL (1.0f / 10.0f) #define UDPC_BAD_MODE_SEND_INTERVAL (1.0f / 10.0f)
#define UDPC_SENT_PKTS_MAX_SIZE 33 #define UDPC_SENT_PKTS_MAX_SIZE 33
#define UDPC_QUEUED_PKTS_MAX_SIZE 32
#define UDPC_ID_CONNECT 0x80000000 #define UDPC_ID_CONNECT 0x80000000
#define UDPC_ID_PING 0x40000000 #define UDPC_ID_PING 0x40000000
@ -18,6 +19,7 @@
#include <cstdint> #include <cstdint>
#include <deque> #include <deque>
#include <unordered_map> #include <unordered_map>
#include <random>
#include "TSQueue.hpp" #include "TSQueue.hpp"
#include "UDPConnection.h" #include "UDPConnection.h"
@ -27,8 +29,14 @@ namespace UDPC {
static uint32_t LOCAL_ADDR = 0; static uint32_t LOCAL_ADDR = 0;
static const auto INIT_PKT_INTERVAL_DT = std::chrono::seconds(5); static const auto INIT_PKT_INTERVAL_DT = std::chrono::seconds(5);
static const auto HEARTBEAT_PKT_INTERVAL_DT = std::chrono::milliseconds(150); static const auto HEARTBEAT_PKT_INTERVAL_DT = std::chrono::milliseconds(150);
static const auto PACKET_TIMEOUT_TIME = std::chrono::seconds(1);
struct Context;
struct ConnectionData { struct ConnectionData {
ConnectionData();
ConnectionData(bool isServer, Context *ctx);
/* /*
* 0 - trigger send * 0 - trigger send
* 1 - is good mode * 1 - is good mode
@ -59,9 +67,11 @@ struct Context {
Context(bool isThreaded); Context(bool isThreaded);
uint_fast32_t _contextIdentifier; uint_fast32_t _contextIdentifier;
char recvBuf[UDPC_PACKET_MAX_SIZE];
/* /*
* 0 - is threaded * 0 - is threaded
* 1 - is client * 1 - is client
* 2 - is accepting new connections
*/ */
std::bitset<32> flags; std::bitset<32> flags;
std::atomic_bool isAcceptNewConnections; std::atomic_bool isAcceptNewConnections;
@ -73,9 +83,13 @@ struct Context {
struct sockaddr_in socketInfo; struct sockaddr_in socketInfo;
std::chrono::steady_clock::time_point lastUpdated; std::chrono::steady_clock::time_point lastUpdated;
// ipv4 address to ConnectionData
std::unordered_map<uint32_t, ConnectionData> conMap; std::unordered_map<uint32_t, ConnectionData> conMap;
// id to ipv4 address
std::unordered_map<uint32_t, uint32_t> idMap; std::unordered_map<uint32_t, uint32_t> idMap;
std::default_random_engine rng_engine;
}; // struct Context }; // struct Context
Context *verifyContext(void *ctx); Context *verifyContext(void *ctx);
@ -92,6 +106,8 @@ bool isBigEndian();
void preparePacket(char *data, uint32_t protocolID, uint32_t conID, void preparePacket(char *data, uint32_t protocolID, uint32_t conID,
uint32_t rseq, uint32_t ack, uint32_t *seqID, int flags); uint32_t rseq, uint32_t ack, uint32_t *seqID, int flags);
uint32_t generateConnectionID(Context &ctx);
} // namespace UDPC } // namespace UDPC
#endif #endif

View file

@ -7,14 +7,36 @@
#include <optional> #include <optional>
#include <vector> #include <vector>
UDPC::ConnectionData::ConnectionData() :
flags(),
sentPkts(),
sendPkts(UDPC_QUEUED_PKTS_MAX_SIZE),
priorityPkts(UDPC_QUEUED_PKTS_MAX_SIZE),
received(std::chrono::steady_clock::now()),
sent(std::chrono::steady_clock::now())
{
}
UDPC::ConnectionData::ConnectionData(bool isServer, Context *ctx) :
UDPC::ConnectionData::ConnectionData()
{
if(isServer) {
flags.set(0);
flags.set(3);
id = UDPC::generateConnectionID(*ctx);
flags.set(4);
}
}
UDPC::Context::Context(bool isThreaded) UDPC::Context::Context(bool isThreaded)
: _contextIdentifier(UDPC_CONTEXT_IDENTIFIER), flags(), : _contextIdentifier(UDPC_CONTEXT_IDENTIFIER), flags(),
isAcceptNewConnections(true), protocolID(UDPC_DEFAULT_PROTOCOL_ID), isAcceptNewConnections(true), protocolID(UDPC_DEFAULT_PROTOCOL_ID),
#ifndef NDEBUG #ifndef NDEBUG
loggingType(INFO) loggingType(INFO),
#else #else
loggingType(WARNING) loggingType(WARNING),
#endif #endif
rng_engine()
{ {
if(isThreaded) { if(isThreaded) {
flags.set(0); flags.set(0);
@ -29,6 +51,8 @@ UDPC::Context::Context(bool isThreaded)
UDPC::LOCAL_ADDR = 0x0100007F; UDPC::LOCAL_ADDR = 0x0100007F;
} }
} }
rng_engine.seed(std::chrono::system_clock::now().time_since_epoch().count());
} }
UDPC::Context *UDPC::verifyContext(void *ctx) { UDPC::Context *UDPC::verifyContext(void *ctx) {
@ -84,6 +108,15 @@ void UDPC::preparePacket(char *data, uint32_t protocolID, uint32_t conID,
std::memcpy(data + 16, &temp, 4); std::memcpy(data + 16, &temp, 4);
} }
uint32_t UDPC::generateConnectionID(Context &ctx) {
auto dist = std::uniform_int_distribution<uint32_t>(0, 0xFFFFFFFF);
uint32_t id = dist(ctx.rng_engine);
while(ctx.idMap.find(id) != ctx.idMap.end()) {
id = dist(ctx.rng_engine);
}
return id;
}
void *UDPC_init(uint16_t listenPort, uint32_t listenAddr, int isClient) { void *UDPC_init(uint16_t listenPort, uint32_t listenAddr, int isClient) {
UDPC::Context *ctx = new UDPC::Context(false); UDPC::Context *ctx = new UDPC::Context(false);
@ -423,7 +456,58 @@ void UDPC_update(void *ctx) {
} }
} }
// TODO receive packet // receive packet
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
typedef int socklen_t;
#endif
struct sockaddr_in receivedData;
socklen_t receivedDataSize = sizeof(receivedData);
int bytes = recvfrom(
c->socketHandle,
c->recvBuf,
UDPC_PACKET_MAX_SIZE,
0,
(struct sockaddr*) &receivedData,
&receivedDataSize);
if(bytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
// no packet was received
return;
} else if(bytes < 20) {
// packet size is too small, invalid packet
// TODO log this
return;
}
uint32_t temp = ntohl(*((uint32_t*)c->recvBuf));
if(temp != c->protocolID) {
// Invalid protocol id in packet
// TODO log this
return;
}
uint32_t conID = ntohl(*((uint32_t*)(c->recvBuf + 4)));
uint32_t seqID = ntohl(*((uint32_t*)(c->recvBuf + 8)));
uint32_t rseq = ntohl(*((uint32_t*)(c->recvBuf + 12)));
uint32_t ack = htonl(*((uint32_t*)(c->recvBuf + 16)));
bool isConnect = conID & UDPC_ID_CONNECT;
bool isPing = conID & UDPC_ID_PING;
bool isNotRecChecked = conID & UDPC_ID_NO_REC_CHK;
bool isResending = conID & UDPC_ID_RESENDING;
conID &= 0x0FFFFFFF;
if(isConnect && c->flags.test(2)) {
// is connect packet and is accepting new connections
if(!c->flags.test(1)
&& c->conMap.find(receivedData.sin_addr.s_addr) == c->conMap.end()) {
// is receiving as server, connection did not already exist
// TODO log establishing connection with client peer
UDPC::ConnectionData newConnection(true, c);
// TODO update idMap and conMap with new CD
// TODO impl establish connection with client peer as server
}
}
// TODO impl // TODO impl
} }