📄 xtunnelsservermain.cpp
字号:
#endif //DEBUG exit(1); } g_tCurrentChildInfo.status = SChild::eDeathwatch; ChildData()->SetAlarm(EOnDeathwatch); #if DEBUG cout << "X-Tunnels: child " << getpid() << " saved session info, now on deathwatch for user id " << ChildData()->UserID() << endl;#endif //DEBUG return iResult; } else { // no successfully logged in user ID, no deathwatch#if DEBUG cout << "X-Tunnels: child " << getpid() << " not deathwatchable, so exiting immediately! " << endl;#endif //DEBUG exit(0); return 0; // just to quiet compiler } }#if VS_TARGET_OS_MAC#pragma mark *** signal handlers#endif // VS_TARGET_OS_MAC // a client, or us, has been quiet long enough for us to time outstatic void ChildHandleSIGALRM(int s) {#if VS_TARGET_OS_MAC #pragma unused (s)#endif // VS_TARGET_OS_MAC time_t tNow = time(NULL); if (g_tCurrentChildInfo.status == SChild::eDeathwatch) {#if DEBUG cout << "X-Tunnels: child " << getpid() << " HandleSIGALRM when deathwatch timed out, now exiting immediately!" << endl;#endif //DEBUG exit(1); } if (tNow >= (time_t)(g_tLastReceivedFromClient + EChildDisconnectTimeOut)) {#if DEBUG cout << "X-Tunnels: child " << getpid() << " HandleSIGALRM when client timed out, now disconnecting" << endl;#endif //DEBUG sQuitReason = kDisconnectReasonTimeout; sQuitMessage = sMessageTimedOut; CheckForDeathwatch(); } if (tNow >= (time_t)(g_tLastSentToClient + EChildPingClientTimeOut)) { if (sClientTCPSocket) { TXTunnelsPacketHeaderUnencrypted tPing; tPing.commandid = HOST2XT32(EMessagePing); ChildData()->SendPacketToClient(reinterpret_cast<TXTunnelsPacket*>(&tPing), 0, false);#if DEBUG cout << "X-Tunnels: child " << getpid() << " HandleSIGALRM sent ping packet after " << (tNow - g_tLastSentToClient) << " no TCP packet sent seconds " << endl;#endif //DEBUG ChildData()->SetAlarm(ESentPacket); } else {#if DEBUG cout << "X-Tunnels: WARNING: child " << getpid() << " HandleSIGALRM could NOT send ping packet -- sClientTCPSocket is zero!! " << endl;#endif //DEBUG } } }// parent has signalled that it would like a status reportstatic void ChildHandleSIGUSR1(int s) {#if VS_TARGET_OS_MAC #pragma unused (s)#endif // VS_TARGET_OS_MAC TChildStatus tStatus = { 0 }; tStatus.ulPortsSingle = g_ulActiveSinglePorts; tStatus.ulPortsDual = g_ulActiveDualPorts; tStatus.ulTrafficIncoming = g_tCurrentChildInfo.incomingbytes; tStatus.ulTrafficOutgoing = g_tCurrentChildInfo.outgoingbytes; tStatus.incomingtrafficlastsecondbytes = GetIncomingBandwidth(); tStatus.outgoingtrafficlastsecondbytes = GetOutgoingBandwidth(); tStatus.m_ulClientIP = g_tCurrentChildInfo.m_ulClientIP; tStatus.m_ulUniqueDestinations = GetUniqueDestinations(); tStatus.connectiontime = g_tCurrentChildInfo.connectiontime; tStatus.usernamelength = strlen(ChildData()->UserID()) + 1; tStatus.iHostNameLength = strlen(ChildData()->Host()) + 1; // 50 is completely arbitrary here tStatus.m_iNumDestinationsTraffic = min<unsigned long>(50, tStatus.m_ulUniqueDestinations); long piperesult = PipeWrite(g_pStatusInfoPipe, &tStatus, sizeof(tStatus)); // followed by user name length characters including trailing NULL piperesult = PipeWrite(g_pStatusInfoPipe, ChildData()->UserID(), tStatus.usernamelength); // followed by host piperesult = PipeWrite(g_pStatusInfoPipe, ChildData()->Host(), tStatus.iHostNameLength); TDestinationInfo pLatestTraffic[50]; // = { 0 }; bzero(pLatestTraffic, 50 * sizeof(TDestinationInfo)); GetDestinationsTraffic(tStatus.m_iNumDestinationsTraffic, pLatestTraffic); piperesult = PipeWrite(g_pStatusInfoPipe, pLatestTraffic, tStatus.m_iNumDestinationsTraffic * sizeof(TDestinationInfo)); }// parent has signalled that it's time to diestatic void ChildHandleSIGUSR2(int s) {#if VS_TARGET_OS_MAC #pragma unused (s)#endif // VS_TARGET_OS_MAC sQuitReason = kDisconnectReasonMustClose; sQuitMessage = g_pMessageServerQuitting; CheckForDeathwatch(); exit(0); }static void ServerCheckStartedChild(int i) { unsigned long startingNew = 0; long result = PipeRead(g_pChildren[i].m_pChild2ServerPipe, &startingNew, sizeof(startingNew)); if (sizeof(startingNew) != result) return; uuid_t sessionid;// = { 0 }; bzero(&sessionid, sizeof(sessionid)); result = PipeRead(g_pChildren[i].m_pChild2ServerPipe, &sessionid, sizeof(sessionid)); if (sizeof(sessionid) != result) return; char szHost[EMaxDBHostLength + 1]; szHost[0] = 0; result = PipeRead(g_pChildren[i].m_pChild2ServerPipe, szHost, EMaxDBHostLength); long reply = 0; if (!startingNew) { bool foundoldone = false; // look for it, if found kill and send back its ports for (unsigned long j = 0; j < g_ulMaximumClients; i++) if ((g_pChildren[j].status > SChild::eAvailable) && !memcmp(&g_pChildren[j].sessionID, &sessionid, sizeof (sessionid))) { if (g_pChildren[j].status != SChild::eDeathwatch) {#if DEBUG cout << "X-Tunnels: HandleSIGUSR1 wants to restart an undead session -- forcing deathwatch on it" << endl;#endif //DEBUG kill(g_pChildren[j].pid, SIGALRM); // expect that to close its connection and fill out its port list } SChild local = g_pChildren[j]; // don't worry about errors here, worst that can happen is old one dies and new one aborts kill(g_pChildren[j].pid, SIGTERM); reply = kFillOutPortList; result = PipeWrite(g_pChildren[i].m_pServer2ChildPipe, &reply, sizeof(reply)); long portcount = local.portcount;#if DEBUG // this isn't *necessarily* an error if client hadn't requested any yet, but probably is if (!portcount) cout << "X-Tunnels: HandleSIGUSR1 found previous process without ports to pipe" << endl;#endif //DEBUG result = PipeWrite(g_pChildren[i].m_pServer2ChildPipe, &portcount, sizeof(portcount)); for (int k = 0; k < portcount; k++) result = PipeWrite(g_pChildren[i].m_pServer2ChildPipe, &local.portarray[k], sizeof(long)); foundoldone = true; break; } // if didn't find it, send back a new id if (!foundoldone) startingNew = true; } if (startingNew) { reply = kStartNewSession; FillWithRandomLongs(&sessionid, sizeof(sessionid)); int iConnections = CountHostConnections(szHost); result = PipeWrite(g_pChildren[i].m_pServer2ChildPipe, &reply, sizeof(reply)); result = PipeWrite(g_pChildren[i].m_pServer2ChildPipe, &sessionid, sizeof(sessionid)); result = PipeWrite(g_pChildren[i].m_pServer2ChildPipe, &iConnections, sizeof(iConnections));#if DEBUG if (sizeof(iConnections) != result) cout << "X-Tunnels: ServerHandleSIGUSR1 failed to pipe new session ID to child" << endl;#endif //DEBUG } g_pChildren[i].sessionID = sessionid; g_pChildren[i].status = SChild::eActive; strncpy(g_pChildren[i].m_szHost, szHost, EMaxDBHostLength); CleanChildPipes(g_pChildren[i]);#if DEBUG cout << "X-Tunnels: ServerHandleSIGUSR1 read session id for child " << g_pChildren[i].pid << " on host " << szHost << endl;#endif //DEBUG } // a child has signalled that it's piped us its session IDstatic void ServerHandleSIGUSR1(int s) {#if VS_TARGET_OS_MAC #pragma unused (s)#endif // VS_TARGET_OS_MAC // signals are blocked but not queued during handler execution // so go through the entire client list every time here for (unsigned long i = 0; i < g_ulMaximumClients; i++) if ((g_pChildren[i].status == SChild::eStarted)) ServerCheckStartedChild(i); } // a child has signalled that it has info for usstatic void ServerHandleSIGUSR2(int s) {#if VS_TARGET_OS_MAC #pragma unused (s)#endif // VS_TARGET_OS_MAC // read whole thing for simplicity -- assume that it'll be less than PIPE_BUF so written atomically TChildToParentPipePacket tPipedChildInfo = { 0 }; int iPipeResult = PipeRead(g_pChild2ParentInfoPipe, &tPipedChildInfo, sizeof(tPipedChildInfo)); if ((sizeof(tPipedChildInfo) != iPipeResult)) {#if DEBUG cout << "X-Tunnels: ERROR: ServerHandleSIGUSR2 failed (" << iPipeResult << ") to read info packet " << endl;#endif //DEBUG return; } switch (tPipedChildInfo.m_ulPacketType) { case EInfoPacketChildOnDeathwatch: if ((tPipedChildInfo.m_tDeathwatch.m_ulStatus != (unsigned long)SChild::eDeathwatch) || (tPipedChildInfo.m_tDeathwatch.m_ulChildIndex >= g_ulMaximumClients)) { #if DEBUG cout << "X-Tunnels: ERROR: failed (" << iPipeResult << ") to read info packet for signalled child " << tPipedChildInfo.m_tDeathwatch.m_ulChildIndex << endl; #endif //DEBUG return; } g_pChildren[tPipedChildInfo.m_tDeathwatch.m_ulChildIndex].status = SChild::eDeathwatch; g_pChildren[tPipedChildInfo.m_tDeathwatch.m_ulChildIndex].portcount = tPipedChildInfo.m_tDeathwatch.m_ulActivePortCount; for (unsigned long iPortIndex = 0; iPortIndex < tPipedChildInfo.m_tDeathwatch.m_ulActivePortCount; iPortIndex++) g_pChildren[tPipedChildInfo.m_tDeathwatch.m_ulChildIndex].portarray[iPortIndex] = tPipedChildInfo.m_tDeathwatch.m_pActivePorts[iPortIndex]; break; case EInfoPacketGotHostKeyPassword: if (XCipher::XCipherEnabled()) GetXCipher()->UpdateHostPairCache(tPipedChildInfo.m_tPairPassword); break; case EInfoPacketWantCipherKey: if (XCipher::XCipherEnabled()) GetXCipher()->HandleCipherKeyRequest(tPipedChildInfo.m_tKeyRequest); break; case EInfoPacketClearXCipherCache: if (XCipher::XCipherEnabled()) GetXCipher()->EmptyHostPairCache(); break; default:#if DEBUG cout << "X-Tunnels: ERROR: ServerHandleSIGUSR2 got unknown info packet type " << tPipedChildInfo.m_ulPacketType << endl;#endif //DEBUG break; } } // a child has diedstatic void ServerHandleSIGCHLD(int s) {#if VS_TARGET_OS_MAC #pragma unused (s)#endif // VS_TARGET_OS_MAC int stat = 0; pid_t pid = 0; // signals are blocked but not queued during handler execution while ((pid = r_waitpid(-1, &stat, WNOHANG)) > 0) {#if DEBUG cout << "X-Tunnels: received a SIGCHLD for pid " << pid << endl; bool foundit = false;#endif //DEBUG for (unsigned long i = 0; i < g_ulMaximumClients; i++) if ((g_pChildren[i].status > SChild::eAvailable) && (g_pChildren[i].pid == pid)) { g_pChildren[i].status = SChild::eAvailable; g_pChildren[i].pid = 0; CleanChildPipes(g_pChildren[i]);#if DEBUG cout << "X-Tunnels: removed pid " << pid << " from index " << i << ", now have " << CountActiveChildren() << "/" << g_ulMaximumClients << " active clients" << endl; foundit = true;#endif //DEBUG break; }#if DEBUG if (!foundit) cout << "WARNING: pid " << pid << " was not found in active client list!" << endl;#endif //DEBUG } }#if VS_TARGET_OS_MAC#pragma mark *** message handlers#endif // VS_TARGET_OS_MACint HandleMessagePing(TXTunnelsPacket* packet) { if (packet->m_tHeaderBasic.payloadsize != 0 /*sizeof(PingParam)*/) // sizeof(PingParam) is 1! {#if DEBUG cout << "X-Tunnels: HandleMessagePing expects packetsize " << 0 /*sizeof(PingParam)*/ << " but packet claims " << packet->m_tHeaderBasic.payloadsize << endl;#endif //DEBUG return 1; } // should we ping back? #if DEBUG ///cout << "X-Tunnels: HandleMessagePing succeeded" << endl;#endif //DEBUG return 0; }int HandleMessageVersion(TXTunnelsPacket* packet) { if (packet->m_tHeaderBasic.payloadsize != sizeof(TVersionParam)) {#if DEBUG cout << "X-Tunnels: HandleMessageVersion expects packetsize " << sizeof(TVersionParam) << " but packet claims " << packet->m_tHeaderBasic.payloadsize << endl;#endif //DEBUG return 1; } ChildData()->m_tVersion = packet->m_tData.m_tVersion;#if DEBUG cout << "X-Tunnels: HandleMessageVersion received protocol " << (long)(ChildData()->m_tVersion.m_byProtocolMajor) << "." << (long)(ChildData()->m_tVersion.m_byProtocolMinor) << " version " << XT2HOST16(ChildData()->m_tVersion.m_wVersionID) << endl;#endif //DEBUG // we don't actually do anything here, according to state diagram #if DEBUG cout << "X-Tunnels: HandleMessageVersion succeeded " << endl;#endif //DEBUG return 0; }int HandleMessageChallengeReply(TXTunnelsPacket* packet) { long blobsize = packet->m_tData.challengereply.challengereplyblobsize = XT2HOST32(packet->m_tData.challengereply.challengereplyblobsize); if (blobsize > ChallengeReplyParam::kMaxChallengeReplyBlobSize) {#if DEBUG cout << "X-Tunnels: HandleMessageChallengeReply found too big (" << blobsize << " ) challenge blob!" << endl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -