Fix Windows support
This commit is contained in:
parent
0e22357d55
commit
71f7bc4977
4 changed files with 145 additions and 65 deletions
|
@ -29,6 +29,10 @@ set_target_properties(UDPConnection PROPERTIES VERSION ${UDPConnection_VERSION})
|
|||
|
||||
target_compile_features(UDPConnection PUBLIC cxx_std_17)
|
||||
target_link_libraries(UDPConnection PUBLIC pthread)
|
||||
if(WIN32)
|
||||
target_link_libraries(UDPConnection PUBLIC Ws2_32)
|
||||
target_link_libraries(UDPConnection PUBLIC Iphlpapi)
|
||||
endif()
|
||||
|
||||
target_include_directories(UDPConnection PUBLIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/RingBuffer/src")
|
||||
|
|
|
@ -243,7 +243,7 @@ public:
|
|||
std::atomic_uint32_t atostrBufIndex;
|
||||
char atostrBuf[UDPC_ATOSTR_SIZE];
|
||||
|
||||
int socketHandle;
|
||||
UDPC_SOCKETTYPE socketHandle;
|
||||
struct sockaddr_in6 socketInfo;
|
||||
|
||||
std::chrono::steady_clock::time_point lastUpdated;
|
||||
|
|
|
@ -16,6 +16,23 @@
|
|||
|
||||
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
||||
#include <netioapi.h>
|
||||
|
||||
static const UDPC_IPV6_ADDR_TYPE in6addr_any = UDPC_IPV6_ADDR_TYPE{{
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0
|
||||
}};
|
||||
static const UDPC_IPV6_ADDR_TYPE in6addr_loopback = UDPC_IPV6_ADDR_TYPE{{
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 1
|
||||
}};
|
||||
|
||||
typedef int socklen_t;
|
||||
|
||||
static const std::regex regex_numeric = std::regex("[0-9]+");
|
||||
#elif UDPC_PLATFORM == UDPC_PLATFORM_MAC || UDPC_PLATFORM == UDPC_PLATFORM_LINUX
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
|
@ -32,7 +49,7 @@ sentTime(std::chrono::steady_clock::now())
|
|||
{}
|
||||
|
||||
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*)UDPC_IPV6_ADDR_SUB(key.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));
|
||||
|
@ -42,17 +59,17 @@ std::size_t UDPC::ConnectionIdHasher::operator()(const UDPC_ConnectionId& key) c
|
|||
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));
|
||||
std::size_t UDPC::IPV6_Hasher::operator()(const UDPC_IPV6_ADDR_TYPE& addr) const {
|
||||
return std::hash<std::string>()(std::string((const char*)UDPC_IPV6_ADDR_SUB(addr), 16));
|
||||
}
|
||||
|
||||
bool operator ==(const UDPC_ConnectionId& a, const UDPC_ConnectionId& b) {
|
||||
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 UDPC_IPV6_ADDR_TYPE& a, const UDPC_IPV6_ADDR_TYPE& b) {
|
||||
for(unsigned int i = 0; i < 16; ++i) {
|
||||
if(a.s6_addr[i] != b.s6_addr[i]) {
|
||||
if(UDPC_IPV6_ADDR_SUB(a)[i] != UDPC_IPV6_ADDR_SUB(b)[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +103,7 @@ rtt(std::chrono::steady_clock::duration::zero())
|
|||
UDPC::ConnectionData::ConnectionData(
|
||||
bool isServer,
|
||||
Context *ctx,
|
||||
struct in6_addr addr,
|
||||
UDPC_IPV6_ADDR_TYPE addr,
|
||||
uint32_t scope_id,
|
||||
uint16_t port) :
|
||||
flags(),
|
||||
|
@ -285,9 +302,9 @@ void UDPC::Context::update_impl() {
|
|||
nullptr,
|
||||
0x1);
|
||||
|
||||
struct sockaddr_in6 destinationInfo;
|
||||
UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
|
||||
destinationInfo.sin6_family = AF_INET6;
|
||||
std::memcpy(destinationInfo.sin6_addr.s6_addr, iter->first.addr.s6_addr, 16);
|
||||
std::memcpy(UDPC_IPV6_ADDR_SUB(destinationInfo.sin6_addr), UDPC_IPV6_ADDR_SUB(iter->first.addr), 16);
|
||||
destinationInfo.sin6_port = htons(iter->second.port);
|
||||
destinationInfo.sin6_flowinfo = 0;
|
||||
destinationInfo.sin6_scope_id = iter->first.scope_id;
|
||||
|
@ -297,7 +314,7 @@ void UDPC::Context::update_impl() {
|
|||
20,
|
||||
0,
|
||||
(struct sockaddr*) &destinationInfo,
|
||||
sizeof(struct sockaddr_in6));
|
||||
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
||||
if(sentBytes != 20) {
|
||||
log(
|
||||
UDPC_LoggingType::UDPC_ERROR,
|
||||
|
@ -327,9 +344,9 @@ void UDPC::Context::update_impl() {
|
|||
&iter->second.lseq,
|
||||
0x1);
|
||||
|
||||
struct sockaddr_in6 destinationInfo;
|
||||
UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
|
||||
destinationInfo.sin6_family = AF_INET6;
|
||||
std::memcpy(destinationInfo.sin6_addr.s6_addr, iter->first.addr.s6_addr, 16);
|
||||
std::memcpy(UDPC_IPV6_ADDR_SUB(destinationInfo.sin6_addr), UDPC_IPV6_ADDR_SUB(iter->first.addr), 16);
|
||||
destinationInfo.sin6_port = htons(iter->second.port);
|
||||
destinationInfo.sin6_flowinfo = 0;
|
||||
destinationInfo.sin6_scope_id = iter->first.scope_id;
|
||||
|
@ -339,7 +356,7 @@ void UDPC::Context::update_impl() {
|
|||
20,
|
||||
0,
|
||||
(struct sockaddr*) &destinationInfo,
|
||||
sizeof(struct sockaddr_in6));
|
||||
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
||||
if(sentBytes != 20) {
|
||||
log(
|
||||
UDPC_LoggingType::UDPC_ERROR,
|
||||
|
@ -371,9 +388,9 @@ void UDPC::Context::update_impl() {
|
|||
&iter->second.lseq,
|
||||
0);
|
||||
|
||||
struct sockaddr_in6 destinationInfo;
|
||||
UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
|
||||
destinationInfo.sin6_family = AF_INET6;
|
||||
std::memcpy(destinationInfo.sin6_addr.s6_addr, iter->first.addr.s6_addr, 16);
|
||||
std::memcpy(UDPC_IPV6_ADDR_SUB(destinationInfo.sin6_addr), UDPC_IPV6_ADDR_SUB(iter->first.addr), 16);
|
||||
destinationInfo.sin6_port = htons(iter->second.port);
|
||||
destinationInfo.sin6_flowinfo = 0;
|
||||
destinationInfo.sin6_scope_id = iter->first.scope_id;
|
||||
|
@ -383,7 +400,7 @@ void UDPC::Context::update_impl() {
|
|||
20,
|
||||
0,
|
||||
(struct sockaddr*) &destinationInfo,
|
||||
sizeof(struct sockaddr_in6));
|
||||
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
||||
if(sentBytes != 20) {
|
||||
log(
|
||||
UDPC_LoggingType::UDPC_ERROR,
|
||||
|
@ -432,9 +449,9 @@ void UDPC::Context::update_impl() {
|
|||
(pInfo.flags & 0x4) | (isResending ? 0x8 : 0));
|
||||
std::memcpy(buf.get() + 20, pInfo.data, pInfo.dataSize);
|
||||
|
||||
struct sockaddr_in6 destinationInfo;
|
||||
UDPC_IPV6_SOCKADDR_TYPE destinationInfo;
|
||||
destinationInfo.sin6_family = AF_INET6;
|
||||
std::memcpy(destinationInfo.sin6_addr.s6_addr, iter->first.addr.s6_addr, 16);
|
||||
std::memcpy(UDPC_IPV6_ADDR_SUB(destinationInfo.sin6_addr), UDPC_IPV6_ADDR_SUB(iter->first.addr), 16);
|
||||
destinationInfo.sin6_port = htons(iter->second.port);
|
||||
long int sentBytes = sendto(
|
||||
socketHandle,
|
||||
|
@ -442,7 +459,7 @@ void UDPC::Context::update_impl() {
|
|||
pInfo.dataSize + 20,
|
||||
0,
|
||||
(struct sockaddr*) &destinationInfo,
|
||||
sizeof(struct sockaddr_in6));
|
||||
sizeof(UDPC_IPV6_SOCKADDR_TYPE));
|
||||
if(sentBytes != 20 + pInfo.dataSize) {
|
||||
log(
|
||||
UDPC_LoggingType::UDPC_ERROR,
|
||||
|
@ -489,10 +506,7 @@ void UDPC::Context::update_impl() {
|
|||
}
|
||||
|
||||
// receive packet
|
||||
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
struct sockaddr_in6 receivedData;
|
||||
UDPC_IPV6_SOCKADDR_TYPE receivedData;
|
||||
socklen_t receivedDataSize = sizeof(receivedData);
|
||||
int bytes = recvfrom(
|
||||
socketHandle,
|
||||
|
@ -502,6 +516,28 @@ void UDPC::Context::update_impl() {
|
|||
(struct sockaddr*) &receivedData,
|
||||
&receivedDataSize);
|
||||
|
||||
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
||||
if(bytes == 0) {
|
||||
// connection closed
|
||||
return;
|
||||
} else if(bytes == SOCKET_ERROR) {
|
||||
int error = WSAGetLastError();
|
||||
if(error != WSAEWOULDBLOCK) {
|
||||
log(UDPC_LoggingType::UDPC_ERROR,
|
||||
"Error receiving packet, ", error);
|
||||
}
|
||||
return;
|
||||
} else if(bytes < 20) {
|
||||
// packet size is too small, invalid packet
|
||||
log(
|
||||
UDPC_LoggingType::UDPC_INFO,
|
||||
"Received packet is smaller than header, ignoring packet from ",
|
||||
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
|
||||
", port = ",
|
||||
receivedData.sin6_port);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if(bytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
|
||||
// no packet was received
|
||||
return;
|
||||
|
@ -515,6 +551,7 @@ void UDPC::Context::update_impl() {
|
|||
receivedData.sin6_port);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t temp = ntohl(*((uint32_t*)recvBuf));
|
||||
if(temp != protocolID) {
|
||||
|
@ -871,11 +908,11 @@ void UDPC::threadedUpdate(Context *ctx) {
|
|||
}
|
||||
}
|
||||
|
||||
UDPC_ConnectionId UDPC_create_id(struct in6_addr addr, uint16_t port) {
|
||||
UDPC_ConnectionId UDPC_create_id(UDPC_IPV6_ADDR_TYPE addr, uint16_t port) {
|
||||
return UDPC_ConnectionId{addr, 0, port};
|
||||
}
|
||||
|
||||
UDPC_ConnectionId UDPC_create_id_full(struct in6_addr addr, uint32_t scope_id, uint16_t port) {
|
||||
UDPC_ConnectionId UDPC_create_id_full(UDPC_IPV6_ADDR_TYPE addr, uint32_t scope_id, uint16_t port) {
|
||||
return UDPC_ConnectionId{addr, scope_id, port};
|
||||
}
|
||||
|
||||
|
@ -890,18 +927,38 @@ UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient) {
|
|||
ctx->log(UDPC_LoggingType::UDPC_INFO, "Got listen addr ",
|
||||
UDPC_atostr((UDPC_HContext)ctx, listenId.addr));
|
||||
|
||||
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
||||
// Initialize Winsock
|
||||
WORD wVersionRequested = MAKEWORD(2, 2);
|
||||
WSADATA wsaData;
|
||||
if(WSAStartup(wVersionRequested, &wsaData) != 0) {
|
||||
ctx->log(UDPC_LoggingType::UDPC_ERROR, "Failed to initialize Winsock");
|
||||
delete ctx;
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
// create socket
|
||||
ctx->socketHandle = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if(ctx->socketHandle <= 0) {
|
||||
if(UDPC_SOCKET_RETURN_ERROR(ctx->socketHandle)) {
|
||||
// TODO maybe different way of handling init fail
|
||||
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
||||
ctx->log(UDPC_LoggingType::UDPC_ERROR, "Failed to create socket, ",
|
||||
WSAGetLastError());
|
||||
#else
|
||||
ctx->log(UDPC_LoggingType::UDPC_ERROR, "Failed to create socket");
|
||||
#endif
|
||||
delete ctx;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// allow ipv4 connections on ipv6 socket
|
||||
{
|
||||
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
||||
char no = 0;
|
||||
#else
|
||||
int no = 0;
|
||||
#endif
|
||||
setsockopt(ctx->socketHandle, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no));
|
||||
}
|
||||
|
||||
|
@ -912,18 +969,18 @@ UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient) {
|
|||
ctx->socketInfo.sin6_flowinfo = 0;
|
||||
ctx->socketInfo.sin6_scope_id = listenId.scope_id;
|
||||
if(bind(ctx->socketHandle, (const struct sockaddr *)&ctx->socketInfo,
|
||||
sizeof(struct sockaddr_in6)) < 0) {
|
||||
sizeof(UDPC_IPV6_SOCKADDR_TYPE)) < 0) {
|
||||
// TODO maybe different way of handling init fail
|
||||
ctx->log(UDPC_LoggingType::UDPC_ERROR, "Failed to bind socket");
|
||||
CleanupSocket(ctx->socketHandle);
|
||||
UDPC_CLEANUPSOCKET(ctx->socketHandle);
|
||||
delete ctx;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO verify this is necessary to get the listen port
|
||||
if(ctx->socketInfo.sin6_port == 0) {
|
||||
struct sockaddr_in6 getInfo;
|
||||
socklen_t size = sizeof(struct sockaddr_in6);
|
||||
UDPC_IPV6_SOCKADDR_TYPE getInfo;
|
||||
socklen_t size = sizeof(UDPC_IPV6_SOCKADDR_TYPE);
|
||||
if(getsockname(ctx->socketHandle, (struct sockaddr *)&getInfo, &size) == 0) {
|
||||
ctx->socketInfo.sin6_port = getInfo.sin6_port;
|
||||
}
|
||||
|
@ -941,7 +998,7 @@ UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient) {
|
|||
#endif
|
||||
// TODO maybe different way of handling init fail
|
||||
ctx->log(UDPC_LoggingType::UDPC_ERROR, "Failed to set nonblocking on socket");
|
||||
CleanupSocket(ctx->socketHandle);
|
||||
UDPC_CLEANUPSOCKET(ctx->socketHandle);
|
||||
delete ctx;
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -972,6 +1029,9 @@ void UDPC_destroy(UDPC_HContext ctx) {
|
|||
UDPC_ctx->threadRunning.store(false);
|
||||
UDPC_ctx->thread.join();
|
||||
}
|
||||
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
||||
WSACleanup();
|
||||
#endif
|
||||
delete UDPC_ctx;
|
||||
}
|
||||
}
|
||||
|
@ -1167,7 +1227,7 @@ 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) {
|
||||
const char *UDPC_atostr(UDPC_HContext ctx, UDPC_IPV6_ADDR_TYPE addr) {
|
||||
UDPC::Context *c = UDPC::verifyContext(ctx);
|
||||
if(!c) {
|
||||
return nullptr;
|
||||
|
@ -1196,12 +1256,12 @@ const char *UDPC_atostr(UDPC_HContext ctx, struct in6_addr addr) {
|
|||
}
|
||||
}
|
||||
|
||||
if(addr.s6_addr[i] == 0 && (headIndex - index <= 1 || c->atostrBuf[index] == ':')) {
|
||||
if(UDPC_IPV6_ADDR_SUB(addr)[i] == 0 && (headIndex - index <= 1 || c->atostrBuf[index] == ':')) {
|
||||
continue;
|
||||
} else {
|
||||
std::stringstream sstream;
|
||||
sstream << std::setw(2) << std::setfill('0')
|
||||
<< std::hex << (unsigned int) addr.s6_addr[i];
|
||||
<< std::hex << (unsigned int) UDPC_IPV6_ADDR_SUB(addr)[i];
|
||||
std::string out(sstream.str());
|
||||
unsigned int outOffset = 0;
|
||||
if(headIndex - index <= 1 || c->atostrBuf[index - 1] == ':') {
|
||||
|
@ -1236,8 +1296,8 @@ const char *UDPC_atostr(UDPC_HContext ctx, struct in6_addr addr) {
|
|||
return c->atostrBuf + headIndex;
|
||||
}
|
||||
|
||||
struct in6_addr UDPC_strtoa(const char *addrStr) {
|
||||
struct in6_addr result = in6addr_loopback;
|
||||
UDPC_IPV6_ADDR_TYPE UDPC_strtoa(const char *addrStr) {
|
||||
UDPC_IPV6_ADDR_TYPE result = in6addr_loopback;
|
||||
std::cmatch matchResults;
|
||||
if(std::regex_match(addrStr, matchResults, ipv6_regex_nolink)) {
|
||||
unsigned int index = 0;
|
||||
|
@ -1249,8 +1309,8 @@ struct in6_addr UDPC_strtoa(const char *addrStr) {
|
|||
|
||||
const auto checkInc = [&result, &index, &bytes] () -> bool {
|
||||
if(index < 15) {
|
||||
result.s6_addr[index++] = bytes[0];
|
||||
result.s6_addr[index++] = bytes[1];
|
||||
UDPC_IPV6_ADDR_SUB(result)[index++] = bytes[0];
|
||||
UDPC_IPV6_ADDR_SUB(result)[index++] = bytes[1];
|
||||
bytes[0] = 0;
|
||||
bytes[1] = 0;
|
||||
return false;
|
||||
|
@ -1400,31 +1460,31 @@ struct in6_addr UDPC_strtoa(const char *addrStr) {
|
|||
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;
|
||||
UDPC_IPV6_ADDR_SUB(result)[i] = UDPC_IPV6_ADDR_SUB(result)[i - strIndex];
|
||||
UDPC_IPV6_ADDR_SUB(result)[i - strIndex] = 0;
|
||||
}
|
||||
}
|
||||
} else if(std::regex_match(addrStr, matchResults, ipv4_regex)) {
|
||||
for(unsigned int i = 0; i < 10; ++i) {
|
||||
result.s6_addr[i] = 0;
|
||||
UDPC_IPV6_ADDR_SUB(result)[i] = 0;
|
||||
}
|
||||
result.s6_addr[10] = 0xFF;
|
||||
result.s6_addr[11] = 0xFF;
|
||||
UDPC_IPV6_ADDR_SUB(result)[10] = 0xFF;
|
||||
UDPC_IPV6_ADDR_SUB(result)[11] = 0xFF;
|
||||
for(unsigned int i = 0; i < 4; ++i) {
|
||||
result.s6_addr[12 + i] = std::stoi(matchResults[i + 1].str());
|
||||
UDPC_IPV6_ADDR_SUB(result)[12 + i] = std::stoi(matchResults[i + 1].str());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
struct in6_addr UDPC_strtoa_link(const char *addrStr, uint32_t *linkId_out) {
|
||||
UDPC_IPV6_ADDR_TYPE 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});
|
||||
UDPC_IPV6_ADDR_TYPE result({0});
|
||||
std::cmatch matchResults;
|
||||
const char *linkName = nullptr;
|
||||
|
||||
|
@ -1438,8 +1498,8 @@ struct in6_addr UDPC_strtoa_link(const char *addrStr, uint32_t *linkId_out) {
|
|||
|
||||
const auto checkInc = [&result, &index, &bytes] () -> bool {
|
||||
if(index < 15) {
|
||||
result.s6_addr[index++] = bytes[0];
|
||||
result.s6_addr[index++] = bytes[1];
|
||||
UDPC_IPV6_ADDR_SUB(result)[index++] = bytes[0];
|
||||
UDPC_IPV6_ADDR_SUB(result)[index++] = bytes[1];
|
||||
bytes[0] = 0;
|
||||
bytes[1] = 0;
|
||||
return false;
|
||||
|
@ -1605,32 +1665,36 @@ struct in6_addr UDPC_strtoa_link(const char *addrStr, uint32_t *linkId_out) {
|
|||
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;
|
||||
UDPC_IPV6_ADDR_SUB(result)[i] = UDPC_IPV6_ADDR_SUB(result)[i - strIndex];
|
||||
UDPC_IPV6_ADDR_SUB(result)[i - strIndex] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t scope_id;
|
||||
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
||||
scope_id = if_nametoindex(linkName);
|
||||
if(scope_id == 0) {
|
||||
checkSetOut(0);
|
||||
return in6addr_loopback;
|
||||
if(std::regex_match(linkName, regex_numeric)) {
|
||||
scope_id = std::atoi(linkName);
|
||||
} else {
|
||||
scope_id = if_nametoindex(linkName);
|
||||
if(scope_id == 0) {
|
||||
checkSetOut(0);
|
||||
return in6addr_loopback;
|
||||
}
|
||||
}
|
||||
#elif UDPC_PLATFORM == UDPC_PLATFORM_MAC || UDPC_PLATFORM == UDPC_PLATFORM_LINUX
|
||||
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);
|
||||
UDPC_CLEANUPSOCKET(socketHandle);
|
||||
checkSetOut(0);
|
||||
return in6addr_loopback;
|
||||
}
|
||||
scope_id = req.ifr_ifindex;
|
||||
UDPC_CLEANUPSOCKET(socketHandle);
|
||||
#endif
|
||||
|
||||
CleanupSocket(socketHandle);
|
||||
checkSetOut(scope_id);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -20,17 +20,29 @@
|
|||
// OS-based networking macros
|
||||
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
|
||||
#include <winsock2.h>
|
||||
#include <Ws2ipdef.h>
|
||||
#include <In6addr.h>
|
||||
|
||||
#define CleanupSocket(x) closesocket(x)
|
||||
#define UDPC_CLEANUPSOCKET(x) closesocket(x)
|
||||
#define UDPC_SOCKETTYPE SOCKET
|
||||
#define UDPC_IPV6_SOCKADDR_TYPE SOCKADDR_IN6
|
||||
#define UDPC_IPV6_ADDR_TYPE IN6_ADDR
|
||||
#define UDPC_IPV6_ADDR_SUB(addr) addr.u.Byte
|
||||
#define UDPC_SOCKET_RETURN_ERROR(socket) (socket == INVALID_SOCKET)
|
||||
#elif UDPC_PLATFORM == UDPC_PLATFORM_MAC || UDPC_PLATFORM == UDPC_PLATFORM_LINUX
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define CleanupSocket(x) close(x)
|
||||
#define UDPC_CLEANUPSOCKET(x) close(x)
|
||||
#define UDPC_SOCKETTYPE int
|
||||
#define UDPC_IPV6_SOCKADDR_TYPE struct sockaddr_in6
|
||||
#define UDPC_IPV6_ADDR_TYPE struct in6_addr
|
||||
#define UDPC_IPV6_ADDR_SUB(addr) addr.s6_addr
|
||||
#define UDPC_SOCKET_RETURN_ERROR(socket) (socket <= 0)
|
||||
#else
|
||||
#define CleanupSocket(x) ((void)0)
|
||||
#define UDPC_CLEANUPSOCKET(x) ((void)0)
|
||||
#endif
|
||||
|
||||
// other defines
|
||||
|
@ -51,7 +63,7 @@ typedef struct UDPC_Context *UDPC_HContext;
|
|||
typedef enum { UDPC_SILENT, UDPC_ERROR, UDPC_WARNING, UDPC_VERBOSE, UDPC_INFO } UDPC_LoggingType;
|
||||
|
||||
typedef struct {
|
||||
struct in6_addr addr;
|
||||
UDPC_IPV6_ADDR_TYPE addr;
|
||||
uint32_t scope_id;
|
||||
uint16_t port;
|
||||
} UDPC_ConnectionId;
|
||||
|
@ -72,9 +84,9 @@ typedef struct {
|
|||
} UDPC_PacketInfo;
|
||||
|
||||
/// 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(UDPC_IPV6_ADDR_TYPE 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_full(UDPC_IPV6_ADDR_TYPE addr, uint32_t scope_id, uint16_t port);
|
||||
|
||||
UDPC_ConnectionId UDPC_create_id_anyaddr(uint16_t port);
|
||||
|
||||
|
@ -107,12 +119,12 @@ UDPC_PacketInfo UDPC_get_received(UDPC_HContext ctx);
|
|||
|
||||
const char *UDPC_atostr_cid(UDPC_HContext ctx, UDPC_ConnectionId connectionId);
|
||||
|
||||
const char *UDPC_atostr(UDPC_HContext ctx, struct in6_addr addr);
|
||||
const char *UDPC_atostr(UDPC_HContext ctx, UDPC_IPV6_ADDR_TYPE addr);
|
||||
|
||||
/// addrStr must be a valid ipv6 address or a valid ipv4 address
|
||||
struct in6_addr UDPC_strtoa(const char *addrStr);
|
||||
UDPC_IPV6_ADDR_TYPE UDPC_strtoa(const char *addrStr);
|
||||
|
||||
struct in6_addr UDPC_strtoa_link(const char *addrStr, uint32_t *linkId_out);
|
||||
UDPC_IPV6_ADDR_TYPE UDPC_strtoa_link(const char *addrStr, uint32_t *linkId_out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue