Add support for link-local ipv6 addr
This commit is contained in:
parent
31c40d4739
commit
355f3b2bd0
5 changed files with 294 additions and 44 deletions
|
@ -69,7 +69,7 @@ struct IPV6_Hasher {
|
||||||
|
|
||||||
struct ConnectionData {
|
struct ConnectionData {
|
||||||
ConnectionData();
|
ConnectionData();
|
||||||
ConnectionData(bool isServer, Context *ctx, struct in6_addr addr, uint16_t port);
|
ConnectionData(bool isServer, Context *ctx, struct in6_addr addr, uint32_t scope_id, uint16_t port);
|
||||||
|
|
||||||
// copy
|
// copy
|
||||||
ConnectionData(const ConnectionData& other) = delete;
|
ConnectionData(const ConnectionData& other) = delete;
|
||||||
|
@ -98,6 +98,7 @@ struct ConnectionData {
|
||||||
std::chrono::steady_clock::duration toggleTimer;
|
std::chrono::steady_clock::duration toggleTimer;
|
||||||
std::chrono::steady_clock::duration toggledTimer;
|
std::chrono::steady_clock::duration toggledTimer;
|
||||||
struct in6_addr addr; // in network order
|
struct in6_addr addr; // in network order
|
||||||
|
uint32_t scope_id;
|
||||||
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;
|
||||||
|
|
|
@ -12,11 +12,13 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
static std::regex ipv6_regex = std::regex(R"d((([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))d");
|
//static const std::regex ipv6_regex = std::regex(R"d((([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))d");
|
||||||
// TODO remove ipv6_regex_nolink when link device is supported
|
static const std::regex ipv6_regex_nolink = std::regex(R"d((([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))d");
|
||||||
static std::regex ipv6_regex_nolink = std::regex(R"d((([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])))d");
|
static const std::regex ipv6_regex_linkonly = std::regex(R"d(fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,})d");
|
||||||
static std::regex ipv4_regex = std::regex(R"d((1[0-9][0-9]|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9])\.(1[0-9][0-9]|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9])\.(1[0-9][0-9]|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9])\.(1[0-9][0-9]|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9]))d");
|
static const std::regex ipv4_regex = std::regex(R"d((1[0-9][0-9]|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9])\.(1[0-9][0-9]|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9])\.(1[0-9][0-9]|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9])\.(1[0-9][0-9]|2[0-4][0-9]|25[0-5]|[1-9][0-9]|[0-9]))d");
|
||||||
|
|
||||||
UDPC::SentPktInfo::SentPktInfo() :
|
UDPC::SentPktInfo::SentPktInfo() :
|
||||||
id(0),
|
id(0),
|
||||||
|
@ -25,6 +27,10 @@ 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 {
|
||||||
std::string value((const char*)key.addr.s6_addr, 16);
|
std::string value((const char*)key.addr.s6_addr, 16);
|
||||||
|
value.push_back((char)((key.scope_id >> 24) & 0xFF));
|
||||||
|
value.push_back((char)((key.scope_id >> 16) & 0xFF));
|
||||||
|
value.push_back((char)((key.scope_id >> 8) & 0xFF));
|
||||||
|
value.push_back((char)(key.scope_id & 0xFF));
|
||||||
value.push_back((char)((key.port >> 8) & 0xFF));
|
value.push_back((char)((key.port >> 8) & 0xFF));
|
||||||
value.push_back((char)(key.port & 0xFF));
|
value.push_back((char)(key.port & 0xFF));
|
||||||
return std::hash<std::string>()(value);
|
return std::hash<std::string>()(value);
|
||||||
|
@ -35,7 +41,7 @@ std::size_t UDPC::IPV6_Hasher::operator()(const struct in6_addr& addr) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
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.scope_id == b.scope_id && a.port == b.port;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator ==(const struct in6_addr& a, const struct in6_addr& b) {
|
bool operator ==(const struct in6_addr& a, const struct in6_addr& b) {
|
||||||
|
@ -71,7 +77,12 @@ rtt(std::chrono::steady_clock::duration::zero())
|
||||||
flags.reset(1);
|
flags.reset(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC::ConnectionData::ConnectionData(bool isServer, Context *ctx, struct in6_addr addr, uint16_t port) :
|
UDPC::ConnectionData::ConnectionData(
|
||||||
|
bool isServer,
|
||||||
|
Context *ctx,
|
||||||
|
struct in6_addr addr,
|
||||||
|
uint32_t scope_id,
|
||||||
|
uint16_t port) :
|
||||||
flags(),
|
flags(),
|
||||||
id(0),
|
id(0),
|
||||||
lseq(0),
|
lseq(0),
|
||||||
|
@ -82,6 +93,7 @@ toggleT(UDPC::THIRTY_SECONDS),
|
||||||
toggleTimer(std::chrono::steady_clock::duration::zero()),
|
toggleTimer(std::chrono::steady_clock::duration::zero()),
|
||||||
toggledTimer(std::chrono::steady_clock::duration::zero()),
|
toggledTimer(std::chrono::steady_clock::duration::zero()),
|
||||||
addr(addr),
|
addr(addr),
|
||||||
|
scope_id(scope_id),
|
||||||
port(port),
|
port(port),
|
||||||
sentPkts(),
|
sentPkts(),
|
||||||
sendPkts(UDPC_QUEUED_PKTS_MAX_SIZE),
|
sendPkts(UDPC_QUEUED_PKTS_MAX_SIZE),
|
||||||
|
@ -154,7 +166,7 @@ void UDPC::Context::update_impl() {
|
||||||
log(
|
log(
|
||||||
UDPC_LoggingType::VERBOSE,
|
UDPC_LoggingType::VERBOSE,
|
||||||
"Timed out connection with ",
|
"Timed out connection with ",
|
||||||
UDPC_atostr((UDPC_HContext)this, iter->first),
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
||||||
", port = ",
|
", port = ",
|
||||||
iter->second.port);
|
iter->second.port);
|
||||||
continue;
|
continue;
|
||||||
|
@ -168,7 +180,7 @@ void UDPC::Context::update_impl() {
|
||||||
log(
|
log(
|
||||||
UDPC_LoggingType::INFO,
|
UDPC_LoggingType::INFO,
|
||||||
"Switching to bad mode in connection with ",
|
"Switching to bad mode in connection with ",
|
||||||
UDPC_atostr((UDPC_HContext)this, iter->first),
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
||||||
", port = ",
|
", port = ",
|
||||||
iter->second.port);
|
iter->second.port);
|
||||||
iter->second.flags.reset(1);
|
iter->second.flags.reset(1);
|
||||||
|
@ -194,7 +206,7 @@ void UDPC::Context::update_impl() {
|
||||||
log(
|
log(
|
||||||
UDPC_LoggingType::INFO,
|
UDPC_LoggingType::INFO,
|
||||||
"Switching to good mode in connection with ",
|
"Switching to good mode in connection with ",
|
||||||
UDPC_atostr((UDPC_HContext)this, iter->first),
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
||||||
", port = ",
|
", port = ",
|
||||||
iter->second.port);
|
iter->second.port);
|
||||||
iter->second.flags.set(1);
|
iter->second.flags.set(1);
|
||||||
|
@ -272,7 +284,7 @@ void UDPC::Context::update_impl() {
|
||||||
std::memcpy(destinationInfo.sin6_addr.s6_addr, iter->first.addr.s6_addr, 16);
|
std::memcpy(destinationInfo.sin6_addr.s6_addr, iter->first.addr.s6_addr, 16);
|
||||||
destinationInfo.sin6_port = htons(iter->second.port);
|
destinationInfo.sin6_port = htons(iter->second.port);
|
||||||
destinationInfo.sin6_flowinfo = 0;
|
destinationInfo.sin6_flowinfo = 0;
|
||||||
destinationInfo.sin6_scope_id = 0;
|
destinationInfo.sin6_scope_id = iter->first.scope_id;
|
||||||
long int sentBytes = sendto(
|
long int sentBytes = sendto(
|
||||||
socketHandle,
|
socketHandle,
|
||||||
buf.get(),
|
buf.get(),
|
||||||
|
@ -284,13 +296,13 @@ void UDPC::Context::update_impl() {
|
||||||
log(
|
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((UDPC_HContext)this, iter->first),
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
||||||
", port = ",
|
", port = ",
|
||||||
iter->second.port);
|
iter->second.port);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
log(UDPC_LoggingType::INFO, "Sent initiate connection to ",
|
log(UDPC_LoggingType::INFO, "Sent initiate connection to ",
|
||||||
UDPC_atostr((UDPC_HContext)this, iter->first),
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
||||||
", port = ",
|
", port = ",
|
||||||
iter->second.port);
|
iter->second.port);
|
||||||
}
|
}
|
||||||
|
@ -314,7 +326,7 @@ void UDPC::Context::update_impl() {
|
||||||
std::memcpy(destinationInfo.sin6_addr.s6_addr, iter->first.addr.s6_addr, 16);
|
std::memcpy(destinationInfo.sin6_addr.s6_addr, iter->first.addr.s6_addr, 16);
|
||||||
destinationInfo.sin6_port = htons(iter->second.port);
|
destinationInfo.sin6_port = htons(iter->second.port);
|
||||||
destinationInfo.sin6_flowinfo = 0;
|
destinationInfo.sin6_flowinfo = 0;
|
||||||
destinationInfo.sin6_scope_id = 0;
|
destinationInfo.sin6_scope_id = iter->first.scope_id;
|
||||||
long int sentBytes = sendto(
|
long int sentBytes = sendto(
|
||||||
socketHandle,
|
socketHandle,
|
||||||
buf.get(),
|
buf.get(),
|
||||||
|
@ -326,7 +338,7 @@ void UDPC::Context::update_impl() {
|
||||||
log(
|
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((UDPC_HContext)this, iter->first),
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
||||||
", port = ",
|
", port = ",
|
||||||
iter->second.port);
|
iter->second.port);
|
||||||
continue;
|
continue;
|
||||||
|
@ -358,7 +370,7 @@ void UDPC::Context::update_impl() {
|
||||||
std::memcpy(destinationInfo.sin6_addr.s6_addr, iter->first.addr.s6_addr, 16);
|
std::memcpy(destinationInfo.sin6_addr.s6_addr, iter->first.addr.s6_addr, 16);
|
||||||
destinationInfo.sin6_port = htons(iter->second.port);
|
destinationInfo.sin6_port = htons(iter->second.port);
|
||||||
destinationInfo.sin6_flowinfo = 0;
|
destinationInfo.sin6_flowinfo = 0;
|
||||||
destinationInfo.sin6_scope_id = 0;
|
destinationInfo.sin6_scope_id = iter->first.scope_id;
|
||||||
long int sentBytes = sendto(
|
long int sentBytes = sendto(
|
||||||
socketHandle,
|
socketHandle,
|
||||||
buf.get(),
|
buf.get(),
|
||||||
|
@ -370,7 +382,7 @@ void UDPC::Context::update_impl() {
|
||||||
log(
|
log(
|
||||||
UDPC_LoggingType::ERROR,
|
UDPC_LoggingType::ERROR,
|
||||||
"Failed to send heartbeat packet to ",
|
"Failed to send heartbeat packet to ",
|
||||||
UDPC_atostr((UDPC_HContext)this, iter->first),
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
||||||
", port = ",
|
", port = ",
|
||||||
iter->second.port);
|
iter->second.port);
|
||||||
continue;
|
continue;
|
||||||
|
@ -429,7 +441,7 @@ void UDPC::Context::update_impl() {
|
||||||
log(
|
log(
|
||||||
UDPC_LoggingType::ERROR,
|
UDPC_LoggingType::ERROR,
|
||||||
"Failed to send packet to ",
|
"Failed to send packet to ",
|
||||||
UDPC_atostr((UDPC_HContext)this, iter->first),
|
UDPC_atostr((UDPC_HContext)this, iter->first.addr),
|
||||||
", port = ",
|
", port = ",
|
||||||
iter->second.port);
|
iter->second.port);
|
||||||
continue;
|
continue;
|
||||||
|
@ -492,7 +504,7 @@ void UDPC::Context::update_impl() {
|
||||||
log(
|
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((UDPC_HContext)this, UDPC_ConnectionId{receivedData.sin6_addr, 0}),
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
||||||
", port = ",
|
", port = ",
|
||||||
receivedData.sin6_port);
|
receivedData.sin6_port);
|
||||||
return;
|
return;
|
||||||
|
@ -504,7 +516,7 @@ void UDPC::Context::update_impl() {
|
||||||
log(
|
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((UDPC_HContext)this, UDPC_ConnectionId{receivedData.sin6_addr, 0}),
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
||||||
", port = ",
|
", port = ",
|
||||||
ntohs(receivedData.sin6_port));
|
ntohs(receivedData.sin6_port));
|
||||||
return;
|
return;
|
||||||
|
@ -521,18 +533,18 @@ void UDPC::Context::update_impl() {
|
||||||
bool isResending = conID & UDPC_ID_RESENDING;
|
bool isResending = conID & UDPC_ID_RESENDING;
|
||||||
conID &= 0x0FFFFFFF;
|
conID &= 0x0FFFFFFF;
|
||||||
|
|
||||||
UDPC_ConnectionId identifier{receivedData.sin6_addr, ntohs(receivedData.sin6_port)};
|
UDPC_ConnectionId identifier{receivedData.sin6_addr, receivedData.sin6_scope_id, ntohs(receivedData.sin6_port)};
|
||||||
|
|
||||||
if(isConnect && flags.test(2)) {
|
if(isConnect && flags.test(2)) {
|
||||||
// is connect packet and is accepting new connections
|
// is connect packet and is accepting new connections
|
||||||
if(!flags.test(1)
|
if(!flags.test(1)
|
||||||
&& conMap.find(identifier) == conMap.end()) {
|
&& conMap.find(identifier) == conMap.end()) {
|
||||||
// is receiving as server, connection did not already exist
|
// is receiving as server, connection did not already exist
|
||||||
UDPC::ConnectionData newConnection(true, this, receivedData.sin6_addr, ntohs(receivedData.sin6_port));
|
UDPC::ConnectionData newConnection(true, this, receivedData.sin6_addr, receivedData.sin6_scope_id, ntohs(receivedData.sin6_port));
|
||||||
log(
|
log(
|
||||||
UDPC_LoggingType::VERBOSE,
|
UDPC_LoggingType::VERBOSE,
|
||||||
"Establishing connection with client ",
|
"Establishing connection with client ",
|
||||||
UDPC_atostr((UDPC_HContext)this, UDPC_ConnectionId{receivedData.sin6_addr, 0}),
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
||||||
", port = ",
|
", port = ",
|
||||||
ntohs(receivedData.sin6_port),
|
ntohs(receivedData.sin6_port),
|
||||||
", giving client id = ", newConnection.id);
|
", giving client id = ", newConnection.id);
|
||||||
|
@ -564,7 +576,7 @@ void UDPC::Context::update_impl() {
|
||||||
log(
|
log(
|
||||||
UDPC_LoggingType::VERBOSE,
|
UDPC_LoggingType::VERBOSE,
|
||||||
"Established connection with server ",
|
"Established connection with server ",
|
||||||
UDPC_atostr((UDPC_HContext)this, UDPC_ConnectionId{receivedData.sin6_addr, 0}),
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
||||||
", port = ",
|
", port = ",
|
||||||
ntohs(receivedData.sin6_port),
|
ntohs(receivedData.sin6_port),
|
||||||
", got id = ", conID);
|
", got id = ", conID);
|
||||||
|
@ -585,7 +597,7 @@ void UDPC::Context::update_impl() {
|
||||||
log(
|
log(
|
||||||
UDPC_LoggingType::INFO,
|
UDPC_LoggingType::INFO,
|
||||||
"Received valid packet from ",
|
"Received valid packet from ",
|
||||||
UDPC_atostr((UDPC_HContext)this, UDPC_ConnectionId{receivedData.sin6_addr, 0}),
|
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
||||||
", port = ",
|
", port = ",
|
||||||
ntohs(receivedData.sin6_port),
|
ntohs(receivedData.sin6_port),
|
||||||
", packet id = ", seqID,
|
", packet id = ", seqID,
|
||||||
|
@ -829,10 +841,12 @@ UDPC_PacketInfo UDPC::get_empty_pinfo() {
|
||||||
0, // dataSize
|
0, // dataSize
|
||||||
{ // sender
|
{ // sender
|
||||||
{0}, // ipv6 addr
|
{0}, // ipv6 addr
|
||||||
|
0, // scope_id
|
||||||
0 // port
|
0 // port
|
||||||
},
|
},
|
||||||
{ // receiver
|
{ // receiver
|
||||||
{0}, // ipv6 addr
|
{0}, // ipv6 addr
|
||||||
|
0, // scope_id
|
||||||
0 // port
|
0 // port
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -852,11 +866,15 @@ void UDPC::threadedUpdate(Context *ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC_ConnectionId UDPC_create_id(struct in6_addr addr, uint16_t port) {
|
UDPC_ConnectionId UDPC_create_id(struct in6_addr addr, uint16_t port) {
|
||||||
return UDPC_ConnectionId{addr, port};
|
return UDPC_ConnectionId{addr, 0, port};
|
||||||
|
}
|
||||||
|
|
||||||
|
UDPC_ConnectionId UDPC_create_id_full(struct in6_addr addr, uint32_t scope_id, uint16_t port) {
|
||||||
|
return UDPC_ConnectionId{addr, scope_id, port};
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC_ConnectionId UDPC_create_id_anyaddr(uint16_t port) {
|
UDPC_ConnectionId UDPC_create_id_anyaddr(uint16_t port) {
|
||||||
return UDPC_ConnectionId{in6addr_any, port};
|
return UDPC_ConnectionId{in6addr_any, 0, port};
|
||||||
}
|
}
|
||||||
|
|
||||||
UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient) {
|
UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient) {
|
||||||
|
@ -864,7 +882,7 @@ UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient) {
|
||||||
ctx->flags.set(1, isClient != 0);
|
ctx->flags.set(1, isClient != 0);
|
||||||
|
|
||||||
ctx->log(UDPC_LoggingType::INFO, "Got listen addr ",
|
ctx->log(UDPC_LoggingType::INFO, "Got listen addr ",
|
||||||
UDPC_atostr((UDPC_HContext)ctx, listenId));
|
UDPC_atostr((UDPC_HContext)ctx, listenId.addr));
|
||||||
|
|
||||||
// create socket
|
// create socket
|
||||||
ctx->socketHandle = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
ctx->socketHandle = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
@ -886,7 +904,7 @@ UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient) {
|
||||||
ctx->socketInfo.sin6_addr = listenId.addr;
|
ctx->socketInfo.sin6_addr = listenId.addr;
|
||||||
ctx->socketInfo.sin6_port = htons(listenId.port);
|
ctx->socketInfo.sin6_port = htons(listenId.port);
|
||||||
ctx->socketInfo.sin6_flowinfo = 0;
|
ctx->socketInfo.sin6_flowinfo = 0;
|
||||||
ctx->socketInfo.sin6_scope_id = 0;
|
ctx->socketInfo.sin6_scope_id = listenId.scope_id;
|
||||||
if(bind(ctx->socketHandle, (const struct sockaddr *)&ctx->socketInfo,
|
if(bind(ctx->socketHandle, (const struct sockaddr *)&ctx->socketInfo,
|
||||||
sizeof(struct sockaddr_in6)) < 0) {
|
sizeof(struct sockaddr_in6)) < 0) {
|
||||||
// TODO maybe different way of handling init fail
|
// TODO maybe different way of handling init fail
|
||||||
|
@ -969,12 +987,12 @@ void UDPC_client_initiate_connection(UDPC_HContext ctx, UDPC_ConnectionId connec
|
||||||
}
|
}
|
||||||
|
|
||||||
c->log(UDPC_LoggingType::INFO, "client_initiate_connection: Got peer a = ",
|
c->log(UDPC_LoggingType::INFO, "client_initiate_connection: Got peer a = ",
|
||||||
UDPC_atostr((UDPC_HContext)ctx, connectionId),
|
UDPC_atostr((UDPC_HContext)ctx, connectionId.addr),
|
||||||
", p = ", connectionId.port);
|
", p = ", connectionId.port);
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(c->mutex);
|
std::lock_guard<std::mutex> lock(c->mutex);
|
||||||
|
|
||||||
UDPC::ConnectionData newCon(false, c, connectionId.addr, connectionId.port);
|
UDPC::ConnectionData newCon(false, c, connectionId.addr, connectionId.scope_id, connectionId.port);
|
||||||
newCon.sent = std::chrono::steady_clock::now() - UDPC::INIT_PKT_INTERVAL_DT;
|
newCon.sent = std::chrono::steady_clock::now() - UDPC::INIT_PKT_INTERVAL_DT;
|
||||||
|
|
||||||
if(c->conMap.find(connectionId) == c->conMap.end()) {
|
if(c->conMap.find(connectionId) == c->conMap.end()) {
|
||||||
|
@ -1139,7 +1157,11 @@ UDPC_PacketInfo UDPC_get_received(UDPC_HContext ctx) {
|
||||||
return UDPC::get_empty_pinfo();
|
return UDPC::get_empty_pinfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *UDPC_atostr(UDPC_HContext ctx, UDPC_ConnectionId connectionId) {
|
const char *UDPC_atostr_cid(UDPC_HContext ctx, UDPC_ConnectionId connectionId) {
|
||||||
|
return UDPC_atostr(ctx, connectionId.addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *UDPC_atostr(UDPC_HContext ctx, struct in6_addr addr) {
|
||||||
UDPC::Context *c = UDPC::verifyContext(ctx);
|
UDPC::Context *c = UDPC::verifyContext(ctx);
|
||||||
if(!c) {
|
if(!c) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1168,11 +1190,11 @@ const char *UDPC_atostr(UDPC_HContext ctx, UDPC_ConnectionId connectionId) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(connectionId.addr.s6_addr[i] == 0) {
|
if(addr.s6_addr[i] == 0) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
std::stringstream sstream;
|
std::stringstream sstream;
|
||||||
sstream << std::hex << (unsigned int) connectionId.addr.s6_addr[i];
|
sstream << std::hex << (unsigned int) addr.s6_addr[i];
|
||||||
std::string out(sstream.str());
|
std::string out(sstream.str());
|
||||||
if(out.size() == 1) {
|
if(out.size() == 1) {
|
||||||
if(out[0] != '0') {
|
if(out[0] != '0') {
|
||||||
|
@ -1198,7 +1220,6 @@ const char *UDPC_atostr(UDPC_HContext ctx, UDPC_ConnectionId connectionId) {
|
||||||
struct in6_addr UDPC_strtoa(const char *addrStr) {
|
struct in6_addr UDPC_strtoa(const char *addrStr) {
|
||||||
struct in6_addr result = in6addr_loopback;
|
struct in6_addr result = in6addr_loopback;
|
||||||
std::cmatch matchResults;
|
std::cmatch matchResults;
|
||||||
// TODO switch regex to ipv6_regex when link device is supported
|
|
||||||
if(std::regex_match(addrStr, matchResults, ipv6_regex_nolink)) {
|
if(std::regex_match(addrStr, matchResults, ipv6_regex_nolink)) {
|
||||||
unsigned int index = 0;
|
unsigned int index = 0;
|
||||||
unsigned int strIndex = 0;
|
unsigned int strIndex = 0;
|
||||||
|
@ -1376,3 +1397,210 @@ struct in6_addr UDPC_strtoa(const char *addrStr) {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct in6_addr UDPC_strtoa_link(const char *addrStr, uint32_t *linkId_out) {
|
||||||
|
const auto checkSetOut = [&linkId_out] (uint32_t val) {
|
||||||
|
if(linkId_out) {
|
||||||
|
*linkId_out = val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct in6_addr result({0});
|
||||||
|
std::cmatch matchResults;
|
||||||
|
const char *linkName = nullptr;
|
||||||
|
|
||||||
|
if(std::regex_match(addrStr, matchResults, ipv6_regex_linkonly)) {
|
||||||
|
unsigned int index = 0;
|
||||||
|
unsigned int strIndex = 0;
|
||||||
|
int doubleColonIndex = -1;
|
||||||
|
unsigned char bytes[2] = {0, 0};
|
||||||
|
unsigned char bytesState = 0;
|
||||||
|
bool prevColon = false;
|
||||||
|
|
||||||
|
const auto checkInc = [&result, &index, &bytes] () -> bool {
|
||||||
|
if(index < 15) {
|
||||||
|
result.s6_addr[index++] = bytes[0];
|
||||||
|
result.s6_addr[index++] = bytes[1];
|
||||||
|
bytes[0] = 0;
|
||||||
|
bytes[1] = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
while(addrStr[strIndex] != '%') {
|
||||||
|
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()) {
|
||||||
|
checkSetOut(0);
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
checkSetOut(0);
|
||||||
|
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()) {
|
||||||
|
checkSetOut(0);
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
checkSetOut(0);
|
||||||
|
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()) {
|
||||||
|
checkSetOut(0);
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
checkSetOut(0);
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
prevColon = false;
|
||||||
|
} else if(addrStr[strIndex] == ':') {
|
||||||
|
switch(bytesState) {
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
bytes[1] = bytes[0];
|
||||||
|
bytes[0] = 0;
|
||||||
|
if(checkInc()) {
|
||||||
|
checkSetOut(0);
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
bytes[1] |= (bytes[0] & 0xF) << 4;
|
||||||
|
bytes[0] = bytes[0] >> 4;
|
||||||
|
if(checkInc()) {
|
||||||
|
checkSetOut(0);
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
checkSetOut(0);
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
bytesState = 0;
|
||||||
|
if(prevColon) {
|
||||||
|
if(doubleColonIndex >= 0) {
|
||||||
|
checkSetOut(0);
|
||||||
|
return in6addr_loopback;
|
||||||
|
} else {
|
||||||
|
doubleColonIndex = index;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
prevColon = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
checkSetOut(0);
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
|
||||||
|
++strIndex;
|
||||||
|
}
|
||||||
|
switch(bytesState) {
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
bytes[1] = bytes[0];
|
||||||
|
bytes[0] = 0;
|
||||||
|
if(checkInc()) {
|
||||||
|
checkSetOut(0);
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
bytes[1] |= (bytes[0] & 0xF) << 4;
|
||||||
|
bytes[0] = bytes[0] >> 4;
|
||||||
|
if(checkInc()) {
|
||||||
|
checkSetOut(0);
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
checkSetOut(0);
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
linkName = addrStr + strIndex + 1;
|
||||||
|
|
||||||
|
if(doubleColonIndex >= 0) {
|
||||||
|
strIndex = 16 - index;
|
||||||
|
if(strIndex < 2) {
|
||||||
|
checkSetOut(0);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct ifreq req{{0}, 0, 0};
|
||||||
|
std::strncpy(req.ifr_name, linkName, IFNAMSIZ);
|
||||||
|
int socketHandle = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if(ioctl(socketHandle, SIOCGIFINDEX, &req) < 0) {
|
||||||
|
CleanupSocket(socketHandle);
|
||||||
|
checkSetOut(0);
|
||||||
|
return in6addr_loopback;
|
||||||
|
}
|
||||||
|
|
||||||
|
CleanupSocket(socketHandle);
|
||||||
|
checkSetOut(req.ifr_ifindex);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ typedef enum { SILENT, ERROR, WARNING, VERBOSE, INFO } UDPC_LoggingType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct in6_addr addr;
|
struct in6_addr addr;
|
||||||
|
uint32_t scope_id;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
} UDPC_ConnectionId;
|
} UDPC_ConnectionId;
|
||||||
|
|
||||||
|
@ -73,6 +74,8 @@ typedef struct {
|
||||||
/// port should be in native byte order (not network/big-endian)
|
/// port should be in native byte order (not network/big-endian)
|
||||||
UDPC_ConnectionId UDPC_create_id(struct in6_addr addr, uint16_t port);
|
UDPC_ConnectionId UDPC_create_id(struct in6_addr addr, uint16_t port);
|
||||||
|
|
||||||
|
UDPC_ConnectionId UDPC_create_id_full(struct in6_addr addr, uint32_t scope_id, uint16_t port);
|
||||||
|
|
||||||
UDPC_ConnectionId UDPC_create_id_anyaddr(uint16_t port);
|
UDPC_ConnectionId UDPC_create_id_anyaddr(uint16_t port);
|
||||||
|
|
||||||
UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient);
|
UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient);
|
||||||
|
@ -102,11 +105,15 @@ UDPC_LoggingType UDPC_set_logging_type(UDPC_HContext ctx, UDPC_LoggingType loggi
|
||||||
|
|
||||||
UDPC_PacketInfo UDPC_get_received(UDPC_HContext ctx);
|
UDPC_PacketInfo UDPC_get_received(UDPC_HContext ctx);
|
||||||
|
|
||||||
const char *UDPC_atostr(UDPC_HContext ctx, UDPC_ConnectionId connectionId);
|
const char *UDPC_atostr_cid(UDPC_HContext ctx, UDPC_ConnectionId connectionId);
|
||||||
|
|
||||||
|
const char *UDPC_atostr(UDPC_HContext ctx, struct in6_addr addr);
|
||||||
|
|
||||||
/// addrStr must be a valid ipv6 address or a valid ipv4 address
|
/// addrStr must be a valid ipv6 address or a valid ipv4 address
|
||||||
struct in6_addr UDPC_strtoa(const char *addrStr);
|
struct in6_addr UDPC_strtoa(const char *addrStr);
|
||||||
|
|
||||||
|
struct in6_addr UDPC_strtoa_link(const char *addrStr, uint32_t *linkId_out);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -15,23 +15,23 @@ TEST(UDPC, atostr) {
|
||||||
for(unsigned int i = 0; i < 16; ++i) {
|
for(unsigned int i = 0; i < 16; ++i) {
|
||||||
conId.addr.s6_addr[i] = (i % 3 == 0 ? 0xFF : (i % 3 == 1 ? 0x12 : 0x56));
|
conId.addr.s6_addr[i] = (i % 3 == 0 ? 0xFF : (i % 3 == 1 ? 0x12 : 0x56));
|
||||||
}
|
}
|
||||||
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId);
|
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId.addr);
|
||||||
EXPECT_STREQ(resultBuf, "ff12:56ff:1256:ff12:56ff:1256:ff12:56ff");
|
EXPECT_STREQ(resultBuf, "ff12:56ff:1256:ff12:56ff:1256:ff12:56ff");
|
||||||
|
|
||||||
for(unsigned int i = 0; i < 8; ++i) {
|
for(unsigned int i = 0; i < 8; ++i) {
|
||||||
conId.addr.s6_addr[i] = 0;
|
conId.addr.s6_addr[i] = 0;
|
||||||
}
|
}
|
||||||
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId);
|
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId.addr);
|
||||||
EXPECT_STREQ(resultBuf, "::56ff:1256:ff12:56ff");
|
EXPECT_STREQ(resultBuf, "::56ff:1256:ff12:56ff");
|
||||||
|
|
||||||
conId.addr.s6_addr[0] = 1;
|
conId.addr.s6_addr[0] = 1;
|
||||||
conId.addr.s6_addr[1] = 2;
|
conId.addr.s6_addr[1] = 2;
|
||||||
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId);
|
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId.addr);
|
||||||
EXPECT_STREQ(resultBuf, "12::56ff:1256:ff12:56ff");
|
EXPECT_STREQ(resultBuf, "12::56ff:1256:ff12:56ff");
|
||||||
|
|
||||||
conId.addr.s6_addr[14] = 0;
|
conId.addr.s6_addr[14] = 0;
|
||||||
conId.addr.s6_addr[15] = 0;
|
conId.addr.s6_addr[15] = 0;
|
||||||
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId);
|
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId.addr);
|
||||||
EXPECT_STREQ(resultBuf, "12::56ff:1256:ff12:0");
|
EXPECT_STREQ(resultBuf, "12::56ff:1256:ff12:0");
|
||||||
|
|
||||||
for(unsigned int i = 0; i < 15; ++i) {
|
for(unsigned int i = 0; i < 15; ++i) {
|
||||||
|
@ -39,12 +39,12 @@ TEST(UDPC, atostr) {
|
||||||
}
|
}
|
||||||
conId.addr.s6_addr[15] = 1;
|
conId.addr.s6_addr[15] = 1;
|
||||||
|
|
||||||
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId);
|
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId.addr);
|
||||||
EXPECT_STREQ(resultBuf, "::1");
|
EXPECT_STREQ(resultBuf, "::1");
|
||||||
|
|
||||||
conId.addr.s6_addr[15] = 0;
|
conId.addr.s6_addr[15] = 0;
|
||||||
|
|
||||||
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId);
|
resultBuf = UDPC_atostr((UDPC_HContext)&context, conId.addr);
|
||||||
EXPECT_STREQ(resultBuf, "::");
|
EXPECT_STREQ(resultBuf, "::");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,9 +128,10 @@ TEST(UDPC, atostr_concurrent) {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
0x11, 0x11, 0x0, (unsigned char)(id + 1)},
|
0x11, 0x11, 0x0, (unsigned char)(id + 1)},
|
||||||
|
0,
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
ptr[id] = UDPC_atostr((UDPC_HContext)c, conId);
|
ptr[id] = UDPC_atostr((UDPC_HContext)c, conId.addr);
|
||||||
}, j, ptrs, &context);
|
}, j, ptrs, &context);
|
||||||
}
|
}
|
||||||
for(unsigned int j = 0; j < 32; ++j) {
|
for(unsigned int j = 0; j < 32; ++j) {
|
||||||
|
|
|
@ -3,9 +3,12 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
#include <UDPConnection.h>
|
#include <UDPConnection.h>
|
||||||
|
|
||||||
|
static const std::regex ipv6_regex_linkonly = std::regex(R"d(fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,})d");
|
||||||
|
|
||||||
void usage() {
|
void usage() {
|
||||||
puts("[-c | -s] - client or server (default server)");
|
puts("[-c | -s] - client or server (default server)");
|
||||||
puts("-ll <addr> - listen addr");
|
puts("-ll <addr> - listen addr");
|
||||||
|
@ -75,11 +78,21 @@ int main(int argc, char **argv) {
|
||||||
UDPC_ConnectionId connectionId;
|
UDPC_ConnectionId connectionId;
|
||||||
if(std::strcmp(listenAddr, "any") == 0) {
|
if(std::strcmp(listenAddr, "any") == 0) {
|
||||||
listenId = UDPC_create_id_anyaddr(std::atoi(listenPort));
|
listenId = UDPC_create_id_anyaddr(std::atoi(listenPort));
|
||||||
|
} else if(std::regex_match(listenAddr, ipv6_regex_linkonly)) {
|
||||||
|
uint32_t scope_id;
|
||||||
|
auto addr = UDPC_strtoa_link(listenAddr, &scope_id);
|
||||||
|
listenId = UDPC_create_id_full(addr, scope_id, std::atoi(listenPort));
|
||||||
} else {
|
} else {
|
||||||
listenId = UDPC_create_id(UDPC_strtoa(listenAddr), std::atoi(listenPort));
|
listenId = UDPC_create_id(UDPC_strtoa(listenAddr), std::atoi(listenPort));
|
||||||
}
|
}
|
||||||
if(isClient) {
|
if(isClient) {
|
||||||
connectionId = UDPC_create_id(UDPC_strtoa(connectionAddr), std::atoi(connectionPort));
|
if(std::regex_match(connectionAddr, ipv6_regex_linkonly)) {
|
||||||
|
uint32_t scope_id;
|
||||||
|
auto addr = UDPC_strtoa_link(connectionAddr, &scope_id);
|
||||||
|
connectionId = UDPC_create_id_full(addr, scope_id, std::atoi(connectionPort));
|
||||||
|
} else {
|
||||||
|
connectionId = UDPC_create_id(UDPC_strtoa(connectionAddr), std::atoi(connectionPort));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
auto context = UDPC_init_threaded_update(listenId, isClient ? 1 : 0);
|
auto context = UDPC_init_threaded_update(listenId, isClient ? 1 : 0);
|
||||||
if(!context) {
|
if(!context) {
|
||||||
|
|
Loading…
Reference in a new issue