Receive packets in loop til none left in interval

Also some formatting fixes (max 80 chars in edited code).
This commit is contained in:
Stephen Seo 2022-12-04 19:57:37 +09:00
parent b7cd3a00c7
commit 77ac7f88a5

View file

@ -1116,6 +1116,7 @@ void UDPC::Context::update_impl() {
deletionMap.clear(); deletionMap.clear();
// receive packet // receive packet
do {
UDPC_IPV6_SOCKADDR_TYPE receivedData; UDPC_IPV6_SOCKADDR_TYPE receivedData;
socklen_t receivedDataSize = sizeof(receivedData); socklen_t receivedDataSize = sizeof(receivedData);
int bytes = recvfrom( int bytes = recvfrom(
@ -1162,7 +1163,8 @@ void UDPC::Context::update_impl() {
// Invalid protocol id in packet // Invalid protocol id in packet
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_VERBOSE, UDPC_LoggingType::UDPC_VERBOSE,
"Received packet has invalid protocol id, ignoring packet from ", "Received packet has invalid protocol id, ignoring packet "
"from ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr), UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr),
", port = ", ", port = ",
ntohs(receivedData.sin6_port)); ntohs(receivedData.sin6_port));
@ -1183,7 +1185,8 @@ void UDPC::Context::update_impl() {
bool isNotRecChecked = conID & UDPC_ID_NO_REC_CHK; bool isNotRecChecked = conID & UDPC_ID_NO_REC_CHK;
bool isResending = conID & UDPC_ID_RESENDING; bool isResending = conID & UDPC_ID_RESENDING;
conID &= 0x0FFFFFFF; conID &= 0x0FFFFFFF;
UDPC_ConnectionId identifier = UDPC_create_id_full(receivedData.sin6_addr, UDPC_ConnectionId identifier =
UDPC_create_id_full(receivedData.sin6_addr,
receivedData.sin6_scope_id, receivedData.sin6_scope_id,
ntohs(receivedData.sin6_port)); ntohs(receivedData.sin6_port));
@ -1253,24 +1256,30 @@ void UDPC::Context::update_impl() {
// is receiving as server, connection did not already exist // is receiving as server, connection did not already exist
int authPolicy = this->authPolicy.load(); int authPolicy = this->authPolicy.load();
if(pktType == 1 && !flags.test(2) if(pktType == 1 && !flags.test(2)
&& authPolicy == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) { && authPolicy
== UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR, UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
"Client peer ", "Client peer ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr), UDPC_atostr(
(UDPC_HContext)this, receivedData.sin6_addr),
" port ", " port ",
ntohs(receivedData.sin6_port), ntohs(receivedData.sin6_port),
" attempted connection with packet authentication " " attempted connection with packet authentication "
"enabled, but auth is disabled and AuthPolicy is STRICT"); "enabled, but auth is disabled and AuthPolicy is "
"STRICT");
return; return;
} else if(pktType == 0 && flags.test(2) } else if(pktType == 0 && flags.test(2)
&& authPolicy == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) { && authPolicy
== UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR, UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
"Client peer ", "Client peer ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr), UDPC_atostr(
(UDPC_HContext)this, receivedData.sin6_addr),
" port ", " port ",
ntohs(receivedData.sin6_port), ntohs(receivedData.sin6_port),
" attempted connection with packet authentication " " attempted connection with packet authentication "
"disabled, but auth is enabled and AuthPolicy is STRICT"); "disabled, but auth is enabled and AuthPolicy is "
"STRICT");
return; return;
} }
unsigned char *sk = nullptr; unsigned char *sk = nullptr;
@ -1298,7 +1307,8 @@ void UDPC::Context::update_impl() {
UDPC_LoggingType::UDPC_ERROR, UDPC_LoggingType::UDPC_ERROR,
"Failed to init ConnectionData instance (libsodium init" "Failed to init ConnectionData instance (libsodium init"
" fail) while server establishing connection with ", " fail) while server establishing connection with ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr), UDPC_atostr(
(UDPC_HContext)this, receivedData.sin6_addr),
", port = ", ", port = ",
ntohs(receivedData.sin6_port)); ntohs(receivedData.sin6_port));
return; return;
@ -1310,20 +1320,26 @@ void UDPC::Context::update_impl() {
recvBuf + UDPC_MIN_HEADER_SIZE + 4, recvBuf + UDPC_MIN_HEADER_SIZE + 4,
crypto_sign_PUBLICKEYBYTES); crypto_sign_PUBLICKEYBYTES);
{ {
std::lock_guard<std::mutex> pkWhitelistLock(peerPKWhitelistMutex); std::lock_guard<std::mutex>
if(!peerPKWhitelist.empty() && peerPKWhitelist.find(UDPC::PKContainer(newConnection.peer_pk)) == peerPKWhitelist.end()) { pkWhitelistLock(peerPKWhitelistMutex);
if(!peerPKWhitelist.empty()
&& peerPKWhitelist.find(
UDPC::PKContainer(newConnection.peer_pk))
== peerPKWhitelist.end()) {
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING, UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
"peer_pk is not in whitelist, not establishing " "peer_pk is not in whitelist, not establishing "
"connection with client"); "connection with client");
return; return;
} }
} }
newConnection.verifyMessage = std::unique_ptr<char[]>(new char[crypto_sign_BYTES]); newConnection.verifyMessage =
std::unique_ptr<char[]>(new char[crypto_sign_BYTES]);
std::time_t currentTime = std::time(nullptr); std::time_t currentTime = std::time(nullptr);
uint64_t receivedTime; uint64_t receivedTime;
std::memcpy( std::memcpy(
&receivedTime, &receivedTime,
recvBuf + UDPC_MIN_HEADER_SIZE + 4 + crypto_sign_PUBLICKEYBYTES + 4, recvBuf + UDPC_MIN_HEADER_SIZE + 4
+ crypto_sign_PUBLICKEYBYTES + 4,
8); 8);
UDPC::be64((char*)&receivedTime); UDPC::be64((char*)&receivedTime);
# ifndef NDEBUG # ifndef NDEBUG
@ -1334,7 +1350,8 @@ void UDPC::Context::update_impl() {
} }
# endif # endif
std::time_t receivedTimeT = receivedTime; std::time_t receivedTimeT = receivedTime;
if(currentTime < receivedTimeT || currentTime - receivedTimeT > 3) { if(currentTime < receivedTimeT
|| currentTime - receivedTimeT > 3) {
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING, UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
"Got invalid epoch time from client, ignoring"); "Got invalid epoch time from client, ignoring");
return; return;
@ -1342,13 +1359,15 @@ void UDPC::Context::update_impl() {
crypto_sign_detached( crypto_sign_detached(
(unsigned char*)newConnection.verifyMessage.get(), (unsigned char*)newConnection.verifyMessage.get(),
nullptr, nullptr,
(unsigned char*)(recvBuf + UDPC_MIN_HEADER_SIZE + 4 + crypto_sign_PUBLICKEYBYTES), (unsigned char*)(recvBuf + UDPC_MIN_HEADER_SIZE + 4
+ crypto_sign_PUBLICKEYBYTES),
12, 12,
newConnection.sk); newConnection.sk);
#else #else
assert(!"libsodium disabled, invalid state"); assert(!"libsodium disabled, invalid state");
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR, UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
"libsodium is disabled, cannot process received packet"); "libsodium is disabled, cannot process received "
"packet");
return; return;
#endif #endif
} }
@ -1363,13 +1382,15 @@ void UDPC::Context::update_impl() {
", libsodium enabled" : ", libsodium disabled"); ", libsodium enabled" : ", libsodium disabled");
idMap.insert(std::make_pair(newConnection.id, identifier)); idMap.insert(std::make_pair(newConnection.id, identifier));
conMap.insert(std::make_pair(identifier, std::move(newConnection))); conMap.insert(std::make_pair(identifier,
std::move(newConnection)));
auto addrConIter = addrConMap.find(identifier.addr); auto addrConIter = addrConMap.find(identifier.addr);
if(addrConIter == addrConMap.end()) { if(addrConIter == addrConMap.end()) {
auto insertResult = addrConMap.insert( auto insertResult = addrConMap.insert(
std::make_pair( std::make_pair(
identifier.addr, identifier.addr,
std::unordered_set<UDPC_ConnectionId, UDPC::ConnectionIdHasher>{} std::unordered_set<UDPC_ConnectionId,
UDPC::ConnectionIdHasher>{}
)); ));
assert(insertResult.second assert(insertResult.second
&& "Must successfully insert into addrConMap"); && "Must successfully insert into addrConMap");
@ -1389,45 +1410,58 @@ void UDPC::Context::update_impl() {
if(iter == conMap.end() || !iter->second.flags.test(3)) { if(iter == conMap.end() || !iter->second.flags.test(3)) {
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_DEBUG, UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_DEBUG,
"client dropped pkt from ", "client dropped pkt from ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr), UDPC_atostr(
(UDPC_HContext)this, receivedData.sin6_addr),
", port ", ntohs(receivedData.sin6_port)); ", port ", ntohs(receivedData.sin6_port));
return; return;
} }
int authPolicy = this->authPolicy.load(); int authPolicy = this->authPolicy.load();
if(pktType == 2 && !iter->second.flags.test(6) if(pktType == 2 && !iter->second.flags.test(6)
&& authPolicy == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) { && authPolicy
// This block actually should never happen, because the server == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
// receives a packet first. If client requests without auth, // This block actually should never happen, because the
// then the server will either deny connection (if strict) or // server receives a packet first. If client requests
// fallback to a connection without auth (if fallback). // without auth, then the server will either deny
// connection (if strict) or fallback to a connection
// without auth (if fallback).
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR, UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
"Server peer ", "Server peer ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr), UDPC_atostr(
(UDPC_HContext)this, receivedData.sin6_addr),
" port ", " port ",
ntohs(receivedData.sin6_port), ntohs(receivedData.sin6_port),
" attempted connection with packet authentication " " attempted connection with packet authentication "
"enabled, but auth is disabled and AuthPolicy is STRICT"); "enabled, but auth is disabled and AuthPolicy is "
"STRICT");
return; return;
} else if(pktType == 0 && iter->second.flags.test(6) } else if(pktType == 0 && iter->second.flags.test(6)
&& authPolicy == UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) { && authPolicy
== UDPC_AuthPolicy::UDPC_AUTH_POLICY_STRICT) {
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR, UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
"Server peer ", "Server peer ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr), UDPC_atostr(
(UDPC_HContext)this, receivedData.sin6_addr),
" port ", " port ",
ntohs(receivedData.sin6_port), ntohs(receivedData.sin6_port),
" attempted connection with packet authentication " " attempted connection with packet authentication "
"disabled, but auth is enabled and AuthPolicy is STRICT"); "disabled, but auth is enabled and AuthPolicy is "
"STRICT");
return; return;
} }
if(pktType == 2 && flags.test(2) && iter->second.flags.test(6)) { if(pktType == 2 && flags.test(2)
&& iter->second.flags.test(6)) {
#ifdef UDPC_LIBSODIUM_ENABLED #ifdef UDPC_LIBSODIUM_ENABLED
std::memcpy(iter->second.peer_pk, std::memcpy(iter->second.peer_pk,
recvBuf + UDPC_MIN_HEADER_SIZE + 4, recvBuf + UDPC_MIN_HEADER_SIZE + 4,
crypto_sign_PUBLICKEYBYTES); crypto_sign_PUBLICKEYBYTES);
{ {
std::lock_guard<std::mutex> pkWhitelistLock(peerPKWhitelistMutex); std::lock_guard<std::mutex>
if(!peerPKWhitelist.empty() && peerPKWhitelist.find(UDPC::PKContainer(iter->second.peer_pk)) == peerPKWhitelist.end()) { pkWhitelistLock(peerPKWhitelistMutex);
if(!peerPKWhitelist.empty()
&& peerPKWhitelist.find(
UDPC::PKContainer(iter->second.peer_pk))
== peerPKWhitelist.end()) {
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING, UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
"peer_pk is not in whitelist, not establishing " "peer_pk is not in whitelist, not establishing "
"connection with server"); "connection with server");
@ -1435,13 +1469,15 @@ void UDPC::Context::update_impl() {
} }
} }
if(crypto_sign_verify_detached( if(crypto_sign_verify_detached(
(unsigned char*)(recvBuf + UDPC_MIN_HEADER_SIZE + 4 + crypto_sign_PUBLICKEYBYTES), (unsigned char*)(recvBuf + UDPC_MIN_HEADER_SIZE + 4
+ crypto_sign_PUBLICKEYBYTES),
(unsigned char*)(iter->second.verifyMessage.get()), (unsigned char*)(iter->second.verifyMessage.get()),
12, 12,
iter->second.peer_pk) != 0) { iter->second.peer_pk) != 0) {
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING, UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
"Failed to verify peer (server) ", "Failed to verify peer (server) ",
UDPC_atostr((UDPC_HContext)this, receivedData.sin6_addr), UDPC_atostr(
(UDPC_HContext)this, receivedData.sin6_addr),
", port = ", ", port = ",
ntohs(receivedData.sin6_port)); ntohs(receivedData.sin6_port));
return; return;
@ -1449,7 +1485,8 @@ void UDPC::Context::update_impl() {
#else #else
assert(!"libsodium disabled, invalid state"); assert(!"libsodium disabled, invalid state");
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR, UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_ERROR,
"libsodium is disabled, cannot process received packet"); "libsodium is disabled, cannot process received "
"packet");
return; return;
#endif #endif
} else if(pktType == 0 && iter->second.flags.test(6)) { } else if(pktType == 0 && iter->second.flags.test(6)) {
@ -1496,8 +1533,12 @@ void UDPC::Context::update_impl() {
#ifdef UDPC_LIBSODIUM_ENABLED #ifdef UDPC_LIBSODIUM_ENABLED
// verify signature of header // verify signature of header
unsigned char sig[crypto_sign_BYTES]; unsigned char sig[crypto_sign_BYTES];
std::memcpy(sig, recvBuf + UDPC_MIN_HEADER_SIZE + 1, crypto_sign_BYTES); std::memcpy(sig,
std::memset(recvBuf + UDPC_MIN_HEADER_SIZE + 1, 0, crypto_sign_BYTES); recvBuf + UDPC_MIN_HEADER_SIZE + 1,
crypto_sign_BYTES);
std::memset(recvBuf + UDPC_MIN_HEADER_SIZE + 1,
0,
crypto_sign_BYTES);
if(crypto_sign_verify_detached( if(crypto_sign_verify_detached(
sig, sig,
(unsigned char*)recvBuf, (unsigned char*)recvBuf,
@ -1539,7 +1580,8 @@ void UDPC::Context::update_impl() {
if(conIter != conMap.end()) { if(conIter != conMap.end()) {
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_VERBOSE, UDPC_LoggingType::UDPC_VERBOSE,
"Packet is request-disconnect packet, deleting connection..."); "Packet is request-disconnect packet, deleting "
"connection...");
if(conIter->second.flags.test(4)) { if(conIter->second.flags.test(4)) {
idMap.erase(conIter->second.id); idMap.erase(conIter->second.id);
} }
@ -1561,7 +1603,9 @@ void UDPC::Context::update_impl() {
} }
// 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) {
uint32_t id; uint32_t id;
std::memcpy(&id, sentIter->data + 8, 4); std::memcpy(&id, sentIter->data + 8, 4);
id = ntohl(id); id = ntohl(id);
@ -1576,7 +1620,8 @@ void UDPC::Context::update_impl() {
iter->second.rtt -= (iter->second.rtt - diff) / 10; iter->second.rtt -= (iter->second.rtt - diff) / 10;
} }
iter->second.flags.set(2, iter->second.rtt <= UDPC::GOOD_RTT_LIMIT); iter->second.flags.set(
2, iter->second.rtt <= UDPC::GOOD_RTT_LIMIT);
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_VERBOSE, UDPC_LoggingType::UDPC_VERBOSE,
@ -1598,23 +1643,33 @@ void UDPC::Context::update_impl() {
} }
// pkt not received yet, find it in sent to check if it timed out // pkt not received yet, find it in sent to check if it timed out
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) {
uint32_t sentID; uint32_t sentID;
std::memcpy(&sentID, sentIter->data + 8, 4); std::memcpy(&sentID, sentIter->data + 8, 4);
sentID = ntohl(sentID); sentID = ntohl(sentID);
if(sentID == rseq) { if(sentID == rseq) {
if((sentIter->flags & 0x4) != 0 || (sentIter->flags & 0x8) != 0) { if((sentIter->flags & 0x4) != 0
|| (sentIter->flags & 0x8) != 0) {
// already resent or not rec-checked pkt // already resent or not rec-checked pkt
break; break;
} }
auto sentInfoIter = iter->second.sentInfoMap.find(sentID); auto sentInfoIter = iter->second.sentInfoMap.find(sentID);
assert(sentInfoIter != iter->second.sentInfoMap.end() assert(sentInfoIter != iter->second.sentInfoMap.end()
&& "Every entry in sentPkts must have a corresponding entry in sentInfoMap"); && "Every entry in sentPkts must have a "
"corresponding entry in sentInfoMap");
auto duration = now - sentInfoIter->second->sentTime; auto duration = now - sentInfoIter->second->sentTime;
if(duration > UDPC::PACKET_TIMEOUT_TIME) { if(duration > UDPC::PACKET_TIMEOUT_TIME) {
bool pktSigned = sentIter->data[UDPC_MIN_HEADER_SIZE] == 1; bool pktSigned =
if((pktSigned && sentIter->dataSize <= UDPC_LSFULL_HEADER_SIZE) sentIter->data[UDPC_MIN_HEADER_SIZE] == 1;
|| (!pktSigned && sentIter->dataSize <= UDPC_NSFULL_HEADER_SIZE)) { if((pktSigned
&& sentIter->dataSize
<= UDPC_LSFULL_HEADER_SIZE
) ||
(!pktSigned
&& sentIter->dataSize
<= UDPC_NSFULL_HEADER_SIZE)) {
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_VERBOSE, UDPC_LoggingType::UDPC_VERBOSE,
"Timed out packet has no payload (probably " "Timed out packet has no payload (probably "
@ -1625,14 +1680,18 @@ void UDPC::Context::update_impl() {
UDPC_PacketInfo resendingData = UDPC::get_empty_pinfo(); UDPC_PacketInfo resendingData = UDPC::get_empty_pinfo();
if(pktSigned) { if(pktSigned) {
resendingData.dataSize = sentIter->dataSize - UDPC_LSFULL_HEADER_SIZE; resendingData.dataSize =
resendingData.data = (char*)std::malloc(resendingData.dataSize); sentIter->dataSize - UDPC_LSFULL_HEADER_SIZE;
resendingData.data =
(char*)std::malloc(resendingData.dataSize);
std::memcpy(resendingData.data, std::memcpy(resendingData.data,
sentIter->data + UDPC_LSFULL_HEADER_SIZE, sentIter->data + UDPC_LSFULL_HEADER_SIZE,
resendingData.dataSize); resendingData.dataSize);
} else { } else {
resendingData.dataSize = sentIter->dataSize - UDPC_NSFULL_HEADER_SIZE; resendingData.dataSize =
resendingData.data = (char*)std::malloc(resendingData.dataSize); sentIter->dataSize - UDPC_NSFULL_HEADER_SIZE;
resendingData.data =
(char*)std::malloc(resendingData.dataSize);
std::memcpy(resendingData.data, std::memcpy(resendingData.data,
sentIter->data + UDPC_NSFULL_HEADER_SIZE, sentIter->data + UDPC_NSFULL_HEADER_SIZE,
resendingData.dataSize); resendingData.dataSize);
@ -1663,7 +1722,8 @@ void UDPC::Context::update_impl() {
// already received packet // already received packet
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_VERBOSE, UDPC_LoggingType::UDPC_VERBOSE,
"Received packet is already marked as received, ignoring it"); "Received packet is already marked as received, "
"ignoring it");
return; return;
} }
iter->second.ack |= 0x80000000 >> (diff - 1); iter->second.ack |= 0x80000000 >> (diff - 1);
@ -1677,7 +1737,8 @@ void UDPC::Context::update_impl() {
// already received packet // already received packet
UDPC_CHECK_LOG(this, UDPC_CHECK_LOG(this,
UDPC_LoggingType::UDPC_VERBOSE, UDPC_LoggingType::UDPC_VERBOSE,
"Received packet is already marked as received, ignoring it"); "Received packet is already marked as received, "
"ignoring it");
return; return;
} }
iter->second.ack |= 0x80000000 >> (diff - 1); iter->second.ack |= 0x80000000 >> (diff - 1);
@ -1749,6 +1810,7 @@ void UDPC::Context::update_impl() {
UDPC_LoggingType::UDPC_VERBOSE, UDPC_LoggingType::UDPC_VERBOSE,
"Received packet has no payload (probably heartbeat packet)"); "Received packet has no payload (probably heartbeat packet)");
} }
} while (true);
} }
UDPC::Context *UDPC::verifyContext(UDPC_HContext ctx) { UDPC::Context *UDPC::verifyContext(UDPC_HContext ctx) {