diff --git a/cpp_impl/src/UDPC_Defines.hpp b/cpp_impl/src/UDPC_Defines.hpp index c6263b3..0325b1e 100644 --- a/cpp_impl/src/UDPC_Defines.hpp +++ b/cpp_impl/src/UDPC_Defines.hpp @@ -50,6 +50,37 @@ struct SentPktInfo { 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 { ConnectionData(); ConnectionData(bool isServer, Context *ctx); @@ -114,10 +145,10 @@ struct Context { struct sockaddr_in socketInfo; std::chrono::steady_clock::time_point lastUpdated; - // ipv4 address to ConnectionData - std::unordered_map conMap; + // ipv4 address and port to ConnectionData + std::unordered_map conMap; // id to ipv4 address - std::unordered_map idMap; + std::unordered_map idMap; std::default_random_engine rng_engine; diff --git a/cpp_impl/src/UDPConnection.cpp b/cpp_impl/src/UDPConnection.cpp index ba2b685..9c5ad2e 100644 --- a/cpp_impl/src/UDPConnection.cpp +++ b/cpp_impl/src/UDPConnection.cpp @@ -6,12 +6,48 @@ #include #include #include +#include UDPC::SentPktInfo::SentPktInfo() : id(0), 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()(key.id); +} + UDPC::ConnectionData::ConnectionData() : flags(), timer(std::chrono::steady_clock::duration::zero()), @@ -230,7 +266,7 @@ void UDPC_update(void *ctx) { std::chrono::steady_clock::duration temp_dt_fs; { // check timed out, check good/bad mode with rtt, remove timed out - std::vector removed; + std::vector removed; for(auto iter = c->conMap.begin(); iter != c->conMap.end(); ++iter) { temp_dt_fs = now - iter->second.received; if(temp_dt_fs >= UDPC::CONNECTION_TIMEOUT) { @@ -319,7 +355,7 @@ void UDPC_update(void *ctx) { struct sockaddr_in destinationInfo; 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); long int sentBytes = sendto( c->socketHandle, @@ -348,7 +384,7 @@ void UDPC_update(void *ctx) { struct sockaddr_in destinationInfo; 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); long int sentBytes = sendto( c->socketHandle, @@ -384,7 +420,7 @@ void UDPC_update(void *ctx) { struct sockaddr_in destinationInfo; 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); long int sentBytes = sendto( c->socketHandle, @@ -399,7 +435,7 @@ void UDPC_update(void *ctx) { UDPC_PacketInfo pInfo{{0}, 0, 0, 0, 0, 0, 0}; pInfo.sender = UDPC::LOCAL_ADDR; - pInfo.receiver = iter->first; + pInfo.receiver = iter->first.getAddr(); pInfo.senderPort = c->socketInfo.sin_port; pInfo.receiverPort = iter->second.port; *((uint32_t*)(pInfo.data + 8)) = htonl(iter->second.lseq - 1); @@ -437,7 +473,7 @@ void UDPC_update(void *ctx) { struct sockaddr_in destinationInfo; 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); long int sentBytes = sendto( c->socketHandle, @@ -457,7 +493,7 @@ void UDPC_update(void *ctx) { sentPInfo.flags = 0; sentPInfo.dataSize = 20 + pInfo.dataSize; sentPInfo.sender = UDPC::LOCAL_ADDR; - sentPInfo.receiver = iter->first; + sentPInfo.receiver = iter->first.getAddr(); sentPInfo.senderPort = c->socketInfo.sin_port; sentPInfo.receiverPort = iter->second.port; @@ -469,7 +505,7 @@ void UDPC_update(void *ctx) { sentPInfo.flags = 0x4; sentPInfo.dataSize = 0; sentPInfo.sender = UDPC::LOCAL_ADDR; - sentPInfo.receiver = iter->first; + sentPInfo.receiver = iter->first.getAddr(); sentPInfo.senderPort = c->socketInfo.sin_port; sentPInfo.receiverPort = iter->second.port; *((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; conID &= 0x0FFFFFFF; + UDPC::ConnectionIdentifier identifier(receivedData.sin_addr.s_addr, ntohs(receivedData.sin_port)); + 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()) { + && c->conMap.find(identifier) == c->conMap.end()) { // is receiving as server, connection did not already exist // TODO log establishing connection with client peer UDPC::ConnectionData newConnection(true, c); newConnection.addr = receivedData.sin_addr.s_addr; newConnection.port = ntohs(receivedData.sin_port); - c->idMap.insert(std::make_pair(newConnection.id, newConnection.addr)); - c->conMap.insert(std::make_pair(newConnection.addr, std::move(newConnection))); + c->idMap.insert(std::make_pair(newConnection.id, identifier)); + c->conMap.insert(std::make_pair(identifier, std::move(newConnection))); // TODO trigger event server established connection with client } else if (c->flags.test(1)) { // 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)) { return; } @@ -553,7 +591,7 @@ void UDPC_update(void *ctx) { 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) || !iter->second.flags.test(4) || iter->second.id != conID) { 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); if(!c) { return 0; } - auto iter = c->conMap.find(addr); + UDPC::ConnectionIdentifier identifier(addr, port); + + auto iter = c->conMap.find(identifier); if(iter != c->conMap.end()) { return iter->second.sendPkts.capacity() - iter->second.sendPkts.size(); } 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) { if(size == 0 || !data) { return; @@ -723,7 +763,9 @@ void UDPC_queue_send(void *ctx, uint32_t destAddr, return; } - auto iter = c->conMap.find(destAddr); + UDPC::ConnectionIdentifier identifier(destAddr, destPort); + + auto iter = c->conMap.find(identifier); if(iter == c->conMap.end()) { // TODO log failed to add packet to queue; unknown recipient return; @@ -749,13 +791,15 @@ int UDPC_set_accept_new_connections(void *ctx, int isAccepting) { 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); if(!c) { return 0; } - auto iter = c->conMap.find(addr); + UDPC::ConnectionIdentifier identifier(addr, port); + + auto iter = c->conMap.find(identifier); if(iter != c->conMap.end()) { c->conMap.erase(iter); return 1; diff --git a/cpp_impl/src/UDPConnection.h b/cpp_impl/src/UDPConnection.h index 94a2383..31af2b4 100644 --- a/cpp_impl/src/UDPConnection.h +++ b/cpp_impl/src/UDPConnection.h @@ -63,7 +63,9 @@ typedef struct { uint16_t receiverPort; } 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); +/// 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, int isClient); @@ -71,14 +73,18 @@ void UDPC_destroy(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); 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); @@ -86,8 +92,10 @@ UDPC_LoggingType set_logging_type(void *ctx, UDPC_LoggingType loggingType); UDPC_PacketInfo UDPC_get_received(void *ctx); +/// addr must be in network byte order 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); #ifdef __cplusplus