Store connections based on both addr and port
Previous implementation only stored based on addr only, preventing connections from/to the same address but different ports.
This commit is contained in:
parent
57e270eb15
commit
1382cc6b7c
3 changed files with 108 additions and 25 deletions
|
@ -50,6 +50,37 @@ struct SentPktInfo {
|
||||||
std::chrono::steady_clock::time_point sentTime;
|
std::chrono::steady_clock::time_point sentTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ConnectionIdentifier {
|
||||||
|
ConnectionIdentifier();
|
||||||
|
ConnectionIdentifier(uint32_t addr, uint16_t port);
|
||||||
|
|
||||||
|
// copy
|
||||||
|
ConnectionIdentifier(const ConnectionIdentifier& other) = default;
|
||||||
|
ConnectionIdentifier& operator =(const ConnectionIdentifier& other) = default;
|
||||||
|
|
||||||
|
// move
|
||||||
|
ConnectionIdentifier(ConnectionIdentifier&& other) = default;
|
||||||
|
ConnectionIdentifier& operator =(ConnectionIdentifier&& other) = default;
|
||||||
|
|
||||||
|
uint64_t id;
|
||||||
|
|
||||||
|
/// expects address to be in network byte order (big-endian)
|
||||||
|
void setAddr(uint32_t addr);
|
||||||
|
/// expects port to be in native order (not network byte order)
|
||||||
|
void setPort(uint16_t port);
|
||||||
|
|
||||||
|
/// returns address as a 4 byte unsigned int in network byte order (big-endian)
|
||||||
|
uint32_t getAddr() const;
|
||||||
|
/// returns port as a 2 byte unsigned int in native order (not network byte order)
|
||||||
|
uint16_t getPort() const;
|
||||||
|
|
||||||
|
bool operator ==(const ConnectionIdentifier& other) const;
|
||||||
|
|
||||||
|
struct Hasher {
|
||||||
|
std::size_t operator()(const ConnectionIdentifier& key) const;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
struct ConnectionData {
|
struct ConnectionData {
|
||||||
ConnectionData();
|
ConnectionData();
|
||||||
ConnectionData(bool isServer, Context *ctx);
|
ConnectionData(bool isServer, Context *ctx);
|
||||||
|
@ -114,10 +145,10 @@ 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
|
// ipv4 address and port to ConnectionData
|
||||||
std::unordered_map<uint32_t, ConnectionData> conMap;
|
std::unordered_map<ConnectionIdentifier, ConnectionData, ConnectionIdentifier::Hasher> conMap;
|
||||||
// id to ipv4 address
|
// id to ipv4 address
|
||||||
std::unordered_map<uint32_t, uint32_t> idMap;
|
std::unordered_map<uint32_t, ConnectionIdentifier> idMap;
|
||||||
|
|
||||||
std::default_random_engine rng_engine;
|
std::default_random_engine rng_engine;
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,48 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
UDPC::SentPktInfo::SentPktInfo() :
|
UDPC::SentPktInfo::SentPktInfo() :
|
||||||
id(0),
|
id(0),
|
||||||
sentTime(std::chrono::steady_clock::now())
|
sentTime(std::chrono::steady_clock::now())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
UDPC::ConnectionIdentifier::ConnectionIdentifier() :
|
||||||
|
id(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
UDPC::ConnectionIdentifier::ConnectionIdentifier(uint32_t addr, uint16_t port) :
|
||||||
|
UDPC::ConnectionIdentifier::ConnectionIdentifier()
|
||||||
|
{
|
||||||
|
*((uint32_t*)&id) = addr;
|
||||||
|
*((uint16_t*)(((unsigned char*)&id) + 4)) = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDPC::ConnectionIdentifier::setAddr(uint32_t addr) {
|
||||||
|
*((uint32_t*)&id) = addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDPC::ConnectionIdentifier::setPort(uint16_t port) {
|
||||||
|
*((uint16_t*)(((unsigned char*)&id) + 4)) = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t UDPC::ConnectionIdentifier::getAddr() const {
|
||||||
|
return *((uint32_t*)&id);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t UDPC::ConnectionIdentifier::getPort() const {
|
||||||
|
return *((uint16_t*)(((unsigned char*)&id) + 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UDPC::ConnectionIdentifier::operator==(const ConnectionIdentifier& other) const {
|
||||||
|
return id == other.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t UDPC::ConnectionIdentifier::Hasher::operator()(const ConnectionIdentifier& key) const {
|
||||||
|
return std::hash<uint64_t>()(key.id);
|
||||||
|
}
|
||||||
|
|
||||||
UDPC::ConnectionData::ConnectionData() :
|
UDPC::ConnectionData::ConnectionData() :
|
||||||
flags(),
|
flags(),
|
||||||
timer(std::chrono::steady_clock::duration::zero()),
|
timer(std::chrono::steady_clock::duration::zero()),
|
||||||
|
@ -230,7 +266,7 @@ void UDPC_update(void *ctx) {
|
||||||
std::chrono::steady_clock::duration temp_dt_fs;
|
std::chrono::steady_clock::duration temp_dt_fs;
|
||||||
{
|
{
|
||||||
// check timed out, check good/bad mode with rtt, remove timed out
|
// check timed out, check good/bad mode with rtt, remove timed out
|
||||||
std::vector<uint32_t> removed;
|
std::vector<UDPC::ConnectionIdentifier> removed;
|
||||||
for(auto iter = c->conMap.begin(); iter != c->conMap.end(); ++iter) {
|
for(auto iter = c->conMap.begin(); iter != c->conMap.end(); ++iter) {
|
||||||
temp_dt_fs = now - iter->second.received;
|
temp_dt_fs = now - iter->second.received;
|
||||||
if(temp_dt_fs >= UDPC::CONNECTION_TIMEOUT) {
|
if(temp_dt_fs >= UDPC::CONNECTION_TIMEOUT) {
|
||||||
|
@ -319,7 +355,7 @@ void UDPC_update(void *ctx) {
|
||||||
|
|
||||||
struct sockaddr_in destinationInfo;
|
struct sockaddr_in destinationInfo;
|
||||||
destinationInfo.sin_family = AF_INET;
|
destinationInfo.sin_family = AF_INET;
|
||||||
destinationInfo.sin_addr.s_addr = iter->first;
|
destinationInfo.sin_addr.s_addr = iter->first.getAddr();
|
||||||
destinationInfo.sin_port = htons(iter->second.port);
|
destinationInfo.sin_port = htons(iter->second.port);
|
||||||
long int sentBytes = sendto(
|
long int sentBytes = sendto(
|
||||||
c->socketHandle,
|
c->socketHandle,
|
||||||
|
@ -348,7 +384,7 @@ void UDPC_update(void *ctx) {
|
||||||
|
|
||||||
struct sockaddr_in destinationInfo;
|
struct sockaddr_in destinationInfo;
|
||||||
destinationInfo.sin_family = AF_INET;
|
destinationInfo.sin_family = AF_INET;
|
||||||
destinationInfo.sin_addr.s_addr = iter->first;
|
destinationInfo.sin_addr.s_addr = iter->first.getAddr();
|
||||||
destinationInfo.sin_port = htons(iter->second.port);
|
destinationInfo.sin_port = htons(iter->second.port);
|
||||||
long int sentBytes = sendto(
|
long int sentBytes = sendto(
|
||||||
c->socketHandle,
|
c->socketHandle,
|
||||||
|
@ -384,7 +420,7 @@ void UDPC_update(void *ctx) {
|
||||||
|
|
||||||
struct sockaddr_in destinationInfo;
|
struct sockaddr_in destinationInfo;
|
||||||
destinationInfo.sin_family = AF_INET;
|
destinationInfo.sin_family = AF_INET;
|
||||||
destinationInfo.sin_addr.s_addr = iter->first;
|
destinationInfo.sin_addr.s_addr = iter->first.getAddr();
|
||||||
destinationInfo.sin_port = htons(iter->second.port);
|
destinationInfo.sin_port = htons(iter->second.port);
|
||||||
long int sentBytes = sendto(
|
long int sentBytes = sendto(
|
||||||
c->socketHandle,
|
c->socketHandle,
|
||||||
|
@ -399,7 +435,7 @@ void UDPC_update(void *ctx) {
|
||||||
|
|
||||||
UDPC_PacketInfo pInfo{{0}, 0, 0, 0, 0, 0, 0};
|
UDPC_PacketInfo pInfo{{0}, 0, 0, 0, 0, 0, 0};
|
||||||
pInfo.sender = UDPC::LOCAL_ADDR;
|
pInfo.sender = UDPC::LOCAL_ADDR;
|
||||||
pInfo.receiver = iter->first;
|
pInfo.receiver = iter->first.getAddr();
|
||||||
pInfo.senderPort = c->socketInfo.sin_port;
|
pInfo.senderPort = c->socketInfo.sin_port;
|
||||||
pInfo.receiverPort = iter->second.port;
|
pInfo.receiverPort = iter->second.port;
|
||||||
*((uint32_t*)(pInfo.data + 8)) = htonl(iter->second.lseq - 1);
|
*((uint32_t*)(pInfo.data + 8)) = htonl(iter->second.lseq - 1);
|
||||||
|
@ -437,7 +473,7 @@ void UDPC_update(void *ctx) {
|
||||||
|
|
||||||
struct sockaddr_in destinationInfo;
|
struct sockaddr_in destinationInfo;
|
||||||
destinationInfo.sin_family = AF_INET;
|
destinationInfo.sin_family = AF_INET;
|
||||||
destinationInfo.sin_addr.s_addr = iter->first;
|
destinationInfo.sin_addr.s_addr = iter->first.getAddr();
|
||||||
destinationInfo.sin_port = htons(iter->second.port);
|
destinationInfo.sin_port = htons(iter->second.port);
|
||||||
long int sentBytes = sendto(
|
long int sentBytes = sendto(
|
||||||
c->socketHandle,
|
c->socketHandle,
|
||||||
|
@ -457,7 +493,7 @@ void UDPC_update(void *ctx) {
|
||||||
sentPInfo.flags = 0;
|
sentPInfo.flags = 0;
|
||||||
sentPInfo.dataSize = 20 + pInfo.dataSize;
|
sentPInfo.dataSize = 20 + pInfo.dataSize;
|
||||||
sentPInfo.sender = UDPC::LOCAL_ADDR;
|
sentPInfo.sender = UDPC::LOCAL_ADDR;
|
||||||
sentPInfo.receiver = iter->first;
|
sentPInfo.receiver = iter->first.getAddr();
|
||||||
sentPInfo.senderPort = c->socketInfo.sin_port;
|
sentPInfo.senderPort = c->socketInfo.sin_port;
|
||||||
sentPInfo.receiverPort = iter->second.port;
|
sentPInfo.receiverPort = iter->second.port;
|
||||||
|
|
||||||
|
@ -469,7 +505,7 @@ void UDPC_update(void *ctx) {
|
||||||
sentPInfo.flags = 0x4;
|
sentPInfo.flags = 0x4;
|
||||||
sentPInfo.dataSize = 0;
|
sentPInfo.dataSize = 0;
|
||||||
sentPInfo.sender = UDPC::LOCAL_ADDR;
|
sentPInfo.sender = UDPC::LOCAL_ADDR;
|
||||||
sentPInfo.receiver = iter->first;
|
sentPInfo.receiver = iter->first.getAddr();
|
||||||
sentPInfo.senderPort = c->socketInfo.sin_port;
|
sentPInfo.senderPort = c->socketInfo.sin_port;
|
||||||
sentPInfo.receiverPort = iter->second.port;
|
sentPInfo.receiverPort = iter->second.port;
|
||||||
*((uint32_t*)(sentPInfo.data + 8)) = htonl(iter->second.lseq - 1);
|
*((uint32_t*)(sentPInfo.data + 8)) = htonl(iter->second.lseq - 1);
|
||||||
|
@ -526,22 +562,24 @@ void UDPC_update(void *ctx) {
|
||||||
bool isResending = conID & UDPC_ID_RESENDING;
|
bool isResending = conID & UDPC_ID_RESENDING;
|
||||||
conID &= 0x0FFFFFFF;
|
conID &= 0x0FFFFFFF;
|
||||||
|
|
||||||
|
UDPC::ConnectionIdentifier identifier(receivedData.sin_addr.s_addr, ntohs(receivedData.sin_port));
|
||||||
|
|
||||||
if(isConnect && c->flags.test(2)) {
|
if(isConnect && c->flags.test(2)) {
|
||||||
// is connect packet and is accepting new connections
|
// is connect packet and is accepting new connections
|
||||||
if(!c->flags.test(1)
|
if(!c->flags.test(1)
|
||||||
&& c->conMap.find(receivedData.sin_addr.s_addr) == c->conMap.end()) {
|
&& c->conMap.find(identifier) == c->conMap.end()) {
|
||||||
// is receiving as server, connection did not already exist
|
// is receiving as server, connection did not already exist
|
||||||
// TODO log establishing connection with client peer
|
// TODO log establishing connection with client peer
|
||||||
UDPC::ConnectionData newConnection(true, c);
|
UDPC::ConnectionData newConnection(true, c);
|
||||||
newConnection.addr = receivedData.sin_addr.s_addr;
|
newConnection.addr = receivedData.sin_addr.s_addr;
|
||||||
newConnection.port = ntohs(receivedData.sin_port);
|
newConnection.port = ntohs(receivedData.sin_port);
|
||||||
|
|
||||||
c->idMap.insert(std::make_pair(newConnection.id, newConnection.addr));
|
c->idMap.insert(std::make_pair(newConnection.id, identifier));
|
||||||
c->conMap.insert(std::make_pair(newConnection.addr, std::move(newConnection)));
|
c->conMap.insert(std::make_pair(identifier, std::move(newConnection)));
|
||||||
// TODO trigger event server established connection with client
|
// TODO trigger event server established connection with client
|
||||||
} else if (c->flags.test(1)) {
|
} else if (c->flags.test(1)) {
|
||||||
// is client
|
// is client
|
||||||
auto iter = c->conMap.find(receivedData.sin_addr.s_addr);
|
auto iter = c->conMap.find(identifier);
|
||||||
if(iter == c->conMap.end() || !iter->second.flags.test(3)) {
|
if(iter == c->conMap.end() || !iter->second.flags.test(3)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -553,7 +591,7 @@ void UDPC_update(void *ctx) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto iter = c->conMap.find(receivedData.sin_addr.s_addr);
|
auto iter = c->conMap.find(identifier);
|
||||||
if(iter == c->conMap.end() || iter->second.flags.test(3)
|
if(iter == c->conMap.end() || iter->second.flags.test(3)
|
||||||
|| !iter->second.flags.test(4) || iter->second.id != conID) {
|
|| !iter->second.flags.test(4) || iter->second.id != conID) {
|
||||||
return;
|
return;
|
||||||
|
@ -698,13 +736,15 @@ void UDPC_update(void *ctx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int UDPC_get_queue_send_available(void *ctx, uint32_t addr) {
|
int UDPC_get_queue_send_available(void *ctx, uint32_t addr, uint16_t port) {
|
||||||
UDPC::Context *c = UDPC::verifyContext(ctx);
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
||||||
if(!c) {
|
if(!c) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto iter = c->conMap.find(addr);
|
UDPC::ConnectionIdentifier identifier(addr, port);
|
||||||
|
|
||||||
|
auto iter = c->conMap.find(identifier);
|
||||||
if(iter != c->conMap.end()) {
|
if(iter != c->conMap.end()) {
|
||||||
return iter->second.sendPkts.capacity() - iter->second.sendPkts.size();
|
return iter->second.sendPkts.capacity() - iter->second.sendPkts.size();
|
||||||
} else {
|
} else {
|
||||||
|
@ -712,7 +752,7 @@ int UDPC_get_queue_send_available(void *ctx, uint32_t addr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDPC_queue_send(void *ctx, uint32_t destAddr,
|
void UDPC_queue_send(void *ctx, uint32_t destAddr, uint16_t destPort,
|
||||||
uint32_t isChecked, void *data, uint32_t size) {
|
uint32_t isChecked, void *data, uint32_t size) {
|
||||||
if(size == 0 || !data) {
|
if(size == 0 || !data) {
|
||||||
return;
|
return;
|
||||||
|
@ -723,7 +763,9 @@ void UDPC_queue_send(void *ctx, uint32_t destAddr,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto iter = c->conMap.find(destAddr);
|
UDPC::ConnectionIdentifier identifier(destAddr, destPort);
|
||||||
|
|
||||||
|
auto iter = c->conMap.find(identifier);
|
||||||
if(iter == c->conMap.end()) {
|
if(iter == c->conMap.end()) {
|
||||||
// TODO log failed to add packet to queue; unknown recipient
|
// TODO log failed to add packet to queue; unknown recipient
|
||||||
return;
|
return;
|
||||||
|
@ -749,13 +791,15 @@ int UDPC_set_accept_new_connections(void *ctx, int isAccepting) {
|
||||||
return c->isAcceptNewConnections.exchange(isAccepting == 0 ? false : true);
|
return c->isAcceptNewConnections.exchange(isAccepting == 0 ? false : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int UDPC_drop_connection(void *ctx, uint32_t addr) {
|
int UDPC_drop_connection(void *ctx, uint32_t addr, uint16_t port) {
|
||||||
UDPC::Context *c = UDPC::verifyContext(ctx);
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
||||||
if(!c) {
|
if(!c) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto iter = c->conMap.find(addr);
|
UDPC::ConnectionIdentifier identifier(addr, port);
|
||||||
|
|
||||||
|
auto iter = c->conMap.find(identifier);
|
||||||
if(iter != c->conMap.end()) {
|
if(iter != c->conMap.end()) {
|
||||||
c->conMap.erase(iter);
|
c->conMap.erase(iter);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -63,7 +63,9 @@ typedef struct {
|
||||||
uint16_t receiverPort;
|
uint16_t receiverPort;
|
||||||
} UDPC_PacketInfo;
|
} UDPC_PacketInfo;
|
||||||
|
|
||||||
|
/// listenPort must be in native byte order, listenAddr must be in network byte order (big-endian)
|
||||||
void *UDPC_init(uint16_t listenPort, uint32_t listenAddr, int isClient);
|
void *UDPC_init(uint16_t listenPort, uint32_t listenAddr, int isClient);
|
||||||
|
/// listenPort must be in native byte order, listenAddr must be in network byte order (big-endian)
|
||||||
void *UDPC_init_threaded_update(uint16_t listenPort, uint32_t listenAddr,
|
void *UDPC_init_threaded_update(uint16_t listenPort, uint32_t listenAddr,
|
||||||
int isClient);
|
int isClient);
|
||||||
|
|
||||||
|
@ -71,14 +73,18 @@ void UDPC_destroy(void *ctx);
|
||||||
|
|
||||||
void UDPC_update(void *ctx);
|
void UDPC_update(void *ctx);
|
||||||
|
|
||||||
int UDPC_get_queue_send_available(void *ctx, uint32_t addr);
|
/// port must be in native byte order, addr must be in network byte order (big-endian)
|
||||||
|
int UDPC_get_queue_send_available(void *ctx, uint32_t addr, uint16_t port);
|
||||||
|
|
||||||
void UDPC_queue_send(void *ctx, uint32_t destAddr,
|
/// destPort must be in native byte order, destAddr must be in network byte order (big-endian)
|
||||||
|
void UDPC_queue_send(void *ctx, uint32_t destAddr, uint16_t destPort,
|
||||||
uint32_t isChecked, void *data, uint32_t size);
|
uint32_t isChecked, void *data, uint32_t size);
|
||||||
|
|
||||||
int UDPC_set_accept_new_connections(void *ctx, int isAccepting);
|
int UDPC_set_accept_new_connections(void *ctx, int isAccepting);
|
||||||
|
|
||||||
int UDPC_drop_connection(void *ctx, uint32_t addr);
|
// TODO implement drop_connection for all connections on an address and any port
|
||||||
|
/// addr must be in network byte order (big-endian), port must be in native byte order
|
||||||
|
int UDPC_drop_connection(void *ctx, uint32_t addr, uint16_t port);
|
||||||
|
|
||||||
uint32_t UDPC_set_protocol_id(void *ctx, uint32_t id);
|
uint32_t UDPC_set_protocol_id(void *ctx, uint32_t id);
|
||||||
|
|
||||||
|
@ -86,8 +92,10 @@ UDPC_LoggingType set_logging_type(void *ctx, UDPC_LoggingType loggingType);
|
||||||
|
|
||||||
UDPC_PacketInfo UDPC_get_received(void *ctx);
|
UDPC_PacketInfo UDPC_get_received(void *ctx);
|
||||||
|
|
||||||
|
/// addr must be in network byte order
|
||||||
const char *UDPC_atostr(void *ctx, uint32_t addr);
|
const char *UDPC_atostr(void *ctx, uint32_t addr);
|
||||||
|
|
||||||
|
/// returns a 4 byte unsigned integer address in network byte order
|
||||||
uint32_t UDPC_strtoa(const char *addrStr);
|
uint32_t UDPC_strtoa(const char *addrStr);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
Loading…
Reference in a new issue