Fixed Android segfault on mysterious udp reception callback.

This commit is contained in:
genxium 2023-01-28 10:52:52 +08:00
parent 26660d75d2
commit bbf07fe518
2 changed files with 47 additions and 40 deletions

View File

@ -43,30 +43,27 @@ window.onUdpMessage = (args) => {
} }
cc.log(`#1 Js called back by CPP: onUdpMessage: args=${args}, typeof(args)=${typeof (args)}, argslen=${args.length}, ui8Arr=${ui8Arr}`); cc.log(`#1 Js called back by CPP: onUdpMessage: args=${args}, typeof(args)=${typeof (args)}, argslen=${args.length}, ui8Arr=${ui8Arr}`);
if (6 == len) { cc.log(`#2 Js called back by CPP for upsync: trying to decode by WsReq...`);
cc.log(`#2 Js called back by CPP for peer hole punching`); const req = window.pb.protos.WsReq.decode(ui8Arr);
} else { if (req) {
const req = window.pb.protos.WsReq.decode(ui8Arr); cc.log(`#2 Js called back by CPP for upsync: onUdpMessage: ${JSON.stringify(req)}`);
if (req) { if (req.act && window.UPSYNC_MSG_ACT_PLAYER_CMD == req.act) {
cc.log(`#2 Js called back by CPP for upsync: onUdpMessage: ${JSON.stringify(req)}`); const renderedInputFrameIdUpper = gopkgs.ConvertToDelayedInputFrameId(self.renderFrameId);
if (req.act && window.UPSYNC_MSG_ACT_PLAYER_CMD == req.act) { const peerJoinIndex = req.joinIndex;
const renderedInputFrameIdUpper = gopkgs.ConvertToDelayedInputFrameId(self.renderFrameId); const batch = req.inputFrameUpsyncBatch;
const peerJoinIndex = req.joinIndex; for (let k in batch) {
const batch = req.inputFrameUpsyncBatch; const inputFrameUpsync = batch[k];
for (let k in batch) { if (inputFrameUpsync.inputFrameId < renderedInputFrameIdUpper) {
const inputFrameUpsync = batch[k]; // Avoid obfuscating already rendered history
if (inputFrameUpsync.inputFrameId < renderedInputFrameIdUpper) { continue;
// Avoid obfuscating already rendered history
continue;
}
if (inputFrameUpsync.inputFrameId <= self.lastAllConfirmedInputFrameId) {
continue;
}
self.getOrPrefabInputFrameUpsync(inputFrameUpsync.inputFrameId); // Make sure that inputFrame exists locally
const existingInputFrame = self.recentInputCache.GetByFrameId(inputFrameUpsync.inputFrameId);
existingInputFrame.InputList[inputFrameUpsync.joinIndex - 1] = inputFrameUpsync.encoded; // No need to change "confirmedList", leave it to "onInputFrameDownsyncBatch" -- we're just helping prediction here
self.recentInputCache.SetByFrameId(existingInputFrame, inputFrameUpsync.inputFrameId);
} }
if (inputFrameUpsync.inputFrameId <= self.lastAllConfirmedInputFrameId) {
continue;
}
self.getOrPrefabInputFrameUpsync(inputFrameUpsync.inputFrameId); // Make sure that inputFrame exists locally
const existingInputFrame = self.recentInputCache.GetByFrameId(inputFrameUpsync.inputFrameId);
existingInputFrame.InputList[inputFrameUpsync.joinIndex - 1] = inputFrameUpsync.encoded; // No need to change "confirmedList", leave it to "onInputFrameDownsyncBatch" -- we're just helping prediction here
self.recentInputCache.SetByFrameId(existingInputFrame, inputFrameUpsync.inputFrameId);
} }
} }
} }

View File

@ -14,30 +14,37 @@ struct PeerAddr peerAddrList[maxPeerCnt];
char SRV_IP[256]; char SRV_IP[256];
int SRV_PORT = 0; int SRV_PORT = 0;
void _onRead(uv_udp_t* req, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags) { void _onRead(uv_udp_t* req, ssize_t nread, uv_buf_t const* buf, struct sockaddr const* addr, unsigned flags) {
if (nread < 0) { if (nread < 0) {
CCLOGERROR("Read error %s", uv_err_name(nread)); CCLOGERROR("Read error %s", uv_err_name(nread));
uv_close((uv_handle_t*)req, NULL); uv_close((uv_handle_t*)req, NULL);
free(buf->base); free(buf->base);
return; return;
} }
if (NULL != addr) {
struct sockaddr_in* sockAddr = (struct sockaddr_in*)addr; // The null check for "addr" is necessary, on Android there'd be such mysterious call to "_onRead"!
char ip[17] = { 0 }; switch (addr->sa_family) {
uv_ip4_name(sockAddr, ip, sizeof ip); case AF_INET: {
int port = ntohs(sockAddr->sin_port); struct sockaddr_in const* sockAddr = (struct sockaddr_in const*)addr;
char ip[INET_ADDRSTRLEN];
int const gameThreadMsgSize = 256; memset(ip, 0, sizeof ip);
char* const gameThreadMsg = (char* const)malloc(gameThreadMsgSize); //uv_ip4_name(sockAddr, ip, 16);
memset(gameThreadMsg, 0, gameThreadMsgSize); uv_inet_ntop(sockAddr->sin_family, &(sockAddr->sin_addr), ip, INET_ADDRSTRLEN);
memcpy(gameThreadMsg, buf->base, nread); int port = ntohs(sockAddr->sin_port);
CCLOG("UDP received %d bytes from %s:%d", nread, ip, port);
free(buf->base); break;
//uv_udp_recv_stop(req); }
default:
break;
}
}
if (6 != nread) { if (6 != nread) {
// Non-holepunching // Non-holepunching
CCLOG("UDP received %d bytes from %s:%d, converted to %d bytes for the JS callback", nread, ip, port, strlen(gameThreadMsg)); int const gameThreadMsgSize = 256;
char* const gameThreadMsg = (char* const)malloc(gameThreadMsgSize);
memset(gameThreadMsg, 0, gameThreadMsgSize);
memcpy(gameThreadMsg, buf->base, nread);
cocos2d::Application::getInstance()->getScheduler()->performFunctionInCocosThread([=]() { cocos2d::Application::getInstance()->getScheduler()->performFunctionInCocosThread([=]() {
// [WARNING] Use of the "ScriptEngine" is only allowed in "GameThread a.k.a. CocosThread"! // [WARNING] Use of the "ScriptEngine" is only allowed in "GameThread a.k.a. CocosThread"!
se::Value onUdpMessageCb; se::Value onUdpMessageCb;
@ -55,8 +62,11 @@ void _onRead(uv_udp_t* req, ssize_t nread, const uv_buf_t* buf, const struct soc
free(gameThreadMsg); free(gameThreadMsg);
}); });
} else { } else {
CCLOG("UDP received hole punching from %s:%d", ip, port); CCLOG("UDP received hole punching");
} }
free(buf->base);
//uv_udp_recv_stop(req);
uv_close((uv_handle_t*)req, NULL);
} }
static void _allocBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { static void _allocBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {