Replace ipv4 with ipv6
ipv6 also supports sending to ipv4.
This commit is contained in:
parent
38eb06f105
commit
255930db9a
4 changed files with 529 additions and 285 deletions
|
@ -12,8 +12,8 @@
|
||||||
#define UDPC_ID_NO_REC_CHK 0x20000000
|
#define UDPC_ID_NO_REC_CHK 0x20000000
|
||||||
#define UDPC_ID_RESENDING 0x10000000
|
#define UDPC_ID_RESENDING 0x10000000
|
||||||
|
|
||||||
#define UDPC_ATOSTR_BUFCOUNT 64
|
#define UDPC_ATOSTR_BUFCOUNT 32
|
||||||
#define UDPC_ATOSTR_BUFSIZE 16
|
#define UDPC_ATOSTR_BUFSIZE 40
|
||||||
#define UDPC_ATOSTR_SIZE (UDPC_ATOSTR_BUFCOUNT * UDPC_ATOSTR_BUFSIZE)
|
#define UDPC_ATOSTR_SIZE (UDPC_ATOSTR_BUFCOUNT * UDPC_ATOSTR_BUFSIZE)
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
@ -38,7 +38,6 @@ static const auto ONE_SECOND = std::chrono::seconds(1);
|
||||||
static const auto TEN_SECONDS = std::chrono::seconds(10);
|
static const auto TEN_SECONDS = std::chrono::seconds(10);
|
||||||
static const auto THIRTY_SECONDS = std::chrono::seconds(30);
|
static const auto THIRTY_SECONDS = std::chrono::seconds(30);
|
||||||
|
|
||||||
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 = ONE_SECOND;
|
static const auto PACKET_TIMEOUT_TIME = ONE_SECOND;
|
||||||
|
@ -63,6 +62,10 @@ struct ConnectionIdHasher {
|
||||||
std::size_t operator()(const UDPC_ConnectionId& key) const;
|
std::size_t operator()(const UDPC_ConnectionId& key) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct IPV6_Hasher {
|
||||||
|
std::size_t operator()(const struct in6_addr& addr) const;
|
||||||
|
};
|
||||||
|
|
||||||
struct ConnectionData {
|
struct ConnectionData {
|
||||||
ConnectionData();
|
ConnectionData();
|
||||||
ConnectionData(bool isServer, Context *ctx);
|
ConnectionData(bool isServer, Context *ctx);
|
||||||
|
@ -93,7 +96,7 @@ struct ConnectionData {
|
||||||
std::chrono::steady_clock::duration toggleT;
|
std::chrono::steady_clock::duration toggleT;
|
||||||
std::chrono::steady_clock::duration toggleTimer;
|
std::chrono::steady_clock::duration toggleTimer;
|
||||||
std::chrono::steady_clock::duration toggledTimer;
|
std::chrono::steady_clock::duration toggledTimer;
|
||||||
uint32_t addr; // in network order
|
struct in6_addr addr; // in network order
|
||||||
uint16_t port; // in native order
|
uint16_t port; // in native order
|
||||||
std::deque<UDPC_PacketInfo> sentPkts;
|
std::deque<UDPC_PacketInfo> sentPkts;
|
||||||
TSQueue<UDPC_PacketInfo> sendPkts;
|
TSQueue<UDPC_PacketInfo> sendPkts;
|
||||||
|
@ -237,14 +240,14 @@ public:
|
||||||
char atostrBuf[UDPC_ATOSTR_SIZE];
|
char atostrBuf[UDPC_ATOSTR_SIZE];
|
||||||
|
|
||||||
int socketHandle;
|
int socketHandle;
|
||||||
struct sockaddr_in socketInfo;
|
struct sockaddr_in6 socketInfo;
|
||||||
|
|
||||||
std::chrono::steady_clock::time_point lastUpdated;
|
std::chrono::steady_clock::time_point lastUpdated;
|
||||||
// ipv4 address and port (as UDPC_ConnectionId) to ConnectionData
|
// ipv6 address and port (as UDPC_ConnectionId) to ConnectionData
|
||||||
std::unordered_map<UDPC_ConnectionId, ConnectionData, ConnectionIdHasher> conMap;
|
std::unordered_map<UDPC_ConnectionId, ConnectionData, ConnectionIdHasher> conMap;
|
||||||
// ipv4 address to all connected UDPC_ConnectionId
|
// ipv6 address to all connected UDPC_ConnectionId
|
||||||
std::unordered_map<uint32_t, std::unordered_set<UDPC_ConnectionId, ConnectionIdHasher> > addrConMap;
|
std::unordered_map<struct in6_addr, std::unordered_set<UDPC_ConnectionId, ConnectionIdHasher>, IPV6_Hasher> addrConMap;
|
||||||
// id to ipv4 address and port (as UDPC_ConnectionId)
|
// id to ipv6 address and port (as UDPC_ConnectionId)
|
||||||
std::unordered_map<uint32_t, UDPC_ConnectionId> idMap;
|
std::unordered_map<uint32_t, UDPC_ConnectionId> idMap;
|
||||||
|
|
||||||
std::default_random_engine rng_engine;
|
std::default_random_engine rng_engine;
|
||||||
|
@ -273,8 +276,12 @@ float timePointsToFSec(
|
||||||
const std::chrono::steady_clock::time_point& older,
|
const std::chrono::steady_clock::time_point& older,
|
||||||
const std::chrono::steady_clock::time_point& newer);
|
const std::chrono::steady_clock::time_point& newer);
|
||||||
|
|
||||||
|
UDPC_PacketInfo get_empty_pinfo();
|
||||||
|
|
||||||
} // namespace UDPC
|
} // namespace UDPC
|
||||||
|
|
||||||
bool operator ==(const UDPC_ConnectionId& a, const UDPC_ConnectionId& b);
|
bool operator ==(const UDPC_ConnectionId& a, const UDPC_ConnectionId& b);
|
||||||
|
|
||||||
|
bool operator ==(const struct in6_addr& a, const struct in6_addr& b);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <ios>
|
||||||
|
|
||||||
UDPC::SentPktInfo::SentPktInfo() :
|
UDPC::SentPktInfo::SentPktInfo() :
|
||||||
id(0),
|
id(0),
|
||||||
|
@ -15,13 +18,29 @@ sentTime(std::chrono::steady_clock::now())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::size_t UDPC::ConnectionIdHasher::operator()(const UDPC_ConnectionId& key) const {
|
std::size_t UDPC::ConnectionIdHasher::operator()(const UDPC_ConnectionId& key) const {
|
||||||
return std::hash<uint32_t>()(key.addr) ^ (std::hash<uint16_t>()(key.port) << 1);
|
std::string value((const char*)key.addr.s6_addr, 16);
|
||||||
|
value.push_back((char)((key.port >> 8) & 0xFF));
|
||||||
|
value.push_back((char)(key.port & 0xFF));
|
||||||
|
return std::hash<std::string>()(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t UDPC::IPV6_Hasher::operator()(const struct in6_addr& addr) const {
|
||||||
|
return std::hash<std::string>()(std::string((const char*)addr.s6_addr, 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator ==(const UDPC_ConnectionId& a, const UDPC_ConnectionId& b) {
|
bool operator ==(const UDPC_ConnectionId& a, const UDPC_ConnectionId& b) {
|
||||||
return a.addr == b.addr && a.port == b.port;
|
return a.addr == b.addr && a.port == b.port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator ==(const struct in6_addr& a, const struct in6_addr& b) {
|
||||||
|
for(unsigned int i = 0; i < 16; ++i) {
|
||||||
|
if(a.s6_addr[i] != b.s6_addr[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
UDPC::ConnectionData::ConnectionData() :
|
UDPC::ConnectionData::ConnectionData() :
|
||||||
flags(),
|
flags(),
|
||||||
id(0),
|
id(0),
|
||||||
|
@ -86,14 +105,6 @@ rng_engine()
|
||||||
flags.reset(0);
|
flags.reset(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(UDPC::LOCAL_ADDR == 0) {
|
|
||||||
if(UDPC::isBigEndian()) {
|
|
||||||
UDPC::LOCAL_ADDR = 0x7F000001;
|
|
||||||
} else {
|
|
||||||
UDPC::LOCAL_ADDR = 0x0100007F;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rng_engine.seed(std::chrono::system_clock::now().time_since_epoch().count());
|
rng_engine.seed(std::chrono::system_clock::now().time_since_epoch().count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,29 +184,54 @@ float UDPC::timePointsToFSec(
|
||||||
* (float)decltype(dt)::period::num / (float)decltype(dt)::period::den;
|
* (float)decltype(dt)::period::num / (float)decltype(dt)::period::den;
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC_ConnectionId UDPC_create_id(uint32_t addr, uint16_t port) {
|
UDPC_PacketInfo UDPC::get_empty_pinfo() {
|
||||||
|
return UDPC_PacketInfo {
|
||||||
|
{0}, // data (array)
|
||||||
|
0, // flags
|
||||||
|
0, // dataSize
|
||||||
|
{ // sender
|
||||||
|
{0}, // ipv6 addr
|
||||||
|
0 // port
|
||||||
|
},
|
||||||
|
{ // receiver
|
||||||
|
{0}, // ipv6 addr
|
||||||
|
0 // port
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
UDPC_ConnectionId UDPC_create_id(struct in6_addr addr, uint16_t port) {
|
||||||
return UDPC_ConnectionId{addr, port};
|
return UDPC_ConnectionId{addr, port};
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC_HContext UDPC_init(uint16_t listenPort, uint32_t listenAddr, int isClient) {
|
UDPC_ConnectionId UDPC_create_id_anyaddr(uint16_t port) {
|
||||||
|
return UDPC_ConnectionId{in6addr_any, port};
|
||||||
|
}
|
||||||
|
|
||||||
|
UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient) {
|
||||||
UDPC::Context *ctx = new UDPC::Context(false);
|
UDPC::Context *ctx = new UDPC::Context(false);
|
||||||
ctx->flags.set(1, isClient);
|
ctx->flags.set(1, isClient);
|
||||||
|
|
||||||
// create socket
|
// create socket
|
||||||
ctx->socketHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
ctx->socketHandle = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
if(ctx->socketHandle <= 0) {
|
if(ctx->socketHandle <= 0) {
|
||||||
// TODO maybe different way of handling init fail
|
// TODO maybe different way of handling init fail
|
||||||
delete ctx;
|
delete ctx;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allow ipv4 connections on ipv6 socket
|
||||||
|
{
|
||||||
|
int no = 0;
|
||||||
|
setsockopt(ctx->socketHandle, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no));
|
||||||
|
}
|
||||||
|
|
||||||
// bind socket
|
// bind socket
|
||||||
ctx->socketInfo.sin_family = AF_INET;
|
ctx->socketInfo.sin6_family = AF_INET6;
|
||||||
ctx->socketInfo.sin_addr.s_addr =
|
ctx->socketInfo.sin6_addr = listenId.addr;
|
||||||
(listenAddr == 0 ? INADDR_ANY : listenAddr);
|
ctx->socketInfo.sin6_port = htons(listenId.port);
|
||||||
ctx->socketInfo.sin_port = htons(listenPort);
|
|
||||||
if(bind(ctx->socketHandle, (const struct sockaddr *)&ctx->socketInfo,
|
if(bind(ctx->socketHandle, (const struct sockaddr *)&ctx->socketInfo,
|
||||||
sizeof(struct sockaddr_in)) < 0) {
|
sizeof(struct sockaddr_in6)) < 0) {
|
||||||
// TODO maybe different way of handling init fail
|
// TODO maybe different way of handling init fail
|
||||||
CleanupSocket(ctx->socketHandle);
|
CleanupSocket(ctx->socketHandle);
|
||||||
delete ctx;
|
delete ctx;
|
||||||
|
@ -203,11 +239,11 @@ UDPC_HContext UDPC_init(uint16_t listenPort, uint32_t listenAddr, int isClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO verify this is necessary to get the listen port
|
// TODO verify this is necessary to get the listen port
|
||||||
if(ctx->socketInfo.sin_port == 0) {
|
if(ctx->socketInfo.sin6_port == 0) {
|
||||||
struct sockaddr_in getInfo;
|
struct sockaddr_in6 getInfo;
|
||||||
socklen_t size = sizeof(struct sockaddr_in);
|
socklen_t size = sizeof(struct sockaddr_in6);
|
||||||
if(getsockname(ctx->socketHandle, (struct sockaddr *)&getInfo, &size) == 0) {
|
if(getsockname(ctx->socketHandle, (struct sockaddr *)&getInfo, &size) == 0) {
|
||||||
ctx->socketInfo.sin_port = getInfo.sin_port;
|
ctx->socketInfo.sin6_port = getInfo.sin6_port;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,10 +266,9 @@ UDPC_HContext UDPC_init(uint16_t listenPort, uint32_t listenAddr, int isClient)
|
||||||
return (UDPC_HContext) ctx;
|
return (UDPC_HContext) ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC_HContext UDPC_init_threaded_update(uint16_t listenPort, uint32_t listenAddr,
|
UDPC_HContext UDPC_init_threaded_update(UDPC_ConnectionId listenId,
|
||||||
int isClient) {
|
int isClient) {
|
||||||
UDPC::Context *ctx =
|
UDPC::Context *ctx = (UDPC::Context *)UDPC_init(listenId, isClient);
|
||||||
(UDPC::Context *)UDPC_init(listenPort, listenAddr, isClient);
|
|
||||||
if(!ctx) {
|
if(!ctx) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -270,7 +305,7 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
c->log(
|
c->log(
|
||||||
UDPC_LoggingType::VERBOSE,
|
UDPC_LoggingType::VERBOSE,
|
||||||
"Timed out connection with ",
|
"Timed out connection with ",
|
||||||
UDPC_atostr(ctx, iter->second.addr),
|
UDPC_atostr(ctx, iter->first),
|
||||||
":",
|
":",
|
||||||
iter->second.port);
|
iter->second.port);
|
||||||
continue;
|
continue;
|
||||||
|
@ -284,7 +319,7 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
c->log(
|
c->log(
|
||||||
UDPC_LoggingType::INFO,
|
UDPC_LoggingType::INFO,
|
||||||
"Switching to bad mode in connection with ",
|
"Switching to bad mode in connection with ",
|
||||||
UDPC_atostr(ctx, iter->second.addr),
|
UDPC_atostr(ctx, iter->first),
|
||||||
":",
|
":",
|
||||||
iter->second.port);
|
iter->second.port);
|
||||||
iter->second.flags.reset(1);
|
iter->second.flags.reset(1);
|
||||||
|
@ -310,7 +345,7 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
c->log(
|
c->log(
|
||||||
UDPC_LoggingType::INFO,
|
UDPC_LoggingType::INFO,
|
||||||
"Switching to good mode in connection with ",
|
"Switching to good mode in connection with ",
|
||||||
UDPC_atostr(ctx, iter->second.addr),
|
UDPC_atostr(ctx, iter->first),
|
||||||
":",
|
":",
|
||||||
iter->second.port);
|
iter->second.port);
|
||||||
iter->second.flags.set(1);
|
iter->second.flags.set(1);
|
||||||
|
@ -379,22 +414,22 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
nullptr,
|
nullptr,
|
||||||
0x1);
|
0x1);
|
||||||
|
|
||||||
struct sockaddr_in destinationInfo;
|
struct sockaddr_in6 destinationInfo;
|
||||||
destinationInfo.sin_family = AF_INET;
|
destinationInfo.sin6_family = AF_INET6;
|
||||||
destinationInfo.sin_addr.s_addr = iter->second.addr;
|
std::memcpy(destinationInfo.sin6_addr.s6_addr, iter->first.addr.s6_addr, 16);
|
||||||
destinationInfo.sin_port = htons(iter->second.port);
|
destinationInfo.sin6_port = htons(iter->second.port);
|
||||||
long int sentBytes = sendto(
|
long int sentBytes = sendto(
|
||||||
c->socketHandle,
|
c->socketHandle,
|
||||||
buf.get(),
|
buf.get(),
|
||||||
20,
|
20,
|
||||||
0,
|
0,
|
||||||
(struct sockaddr*) &destinationInfo,
|
(struct sockaddr*) &destinationInfo,
|
||||||
sizeof(struct sockaddr_in));
|
sizeof(struct sockaddr_in6));
|
||||||
if(sentBytes != 20) {
|
if(sentBytes != 20) {
|
||||||
c->log(
|
c->log(
|
||||||
UDPC_LoggingType::ERROR,
|
UDPC_LoggingType::ERROR,
|
||||||
"Failed to send packet to initiate connection to ",
|
"Failed to send packet to initiate connection to ",
|
||||||
UDPC_atostr(ctx, iter->second.addr),
|
UDPC_atostr(ctx, iter->first),
|
||||||
":",
|
":",
|
||||||
iter->second.port);
|
iter->second.port);
|
||||||
continue;
|
continue;
|
||||||
|
@ -414,22 +449,22 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
&iter->second.lseq,
|
&iter->second.lseq,
|
||||||
0x1);
|
0x1);
|
||||||
|
|
||||||
struct sockaddr_in destinationInfo;
|
struct sockaddr_in6 destinationInfo;
|
||||||
destinationInfo.sin_family = AF_INET;
|
destinationInfo.sin6_family = AF_INET6;
|
||||||
destinationInfo.sin_addr.s_addr = iter->second.addr;
|
std::memcpy(destinationInfo.sin6_addr.s6_addr, iter->first.addr.s6_addr, 16);
|
||||||
destinationInfo.sin_port = htons(iter->second.port);
|
destinationInfo.sin6_port = htons(iter->second.port);
|
||||||
long int sentBytes = sendto(
|
long int sentBytes = sendto(
|
||||||
c->socketHandle,
|
c->socketHandle,
|
||||||
buf.get(),
|
buf.get(),
|
||||||
20,
|
20,
|
||||||
0,
|
0,
|
||||||
(struct sockaddr*) &destinationInfo,
|
(struct sockaddr*) &destinationInfo,
|
||||||
sizeof(struct sockaddr_in));
|
sizeof(struct sockaddr_in6));
|
||||||
if(sentBytes != 20) {
|
if(sentBytes != 20) {
|
||||||
c->log(
|
c->log(
|
||||||
UDPC_LoggingType::ERROR,
|
UDPC_LoggingType::ERROR,
|
||||||
"Failed to send packet to initiate connection to ",
|
"Failed to send packet to initiate connection to ",
|
||||||
UDPC_atostr(ctx, iter->second.addr),
|
UDPC_atostr(ctx, iter->first),
|
||||||
":",
|
":",
|
||||||
iter->second.port);
|
iter->second.port);
|
||||||
continue;
|
continue;
|
||||||
|
@ -456,31 +491,31 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
&iter->second.lseq,
|
&iter->second.lseq,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
struct sockaddr_in destinationInfo;
|
struct sockaddr_in6 destinationInfo;
|
||||||
destinationInfo.sin_family = AF_INET;
|
destinationInfo.sin6_family = AF_INET6;
|
||||||
destinationInfo.sin_addr.s_addr = iter->second.addr;
|
std::memcpy(destinationInfo.sin6_addr.s6_addr, iter->first.addr.s6_addr, 16);
|
||||||
destinationInfo.sin_port = htons(iter->second.port);
|
destinationInfo.sin6_port = htons(iter->second.port);
|
||||||
long int sentBytes = sendto(
|
long int sentBytes = sendto(
|
||||||
c->socketHandle,
|
c->socketHandle,
|
||||||
buf.get(),
|
buf.get(),
|
||||||
20,
|
20,
|
||||||
0,
|
0,
|
||||||
(struct sockaddr*) &destinationInfo,
|
(struct sockaddr*) &destinationInfo,
|
||||||
sizeof(struct sockaddr_in));
|
sizeof(struct sockaddr_in6));
|
||||||
if(sentBytes != 20) {
|
if(sentBytes != 20) {
|
||||||
c->log(
|
c->log(
|
||||||
UDPC_LoggingType::ERROR,
|
UDPC_LoggingType::ERROR,
|
||||||
"Failed to send heartbeat packet to ",
|
"Failed to send heartbeat packet to ",
|
||||||
UDPC_atostr(ctx, iter->second.addr),
|
UDPC_atostr(ctx, iter->first),
|
||||||
":",
|
":",
|
||||||
iter->second.port);
|
iter->second.port);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC_PacketInfo pInfo{{0}, 0, 0, 0, 0, 0, 0};
|
UDPC_PacketInfo pInfo = UDPC::get_empty_pinfo();
|
||||||
pInfo.sender.addr = UDPC::LOCAL_ADDR;
|
pInfo.sender.addr = in6addr_loopback;
|
||||||
pInfo.receiver.addr = iter->first.addr;
|
pInfo.receiver.addr = iter->first.addr;
|
||||||
pInfo.sender.port = c->socketInfo.sin_port;
|
pInfo.sender.port = c->socketInfo.sin6_port;
|
||||||
pInfo.receiver.port = iter->second.port;
|
pInfo.receiver.port = iter->second.port;
|
||||||
*((uint32_t*)(pInfo.data + 8)) = iter->second.lseq - 1;
|
*((uint32_t*)(pInfo.data + 8)) = iter->second.lseq - 1;
|
||||||
|
|
||||||
|
@ -493,7 +528,7 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
iter->second.sentInfoMap.insert(std::make_pair(sentPktInfo->id, sentPktInfo));
|
iter->second.sentInfoMap.insert(std::make_pair(sentPktInfo->id, sentPktInfo));
|
||||||
} else {
|
} else {
|
||||||
// sendPkts or priorityPkts not empty
|
// sendPkts or priorityPkts not empty
|
||||||
UDPC_PacketInfo pInfo;
|
UDPC_PacketInfo pInfo = UDPC::get_empty_pinfo();
|
||||||
bool isResending = false;
|
bool isResending = false;
|
||||||
if(!iter->second.priorityPkts.empty()) {
|
if(!iter->second.priorityPkts.empty()) {
|
||||||
// TODO verify getting struct copy is valid
|
// TODO verify getting struct copy is valid
|
||||||
|
@ -515,22 +550,22 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
(pInfo.flags & 0x4) | (isResending ? 0x8 : 0));
|
(pInfo.flags & 0x4) | (isResending ? 0x8 : 0));
|
||||||
std::memcpy(buf.get() + 20, pInfo.data, pInfo.dataSize);
|
std::memcpy(buf.get() + 20, pInfo.data, pInfo.dataSize);
|
||||||
|
|
||||||
struct sockaddr_in destinationInfo;
|
struct sockaddr_in6 destinationInfo;
|
||||||
destinationInfo.sin_family = AF_INET;
|
destinationInfo.sin6_family = AF_INET6;
|
||||||
destinationInfo.sin_addr.s_addr = iter->second.addr;
|
std::memcpy(destinationInfo.sin6_addr.s6_addr, iter->first.addr.s6_addr, 16);
|
||||||
destinationInfo.sin_port = htons(iter->second.port);
|
destinationInfo.sin6_port = htons(iter->second.port);
|
||||||
long int sentBytes = sendto(
|
long int sentBytes = sendto(
|
||||||
c->socketHandle,
|
c->socketHandle,
|
||||||
buf.get(),
|
buf.get(),
|
||||||
pInfo.dataSize + 20,
|
pInfo.dataSize + 20,
|
||||||
0,
|
0,
|
||||||
(struct sockaddr*) &destinationInfo,
|
(struct sockaddr*) &destinationInfo,
|
||||||
sizeof(struct sockaddr_in));
|
sizeof(struct sockaddr_in6));
|
||||||
if(sentBytes != 20 + pInfo.dataSize) {
|
if(sentBytes != 20 + pInfo.dataSize) {
|
||||||
c->log(
|
c->log(
|
||||||
UDPC_LoggingType::ERROR,
|
UDPC_LoggingType::ERROR,
|
||||||
"Failed to send packet to ",
|
"Failed to send packet to ",
|
||||||
UDPC_atostr(ctx, iter->second.addr),
|
UDPC_atostr(ctx, iter->first),
|
||||||
":",
|
":",
|
||||||
iter->second.port);
|
iter->second.port);
|
||||||
continue;
|
continue;
|
||||||
|
@ -538,25 +573,25 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
|
|
||||||
if((pInfo.flags & 0x4) == 0) {
|
if((pInfo.flags & 0x4) == 0) {
|
||||||
// is check-received, store data in case packet gets lost
|
// is check-received, store data in case packet gets lost
|
||||||
UDPC_PacketInfo sentPInfo;
|
UDPC_PacketInfo sentPInfo = UDPC::get_empty_pinfo();
|
||||||
std::memcpy(sentPInfo.data, buf.get(), 20 + pInfo.dataSize);
|
std::memcpy(sentPInfo.data, buf.get(), 20 + pInfo.dataSize);
|
||||||
sentPInfo.flags = 0;
|
sentPInfo.flags = 0;
|
||||||
sentPInfo.dataSize = 20 + pInfo.dataSize;
|
sentPInfo.dataSize = 20 + pInfo.dataSize;
|
||||||
sentPInfo.sender.addr = UDPC::LOCAL_ADDR;
|
sentPInfo.sender.addr = in6addr_loopback;
|
||||||
sentPInfo.receiver.addr = iter->first.addr;
|
sentPInfo.receiver.addr = iter->first.addr;
|
||||||
sentPInfo.sender.port = c->socketInfo.sin_port;
|
sentPInfo.sender.port = c->socketInfo.sin6_port;
|
||||||
sentPInfo.receiver.port = iter->second.port;
|
sentPInfo.receiver.port = iter->second.port;
|
||||||
|
|
||||||
iter->second.sentPkts.push_back(std::move(pInfo));
|
iter->second.sentPkts.push_back(std::move(pInfo));
|
||||||
iter->second.cleanupSentPkts();
|
iter->second.cleanupSentPkts();
|
||||||
} else {
|
} else {
|
||||||
// is not check-received, only id stored in data array
|
// is not check-received, only id stored in data array
|
||||||
UDPC_PacketInfo sentPInfo;
|
UDPC_PacketInfo sentPInfo = UDPC::get_empty_pinfo();
|
||||||
sentPInfo.flags = 0x4;
|
sentPInfo.flags = 0x4;
|
||||||
sentPInfo.dataSize = 0;
|
sentPInfo.dataSize = 0;
|
||||||
sentPInfo.sender.addr = UDPC::LOCAL_ADDR;
|
sentPInfo.sender.addr = in6addr_loopback;
|
||||||
sentPInfo.receiver.addr = iter->first.addr;
|
sentPInfo.receiver.addr = iter->first.addr;
|
||||||
sentPInfo.sender.port = c->socketInfo.sin_port;
|
sentPInfo.sender.port = c->socketInfo.sin6_port;
|
||||||
sentPInfo.receiver.port = iter->second.port;
|
sentPInfo.receiver.port = iter->second.port;
|
||||||
*((uint32_t*)(sentPInfo.data + 8)) = iter->second.lseq - 1;
|
*((uint32_t*)(sentPInfo.data + 8)) = iter->second.lseq - 1;
|
||||||
|
|
||||||
|
@ -575,7 +610,7 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
||||||
typedef int socklen_t;
|
typedef int socklen_t;
|
||||||
#endif
|
#endif
|
||||||
struct sockaddr_in receivedData;
|
struct sockaddr_in6 receivedData;
|
||||||
socklen_t receivedDataSize = sizeof(receivedData);
|
socklen_t receivedDataSize = sizeof(receivedData);
|
||||||
int bytes = recvfrom(
|
int bytes = recvfrom(
|
||||||
c->socketHandle,
|
c->socketHandle,
|
||||||
|
@ -593,9 +628,9 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
c->log(
|
c->log(
|
||||||
UDPC_LoggingType::INFO,
|
UDPC_LoggingType::INFO,
|
||||||
"Received packet is smaller than header, ignoring packet from ",
|
"Received packet is smaller than header, ignoring packet from ",
|
||||||
UDPC_atostr(ctx, receivedData.sin_addr.s_addr),
|
UDPC_atostr(ctx, UDPC_ConnectionId{receivedData.sin6_addr, 0}),
|
||||||
":",
|
":",
|
||||||
receivedData.sin_port);
|
receivedData.sin6_port);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,9 +640,9 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
c->log(
|
c->log(
|
||||||
UDPC_LoggingType::INFO,
|
UDPC_LoggingType::INFO,
|
||||||
"Received packet has invalid protocol id, ignoring packet from ",
|
"Received packet has invalid protocol id, ignoring packet from ",
|
||||||
UDPC_atostr(ctx, receivedData.sin_addr.s_addr),
|
UDPC_atostr(ctx, UDPC_ConnectionId{receivedData.sin6_addr, 0}),
|
||||||
":",
|
":",
|
||||||
receivedData.sin_port);
|
receivedData.sin6_port);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,7 +657,7 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
bool isResending = conID & UDPC_ID_RESENDING;
|
bool isResending = conID & UDPC_ID_RESENDING;
|
||||||
conID &= 0x0FFFFFFF;
|
conID &= 0x0FFFFFFF;
|
||||||
|
|
||||||
UDPC_ConnectionId identifier{receivedData.sin_addr.s_addr, ntohs(receivedData.sin_port)};
|
UDPC_ConnectionId identifier{receivedData.sin6_addr, ntohs(receivedData.sin6_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
|
||||||
|
@ -632,12 +667,12 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
c->log(
|
c->log(
|
||||||
UDPC_LoggingType::VERBOSE,
|
UDPC_LoggingType::VERBOSE,
|
||||||
"Establishing connection with client ",
|
"Establishing connection with client ",
|
||||||
UDPC_atostr(ctx, receivedData.sin_addr.s_addr),
|
UDPC_atostr(ctx, UDPC_ConnectionId{receivedData.sin6_addr, 0}),
|
||||||
":",
|
":",
|
||||||
receivedData.sin_port);
|
receivedData.sin6_port);
|
||||||
UDPC::ConnectionData newConnection(true, c);
|
UDPC::ConnectionData newConnection(true, c);
|
||||||
newConnection.addr = receivedData.sin_addr.s_addr;
|
newConnection.addr = receivedData.sin6_addr;
|
||||||
newConnection.port = ntohs(receivedData.sin_port);
|
newConnection.port = ntohs(receivedData.sin6_port);
|
||||||
|
|
||||||
c->idMap.insert(std::make_pair(newConnection.id, identifier));
|
c->idMap.insert(std::make_pair(newConnection.id, identifier));
|
||||||
c->conMap.insert(std::make_pair(identifier, std::move(newConnection)));
|
c->conMap.insert(std::make_pair(identifier, std::move(newConnection)));
|
||||||
|
@ -666,9 +701,9 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
c->log(
|
c->log(
|
||||||
UDPC_LoggingType::VERBOSE,
|
UDPC_LoggingType::VERBOSE,
|
||||||
"Established connection with server ",
|
"Established connection with server ",
|
||||||
UDPC_atostr(ctx, receivedData.sin_addr.s_addr),
|
UDPC_atostr(ctx, UDPC_ConnectionId{receivedData.sin6_addr, 0}),
|
||||||
":",
|
":",
|
||||||
receivedData.sin_port);
|
receivedData.sin6_port);
|
||||||
// TODO trigger event client established connection with server
|
// TODO trigger event client established connection with server
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -687,9 +722,9 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
c->log(
|
c->log(
|
||||||
UDPC_LoggingType::INFO,
|
UDPC_LoggingType::INFO,
|
||||||
"Received valid packet from ",
|
"Received valid packet from ",
|
||||||
UDPC_atostr(ctx, receivedData.sin_addr.s_addr),
|
UDPC_atostr(ctx, UDPC_ConnectionId{receivedData.sin6_addr, 0}),
|
||||||
":",
|
":",
|
||||||
receivedData.sin_port);
|
receivedData.sin6_port);
|
||||||
|
|
||||||
// update rtt
|
// update rtt
|
||||||
for(auto sentIter = iter->second.sentPkts.rbegin(); sentIter != iter->second.sentPkts.rend(); ++sentIter) {
|
for(auto sentIter = iter->second.sentPkts.rbegin(); sentIter != iter->second.sentPkts.rend(); ++sentIter) {
|
||||||
|
@ -747,7 +782,7 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC_PacketInfo resendingData;
|
UDPC_PacketInfo resendingData = UDPC::get_empty_pinfo();
|
||||||
resendingData.dataSize = sentIter->dataSize - 20;
|
resendingData.dataSize = sentIter->dataSize - 20;
|
||||||
std::memcpy(resendingData.data, sentIter->data + 20, resendingData.dataSize);
|
std::memcpy(resendingData.data, sentIter->data + 20, resendingData.dataSize);
|
||||||
resendingData.flags = 0;
|
resendingData.flags = 0;
|
||||||
|
@ -816,7 +851,7 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bytes > 20) {
|
if(bytes > 20) {
|
||||||
UDPC_PacketInfo recPktInfo;
|
UDPC_PacketInfo recPktInfo = UDPC::get_empty_pinfo();
|
||||||
std::memcpy(recPktInfo.data, c->recvBuf, bytes);
|
std::memcpy(recPktInfo.data, c->recvBuf, bytes);
|
||||||
recPktInfo.dataSize = bytes;
|
recPktInfo.dataSize = bytes;
|
||||||
recPktInfo.flags =
|
recPktInfo.flags =
|
||||||
|
@ -824,10 +859,10 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
| (isPing ? 0x2 : 0)
|
| (isPing ? 0x2 : 0)
|
||||||
| (isNotRecChecked ? 0x4 : 0)
|
| (isNotRecChecked ? 0x4 : 0)
|
||||||
| (isResending ? 0x8 : 0);
|
| (isResending ? 0x8 : 0);
|
||||||
recPktInfo.sender.addr = receivedData.sin_addr.s_addr;
|
recPktInfo.sender.addr = receivedData.sin6_addr;
|
||||||
recPktInfo.receiver.addr = UDPC::LOCAL_ADDR;
|
recPktInfo.receiver.addr = in6addr_loopback;
|
||||||
recPktInfo.sender.port = receivedData.sin_port;
|
recPktInfo.sender.port = receivedData.sin6_port;
|
||||||
recPktInfo.receiver.port = c->socketInfo.sin_port;
|
recPktInfo.receiver.port = c->socketInfo.sin6_port;
|
||||||
|
|
||||||
if(iter->second.receivedPkts.size() == iter->second.receivedPkts.capacity()) {
|
if(iter->second.receivedPkts.size() == iter->second.receivedPkts.capacity()) {
|
||||||
c->log(
|
c->log(
|
||||||
|
@ -844,38 +879,35 @@ void UDPC_update(UDPC_HContext ctx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDPC_client_initiate_connection(UDPC_HContext ctx, uint32_t addr, uint16_t port) {
|
void UDPC_client_initiate_connection(UDPC_HContext ctx, UDPC_ConnectionId connectionId) {
|
||||||
UDPC::Context *c = UDPC::verifyContext(ctx);
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
||||||
if(!c || !c->flags.test(1)) {
|
if(!c || !c->flags.test(1)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC::ConnectionData newCon(false, c);
|
UDPC::ConnectionData newCon(false, c);
|
||||||
UDPC_ConnectionId identifier{addr, port};
|
|
||||||
|
|
||||||
// TODO make thread safe by using mutex
|
// TODO make thread safe by using mutex
|
||||||
c->conMap.insert(std::make_pair(identifier, std::move(newCon)));
|
c->conMap.insert(std::make_pair(connectionId, std::move(newCon)));
|
||||||
auto addrConIter = c->addrConMap.find(addr);
|
auto addrConIter = c->addrConMap.find(connectionId.addr);
|
||||||
if(addrConIter == c->addrConMap.end()) {
|
if(addrConIter == c->addrConMap.end()) {
|
||||||
auto insertResult = c->addrConMap.insert(std::make_pair(
|
auto insertResult = c->addrConMap.insert(std::make_pair(
|
||||||
addr,
|
connectionId.addr,
|
||||||
std::unordered_set<UDPC_ConnectionId, UDPC::ConnectionIdHasher>{}
|
std::unordered_set<UDPC_ConnectionId, UDPC::ConnectionIdHasher>{}
|
||||||
));
|
));
|
||||||
assert(insertResult.second);
|
assert(insertResult.second);
|
||||||
addrConIter = insertResult.first;
|
addrConIter = insertResult.first;
|
||||||
}
|
}
|
||||||
addrConIter->second.insert(identifier);
|
addrConIter->second.insert(connectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
int UDPC_get_queue_send_available(UDPC_HContext ctx, uint32_t addr, uint16_t port) {
|
int UDPC_get_queue_send_available(UDPC_HContext ctx, UDPC_ConnectionId connectionId) {
|
||||||
UDPC::Context *c = UDPC::verifyContext(ctx);
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
||||||
if(!c) {
|
if(!c) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC_ConnectionId identifier{addr, port};
|
auto iter = c->conMap.find(connectionId);
|
||||||
|
|
||||||
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 {
|
||||||
|
@ -883,7 +915,7 @@ int UDPC_get_queue_send_available(UDPC_HContext ctx, uint32_t addr, uint16_t por
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDPC_queue_send(UDPC_HContext ctx, uint32_t destAddr, uint16_t destPort,
|
void UDPC_queue_send(UDPC_HContext ctx, UDPC_ConnectionId destinationId,
|
||||||
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;
|
||||||
|
@ -894,9 +926,7 @@ void UDPC_queue_send(UDPC_HContext ctx, uint32_t destAddr, uint16_t destPort,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC_ConnectionId identifier{destAddr, destPort};
|
auto iter = c->conMap.find(destinationId);
|
||||||
|
|
||||||
auto iter = c->conMap.find(identifier);
|
|
||||||
if(iter == c->conMap.end()) {
|
if(iter == c->conMap.end()) {
|
||||||
c->log(
|
c->log(
|
||||||
UDPC_LoggingType::ERROR,
|
UDPC_LoggingType::ERROR,
|
||||||
|
@ -905,12 +935,12 @@ void UDPC_queue_send(UDPC_HContext ctx, uint32_t destAddr, uint16_t destPort,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC_PacketInfo sendInfo;
|
UDPC_PacketInfo sendInfo = UDPC::get_empty_pinfo();
|
||||||
std::memcpy(sendInfo.data, data, size);
|
std::memcpy(sendInfo.data, data, size);
|
||||||
sendInfo.dataSize = size;
|
sendInfo.dataSize = size;
|
||||||
sendInfo.sender.addr = UDPC::LOCAL_ADDR;
|
sendInfo.sender.addr = in6addr_loopback;
|
||||||
sendInfo.sender.port = c->socketInfo.sin_port;
|
sendInfo.sender.port = c->socketInfo.sin6_port;
|
||||||
sendInfo.receiver.addr = destAddr;
|
sendInfo.receiver.addr = destinationId.addr;
|
||||||
sendInfo.receiver.port = iter->second.port;
|
sendInfo.receiver.port = iter->second.port;
|
||||||
sendInfo.flags = (isChecked ? 0x0 : 0x4);
|
sendInfo.flags = (isChecked ? 0x0 : 0x4);
|
||||||
|
|
||||||
|
@ -925,40 +955,14 @@ int UDPC_set_accept_new_connections(UDPC_HContext ctx, int isAccepting) {
|
||||||
return c->isAcceptNewConnections.exchange(isAccepting == 0 ? false : true);
|
return c->isAcceptNewConnections.exchange(isAccepting == 0 ? false : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int UDPC_drop_connection(UDPC_HContext ctx, uint32_t addr, uint16_t port) {
|
int UDPC_drop_connection(UDPC_HContext ctx, UDPC_ConnectionId connectionId, bool dropAllWithAddr) {
|
||||||
UDPC::Context *c = UDPC::verifyContext(ctx);
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
||||||
if(!c) {
|
if(!c) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC_ConnectionId identifier{addr, port};
|
if(dropAllWithAddr) {
|
||||||
|
auto addrConIter = c->addrConMap.find(connectionId.addr);
|
||||||
auto iter = c->conMap.find(identifier);
|
|
||||||
if(iter != c->conMap.end()) {
|
|
||||||
if(iter->second.flags.test(4)) {
|
|
||||||
c->idMap.erase(iter->second.id);
|
|
||||||
}
|
|
||||||
auto addrConIter = c->addrConMap.find(addr);
|
|
||||||
if(addrConIter != c->addrConMap.end()) {
|
|
||||||
addrConIter->second.erase(identifier);
|
|
||||||
if(addrConIter->second.empty()) {
|
|
||||||
c->addrConMap.erase(addrConIter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c->conMap.erase(iter);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int UDPC_drop_connection_addr(UDPC_HContext ctx, uint32_t addr) {
|
|
||||||
UDPC::Context *c = UDPC::verifyContext(ctx);
|
|
||||||
if(!c) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto addrConIter = c->addrConMap.find(addr);
|
|
||||||
if(addrConIter != c->addrConMap.end()) {
|
if(addrConIter != c->addrConMap.end()) {
|
||||||
for(auto identIter = addrConIter->second.begin();
|
for(auto identIter = addrConIter->second.begin();
|
||||||
identIter != addrConIter->second.end();
|
identIter != addrConIter->second.end();
|
||||||
|
@ -973,6 +977,23 @@ int UDPC_drop_connection_addr(UDPC_HContext ctx, uint32_t addr) {
|
||||||
c->addrConMap.erase(addrConIter);
|
c->addrConMap.erase(addrConIter);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
auto iter = c->conMap.find(connectionId);
|
||||||
|
if(iter != c->conMap.end()) {
|
||||||
|
if(iter->second.flags.test(4)) {
|
||||||
|
c->idMap.erase(iter->second.id);
|
||||||
|
}
|
||||||
|
auto addrConIter = c->addrConMap.find(connectionId.addr);
|
||||||
|
if(addrConIter != c->addrConMap.end()) {
|
||||||
|
addrConIter->second.erase(connectionId);
|
||||||
|
if(addrConIter->second.empty()) {
|
||||||
|
c->addrConMap.erase(addrConIter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c->conMap.erase(iter);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -996,13 +1017,13 @@ UDPC_LoggingType set_logging_type(UDPC_HContext ctx, UDPC_LoggingType loggingTyp
|
||||||
UDPC_PacketInfo UDPC_get_received(UDPC_HContext ctx) {
|
UDPC_PacketInfo UDPC_get_received(UDPC_HContext ctx) {
|
||||||
UDPC::Context *c = UDPC::verifyContext(ctx);
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
||||||
if(!c) {
|
if(!c) {
|
||||||
return UDPC_PacketInfo{{0}, 0, 0, 0, 0, 0, 0};
|
return UDPC::get_empty_pinfo();
|
||||||
}
|
}
|
||||||
// TODO impl
|
// TODO impl
|
||||||
return UDPC_PacketInfo{{0}, 0, 0, 0, 0, 0, 0};
|
return UDPC::get_empty_pinfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *UDPC_atostr(UDPC_HContext ctx, uint32_t addr) {
|
const char *UDPC_atostr(UDPC_HContext ctx, UDPC_ConnectionId connectionId) {
|
||||||
UDPC::Context *c = UDPC::verifyContext(ctx);
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
||||||
if(!c) {
|
if(!c) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1010,55 +1031,220 @@ const char *UDPC_atostr(UDPC_HContext ctx, uint32_t addr) {
|
||||||
const uint32_t headIndex =
|
const uint32_t headIndex =
|
||||||
c->atostrBufIndex.fetch_add(UDPC_ATOSTR_BUFSIZE) % UDPC_ATOSTR_SIZE;
|
c->atostrBufIndex.fetch_add(UDPC_ATOSTR_BUFSIZE) % UDPC_ATOSTR_SIZE;
|
||||||
uint32_t index = headIndex;
|
uint32_t index = headIndex;
|
||||||
for(int x = 0; x < 4; ++x) {
|
bool usedDouble = false;
|
||||||
unsigned char temp = (addr >> (x * 8)) & 0xFF;
|
|
||||||
|
|
||||||
if(temp >= 100) {
|
for(unsigned int i = 0; i < 16; ++i) {
|
||||||
c->atostrBuf[index++] = '0' + temp / 100;
|
if(i != 0 && i % 2 == 0) {
|
||||||
|
if(headIndex - index > 1 && c->atostrBuf[index - 1] == ':') {
|
||||||
|
if(usedDouble) {
|
||||||
|
if(c->atostrBuf[index - 2] != ':') {
|
||||||
|
c->atostrBuf[index++] = '0';
|
||||||
|
c->atostrBuf[index++] = ':';
|
||||||
|
} else {
|
||||||
|
// continue use of double :, do nothing here
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
usedDouble = true;
|
||||||
|
c->atostrBuf[index++] = ':';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c->atostrBuf[index++] = ':';
|
||||||
}
|
}
|
||||||
if(temp >= 10) {
|
|
||||||
c->atostrBuf[index++] = '0' + ((temp / 10) % 10);
|
|
||||||
}
|
}
|
||||||
c->atostrBuf[index++] = '0' + temp % 10;
|
|
||||||
|
|
||||||
if(x < 3) {
|
if(connectionId.addr.s6_addr[i] == 0) {
|
||||||
c->atostrBuf[index++] = '.';
|
continue;
|
||||||
|
} else {
|
||||||
|
std::stringstream sstream;
|
||||||
|
sstream << std::hex << (unsigned int) connectionId.addr.s6_addr[i];
|
||||||
|
std::string out(sstream.str());
|
||||||
|
if(out.size() == 1) {
|
||||||
|
if(out[0] != '0') {
|
||||||
|
std::memcpy(c->atostrBuf + index, out.c_str(), 1);
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::memcpy(c->atostrBuf + index, out.c_str(), 2);
|
||||||
|
index += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if(c->atostrBuf[index - 1] == ':'
|
||||||
|
&& (headIndex - index <= 2 || c->atostrBuf[index - 2] != ':')) {
|
||||||
|
c->atostrBuf[index++] = '0';
|
||||||
|
}
|
||||||
|
|
||||||
c->atostrBuf[index] = 0;
|
c->atostrBuf[index] = 0;
|
||||||
|
|
||||||
return c->atostrBuf + headIndex;
|
return c->atostrBuf + headIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t UDPC_strtoa(const char *addrStr) {
|
struct in6_addr UDPC_strtoa(const char *addrStr) {
|
||||||
uint32_t addr = 0;
|
struct in6_addr result{{0}};
|
||||||
uint32_t temp = 0;
|
unsigned int index = 0;
|
||||||
uint32_t index = 0;
|
unsigned int strIndex = 0;
|
||||||
while(*addrStr != 0) {
|
int doubleColonIndex = -1;
|
||||||
if(*addrStr >= '0' && *addrStr <= '9') {
|
unsigned char bytes[2] = {0, 0};
|
||||||
temp *= 10;
|
unsigned char bytesState = 0;
|
||||||
temp += *addrStr - '0';
|
bool prevColon = false;
|
||||||
} else if(*addrStr == '.' && temp <= 0xFF && index < 3) {
|
|
||||||
if(UDPC::isBigEndian()) {
|
const auto checkInc = [&result, &index, &bytes] () -> bool {
|
||||||
addr |= (temp << (24 - 8 * index++));
|
if(index < 15) {
|
||||||
} else {
|
result.s6_addr[index++] = bytes[0];
|
||||||
addr |= (temp << (8 * index++));
|
result.s6_addr[index++] = bytes[1];
|
||||||
|
bytes[0] = 0;
|
||||||
|
bytes[1] = 0;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
temp = 0;
|
return true;
|
||||||
} else {
|
};
|
||||||
return 0;
|
|
||||||
|
while(addrStr[strIndex] != '\0') {
|
||||||
|
if(addrStr[strIndex] >= '0' && addrStr[strIndex] <= '9') {
|
||||||
|
switch(bytesState) {
|
||||||
|
case 0:
|
||||||
|
bytes[0] = (addrStr[strIndex] - '0');
|
||||||
|
bytesState = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
bytes[0] = (bytes[0] << 4) | (addrStr[strIndex] - '0');
|
||||||
|
bytesState = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
bytes[1] = (addrStr[strIndex] - '0');
|
||||||
|
bytesState = 3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
bytes[1] = (bytes[1] << 4) | (addrStr[strIndex] - '0');
|
||||||
|
bytesState = 0;
|
||||||
|
if(checkInc()) {
|
||||||
|
return in6addr_loopback;
|
||||||
}
|
}
|
||||||
++addrStr;
|
break;
|
||||||
|
default:
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
prevColon = false;
|
||||||
|
} else if(addrStr[strIndex] >= 'a' && addrStr[strIndex] <= 'f') {
|
||||||
|
switch(bytesState) {
|
||||||
|
case 0:
|
||||||
|
bytes[0] = (addrStr[strIndex] - 'a' + 10);
|
||||||
|
bytesState = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
bytes[0] = (bytes[0] << 4) | (addrStr[strIndex] - 'a' + 10);
|
||||||
|
bytesState = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
bytes[1] = (addrStr[strIndex] - 'a' + 10);
|
||||||
|
bytesState = 3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
bytes[1] = (bytes[1] << 4) | (addrStr[strIndex] - 'a' + 10);
|
||||||
|
bytesState = 0;
|
||||||
|
if(checkInc()) {
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
prevColon = false;
|
||||||
|
} else if(addrStr[strIndex] >= 'A' && addrStr[strIndex] <= 'F') {
|
||||||
|
switch(bytesState) {
|
||||||
|
case 0:
|
||||||
|
bytes[0] = (addrStr[strIndex] - 'A' + 10);
|
||||||
|
bytesState = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
bytes[0] = (bytes[0] << 4) | (addrStr[strIndex] - 'A' + 10);
|
||||||
|
bytesState = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
bytes[1] = (addrStr[strIndex] - 'A' + 10);
|
||||||
|
bytesState = 3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
bytes[1] = (bytes[1] << 4) | (addrStr[strIndex] - 'A' + 10);
|
||||||
|
bytesState = 0;
|
||||||
|
if(checkInc()) {
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
prevColon = false;
|
||||||
|
} else if(addrStr[strIndex] == ':') {
|
||||||
|
switch(bytesState) {
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
bytes[1] = bytes[0];
|
||||||
|
bytes[0] = 0;
|
||||||
|
if(checkInc()) {
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
bytes[1] |= (bytes[0] & 0xF) << 4;
|
||||||
|
bytes[0] = bytes[0] >> 4;
|
||||||
|
if(checkInc()) {
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
bytesState = 0;
|
||||||
|
if(prevColon) {
|
||||||
|
if(doubleColonIndex >= 0) {
|
||||||
|
return in6addr_loopback;
|
||||||
|
} else {
|
||||||
|
doubleColonIndex = index;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
prevColon = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return in6addr_loopback;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(index == 3 && temp <= 0xFF) {
|
++strIndex;
|
||||||
if(UDPC::isBigEndian()) {
|
|
||||||
addr |= temp;
|
|
||||||
} else {
|
|
||||||
addr |= temp << 24;
|
|
||||||
}
|
}
|
||||||
return addr;
|
switch(bytesState) {
|
||||||
} else {
|
case 1:
|
||||||
return 0;
|
case 2:
|
||||||
|
bytes[1] = bytes[0];
|
||||||
|
bytes[0] = 0;
|
||||||
|
if(checkInc()) {
|
||||||
|
return in6addr_loopback;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
bytes[1] |= (bytes[0] & 0xF) << 4;
|
||||||
|
bytes[0] = bytes[0] >> 4;
|
||||||
|
if(checkInc()) {
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(doubleColonIndex >= 0) {
|
||||||
|
strIndex = 16 - index;
|
||||||
|
if(strIndex < 2) {
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
for(unsigned int i = 16; i-- > (unsigned int)doubleColonIndex + strIndex; ) {
|
||||||
|
result.s6_addr[i] = result.s6_addr[i - strIndex];
|
||||||
|
result.s6_addr[i - strIndex] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ typedef struct UDPC_Context *UDPC_HContext;
|
||||||
typedef enum { SILENT, ERROR, WARNING, VERBOSE, INFO } UDPC_LoggingType;
|
typedef enum { SILENT, ERROR, WARNING, VERBOSE, INFO } UDPC_LoggingType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t addr;
|
struct in6_addr addr;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
} UDPC_ConnectionId;
|
} UDPC_ConnectionId;
|
||||||
|
|
||||||
|
@ -70,35 +70,29 @@ typedef struct {
|
||||||
UDPC_ConnectionId receiver;
|
UDPC_ConnectionId receiver;
|
||||||
} UDPC_PacketInfo;
|
} UDPC_PacketInfo;
|
||||||
|
|
||||||
UDPC_ConnectionId UDPC_create_id(uint32_t addr, uint16_t port);
|
/// port should be in native byte order (not network/big-endian)
|
||||||
|
UDPC_ConnectionId UDPC_create_id(struct in6_addr addr, uint16_t port);
|
||||||
|
|
||||||
/// listenPort must be in native byte order, listenAddr must be in network byte order (big-endian)
|
UDPC_ConnectionId UDPC_create_id_anyaddr(uint16_t port);
|
||||||
UDPC_HContext 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)
|
UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient);
|
||||||
UDPC_HContext UDPC_init_threaded_update(uint16_t listenPort, uint32_t listenAddr,
|
UDPC_HContext UDPC_init_threaded_update(UDPC_ConnectionId listenId,
|
||||||
int isClient);
|
int isClient);
|
||||||
|
|
||||||
void UDPC_destroy(UDPC_HContext ctx);
|
void UDPC_destroy(UDPC_HContext ctx);
|
||||||
|
|
||||||
void UDPC_update(UDPC_HContext ctx);
|
void UDPC_update(UDPC_HContext ctx);
|
||||||
|
|
||||||
/// addr must be in network byte order (big-endian), port must be in native byte order
|
void UDPC_client_initiate_connection(UDPC_HContext ctx, UDPC_ConnectionId connectionId);
|
||||||
void UDPC_client_initiate_connection(UDPC_HContext ctx, uint32_t addr, uint16_t port);
|
|
||||||
|
|
||||||
/// addr must be in network byte order (big-endian), port must be in native byte order
|
int UDPC_get_queue_send_available(UDPC_HContext ctx, UDPC_ConnectionId connectionId);
|
||||||
int UDPC_get_queue_send_available(UDPC_HContext ctx, uint32_t addr, uint16_t port);
|
|
||||||
|
|
||||||
/// destAddr must be in network byte order (big-endian), destPort must be in native byte order
|
void UDPC_queue_send(UDPC_HContext ctx, UDPC_ConnectionId destinationId,
|
||||||
void UDPC_queue_send(UDPC_HContext 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(UDPC_HContext ctx, int isAccepting);
|
int UDPC_set_accept_new_connections(UDPC_HContext ctx, int isAccepting);
|
||||||
|
|
||||||
/// addr must be in network byte order (big-endian), port must be in native byte order
|
int UDPC_drop_connection(UDPC_HContext ctx, UDPC_ConnectionId connectionId, bool dropAllWithAddr);
|
||||||
int UDPC_drop_connection(UDPC_HContext ctx, uint32_t addr, uint16_t port);
|
|
||||||
|
|
||||||
/// addr must be in network byte order, drops all connections to specified addr
|
|
||||||
int UDPC_drop_connection_addr(UDPC_HContext ctx, uint32_t addr);
|
|
||||||
|
|
||||||
uint32_t UDPC_set_protocol_id(UDPC_HContext ctx, uint32_t id);
|
uint32_t UDPC_set_protocol_id(UDPC_HContext ctx, uint32_t id);
|
||||||
|
|
||||||
|
@ -106,11 +100,9 @@ UDPC_LoggingType set_logging_type(UDPC_HContext ctx, UDPC_LoggingType loggingTyp
|
||||||
|
|
||||||
UDPC_PacketInfo UDPC_get_received(UDPC_HContext ctx);
|
UDPC_PacketInfo UDPC_get_received(UDPC_HContext ctx);
|
||||||
|
|
||||||
/// addr must be in network byte order
|
const char *UDPC_atostr(UDPC_HContext ctx, UDPC_ConnectionId connectionId);
|
||||||
const char *UDPC_atostr(UDPC_HContext ctx, uint32_t addr);
|
|
||||||
|
|
||||||
/// returns a 4 byte unsigned integer address in network byte order
|
struct in6_addr UDPC_strtoa(const char *addrStr);
|
||||||
uint32_t UDPC_strtoa(const char *addrStr);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,108 +9,167 @@
|
||||||
TEST(UDPC, atostr) {
|
TEST(UDPC, atostr) {
|
||||||
UDPC::Context context(false);
|
UDPC::Context context(false);
|
||||||
|
|
||||||
|
UDPC_ConnectionId conId;
|
||||||
const char* resultBuf;
|
const char* resultBuf;
|
||||||
|
|
||||||
resultBuf = UDPC_atostr((UDPC_HContext)&context, 0x0100007F);
|
for(unsigned int i = 0; i < 16; ++i) {
|
||||||
EXPECT_EQ(std::strcmp(resultBuf, "127.0.0.1"), 0);
|
conId.addr.s6_addr[i] = (i % 3 == 0 ? 0xFF : (i % 3 == 1 ? 0x12 : 0x56));
|
||||||
|
}
|
||||||
|
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId);
|
||||||
|
EXPECT_STREQ(resultBuf, "ff12:56ff:1256:ff12:56ff:1256:ff12:56ff");
|
||||||
|
|
||||||
resultBuf = UDPC_atostr((UDPC_HContext)&context, 0xFF08000A);
|
for(unsigned int i = 0; i < 8; ++i) {
|
||||||
EXPECT_EQ(std::strcmp(resultBuf, "10.0.8.255"), 0);
|
conId.addr.s6_addr[i] = 0;
|
||||||
|
}
|
||||||
|
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId);
|
||||||
|
EXPECT_STREQ(resultBuf, "::56ff:1256:ff12:56ff");
|
||||||
|
|
||||||
resultBuf = UDPC_atostr((UDPC_HContext)&context, 0x0201A8C0);
|
conId.addr.s6_addr[0] = 1;
|
||||||
EXPECT_EQ(std::strcmp(resultBuf, "192.168.1.2"), 0);
|
conId.addr.s6_addr[1] = 2;
|
||||||
|
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId);
|
||||||
|
EXPECT_STREQ(resultBuf, "12::56ff:1256:ff12:56ff");
|
||||||
|
|
||||||
|
conId.addr.s6_addr[14] = 0;
|
||||||
|
conId.addr.s6_addr[15] = 0;
|
||||||
|
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId);
|
||||||
|
EXPECT_STREQ(resultBuf, "12::56ff:1256:ff12:0");
|
||||||
|
|
||||||
|
for(unsigned int i = 0; i < 15; ++i) {
|
||||||
|
conId.addr.s6_addr[i] = 0;
|
||||||
|
}
|
||||||
|
conId.addr.s6_addr[15] = 1;
|
||||||
|
|
||||||
|
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId);
|
||||||
|
EXPECT_STREQ(resultBuf, "::1");
|
||||||
|
|
||||||
|
conId.addr.s6_addr[15] = 0;
|
||||||
|
|
||||||
|
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId);
|
||||||
|
EXPECT_STREQ(resultBuf, "::");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UDPC, atostr_concurrent) {
|
TEST(UDPC, atostr_concurrent) {
|
||||||
UDPC::Context context(false);
|
UDPC::Context context(false);
|
||||||
|
|
||||||
const char* results[64] = {
|
const char* results[64] = {
|
||||||
"0.0.0.0",
|
"::1111:1",
|
||||||
"1.1.1.1",
|
"::1111:2",
|
||||||
"2.2.2.2",
|
"::1111:3",
|
||||||
"3.3.3.3",
|
"::1111:4",
|
||||||
"4.4.4.4",
|
"::1111:5",
|
||||||
"5.5.5.5",
|
"::1111:6",
|
||||||
"6.6.6.6",
|
"::1111:7",
|
||||||
"7.7.7.7",
|
"::1111:8",
|
||||||
"8.8.8.8",
|
"::1111:9",
|
||||||
"9.9.9.9",
|
"::1111:a",
|
||||||
"10.10.10.10",
|
"::1111:b",
|
||||||
"11.11.11.11",
|
"::1111:c",
|
||||||
"12.12.12.12",
|
"::1111:d",
|
||||||
"13.13.13.13",
|
"::1111:e",
|
||||||
"14.14.14.14",
|
"::1111:f",
|
||||||
"15.15.15.15",
|
"::1111:10",
|
||||||
"16.16.16.16",
|
"::1111:11",
|
||||||
"17.17.17.17",
|
"::1111:12",
|
||||||
"18.18.18.18",
|
"::1111:13",
|
||||||
"19.19.19.19",
|
"::1111:14",
|
||||||
"20.20.20.20",
|
"::1111:15",
|
||||||
"21.21.21.21",
|
"::1111:16",
|
||||||
"22.22.22.22",
|
"::1111:17",
|
||||||
"23.23.23.23",
|
"::1111:18",
|
||||||
"24.24.24.24",
|
"::1111:19",
|
||||||
"25.25.25.25",
|
"::1111:1a",
|
||||||
"26.26.26.26",
|
"::1111:1b",
|
||||||
"27.27.27.27",
|
"::1111:1c",
|
||||||
"28.28.28.28",
|
"::1111:1d",
|
||||||
"29.29.29.29",
|
"::1111:1e",
|
||||||
"30.30.30.30",
|
"::1111:1f",
|
||||||
"31.31.31.31",
|
"::1111:20",
|
||||||
"32.32.32.32",
|
"::1111:21",
|
||||||
"33.33.33.33",
|
"::1111:22",
|
||||||
"34.34.34.34",
|
"::1111:23",
|
||||||
"35.35.35.35",
|
"::1111:24",
|
||||||
"36.36.36.36",
|
"::1111:25",
|
||||||
"37.37.37.37",
|
"::1111:26",
|
||||||
"38.38.38.38",
|
"::1111:27",
|
||||||
"39.39.39.39",
|
"::1111:28",
|
||||||
"40.40.40.40",
|
"::1111:29",
|
||||||
"41.41.41.41",
|
"::1111:2a",
|
||||||
"42.42.42.42",
|
"::1111:2b",
|
||||||
"43.43.43.43",
|
"::1111:2c",
|
||||||
"44.44.44.44",
|
"::1111:2d",
|
||||||
"45.45.45.45",
|
"::1111:2e",
|
||||||
"46.46.46.46",
|
"::1111:2f",
|
||||||
"47.47.47.47",
|
"::1111:30",
|
||||||
"48.48.48.48",
|
"::1111:31",
|
||||||
"49.49.49.49",
|
"::1111:32",
|
||||||
"50.50.50.50",
|
"::1111:33",
|
||||||
"51.51.51.51",
|
"::1111:34",
|
||||||
"52.52.52.52",
|
"::1111:35",
|
||||||
"53.53.53.53",
|
"::1111:36",
|
||||||
"54.54.54.54",
|
"::1111:37",
|
||||||
"55.55.55.55",
|
"::1111:38",
|
||||||
"56.56.56.56",
|
"::1111:39",
|
||||||
"57.57.57.57",
|
"::1111:3a",
|
||||||
"58.58.58.58",
|
"::1111:3b",
|
||||||
"59.59.59.59",
|
"::1111:3c",
|
||||||
"60.60.60.60",
|
"::1111:3d",
|
||||||
"61.61.61.61",
|
"::1111:3e",
|
||||||
"62.62.62.62",
|
"::1111:3f",
|
||||||
"63.63.63.63"
|
"::1111:40"
|
||||||
};
|
};
|
||||||
|
|
||||||
std::future<void> futures[64];
|
std::future<void> futures[32];
|
||||||
const char* ptrs[64];
|
const char* ptrs[32];
|
||||||
for(unsigned int i = 0; i < 2; ++i) {
|
for(unsigned int i = 0; i < 2; ++i) {
|
||||||
for(unsigned int j = 0; j < 64; ++j) {
|
for(unsigned int j = 0; j < 32; ++j) {
|
||||||
futures[j] = std::async(std::launch::async, [] (unsigned int id, const char** ptr, UDPC::Context* c) {
|
futures[j] = std::async(std::launch::async, [] (unsigned int id, const char** ptr, UDPC::Context* c) {
|
||||||
ptr[id] = UDPC_atostr((UDPC_HContext)c, id | (id << 8) | (id << 16) | (id << 24));
|
UDPC_ConnectionId conId = {
|
||||||
|
{0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
0x11, 0x11, 0x0, (unsigned char)(id + 1)},
|
||||||
|
0
|
||||||
|
};
|
||||||
|
ptr[id] = UDPC_atostr((UDPC_HContext)c, conId);
|
||||||
}, j, ptrs, &context);
|
}, j, ptrs, &context);
|
||||||
}
|
}
|
||||||
for(unsigned int j = 0; j < 64; ++j) {
|
for(unsigned int j = 0; j < 32; ++j) {
|
||||||
ASSERT_TRUE(futures[j].valid());
|
ASSERT_TRUE(futures[j].valid());
|
||||||
futures[j].wait();
|
futures[j].wait();
|
||||||
}
|
}
|
||||||
for(unsigned int j = 0; j < 64; ++j) {
|
for(unsigned int j = 0; j < 32; ++j) {
|
||||||
EXPECT_EQ(std::strcmp(ptrs[j], results[j]), 0);
|
EXPECT_STREQ(ptrs[j], results[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(UDPC, strtoa) {
|
TEST(UDPC, strtoa) {
|
||||||
EXPECT_EQ(UDPC_strtoa("127.0.0.1"), 0x0100007F);
|
struct in6_addr addr;
|
||||||
EXPECT_EQ(UDPC_strtoa("10.0.8.255"), 0xFF08000A);
|
|
||||||
EXPECT_EQ(UDPC_strtoa("192.168.1.2"), 0x0201A8C0);
|
for(unsigned int i = 0; i < 16; ++i) {
|
||||||
|
addr.s6_addr[i] = 0;
|
||||||
|
}
|
||||||
|
addr.s6_addr[15] = 1;
|
||||||
|
|
||||||
|
EXPECT_EQ(UDPC_strtoa("::1"), addr);
|
||||||
|
|
||||||
|
// check invalid
|
||||||
|
EXPECT_EQ(UDPC_strtoa("1:1::1:1::1"), addr);
|
||||||
|
EXPECT_EQ(UDPC_strtoa("derpadoodle"), addr);
|
||||||
|
|
||||||
|
addr = {
|
||||||
|
0xF0, 0xF, 0x0, 0x1,
|
||||||
|
0x56, 0x78, 0x9A, 0xBC,
|
||||||
|
0xDE, 0xFF, 0x1, 0x2,
|
||||||
|
0x3, 0x4, 0x5, 0x6
|
||||||
|
};
|
||||||
|
EXPECT_EQ(UDPC_strtoa("F00F:1:5678:9abc:deff:102:304:506"), addr);
|
||||||
|
|
||||||
|
addr = {
|
||||||
|
0x0, 0xFF, 0x1, 0x0,
|
||||||
|
0x0, 0x1, 0x10, 0x0,
|
||||||
|
0x0, 0x0, 0x0, 0x0,
|
||||||
|
0x12, 0x34, 0xab, 0xcd
|
||||||
|
};
|
||||||
|
EXPECT_EQ(UDPC_strtoa("ff:100:1:1000::1234:abcd"), addr);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue