int CUnconnSocket::SendPingPacket() { //ASSERT(m_pDataHandler); if(m_dwState & NAT_E_TIMEOUT) return 1; m_nPassivePing++; m_SendPingTime = time(NULL); T_TRACE("send ping packet for %02X%02X%02X%02X. ConnAck=%08x\n", m_ClientId[0],m_ClientId[1],m_ClientId[2],m_ClientId[3], m_dwConnAskNumber); if(m_dwClientIp && m_wClientPort) { // Packet pack(OP_NAT_PING, 20, OP_VC_NAT_HEADER,false); uchar pack[20]; GetMyUserHash(pack); memcpy(pack+16, &m_dwConnAskNumber, 4); //TRACE("\nCUnconnSocket::SendPingPacket Send Ping Successful! IP : %d Port %d\n", m_dwClientIp, m_wClientPort); return CNatSocket::SendPacket(m_dwClientIp, m_wClientPort, OP_NAT_PING, pack, 20); } return -1; }
int CNatThread::Send(CAsyncSocketEx * sock, const void * data, int len) { CNatSocket * nsock=NULL; CSingleLock locker(&m_Mutex, TRUE); m_SockMap.Lookup(sock, nsock); int nRet = -1; if(nsock) { // ASSERT(nsock->m_MyVSock == sock->m_MyVSock); #ifdef _DEBUG_NAT const uchar * uh=nsock->GetUserHash(); T_TRACE("%s: len=%d to %02X%02X%02X%02X",__FUNCTION__, len, uh[0],uh[1],uh[2],uh[3]); #endif nRet = nsock->Send(data, len); } else { WSASetLastError(WSAEWOULDBLOCK); TRACE("->%s: but no peer to send\n",__FUNCTION__); } return nRet; }
void CSourceExchangeNAT::CheckForTimeOut(CUpDownClient * pClient) { if (pClient->m_nUDPState == UDP_DISCONNECT) { return; } if(time(NULL) - pClient->m_dwRegisterTime > 60 * 10) { byte pack[1+1+16]; pack[0] = OP_EMULEPROT; pack[1] = OP_UDPREGISTER; memcpy(pack+2, pClient->GetUserHash(), 16); SendUDPPacket(pClient->GetIP(), htons(pClient->GetUDPPort()), pack, 1+1+16, pClient); T_TRACE("\nSend Register From CSourceExchangeNAT::CheckForTimeOut.\n"); pClient->m_dwRegisterTime = time(NULL); pClient->m_dwSendKeepALiveTime = time(NULL); return; } if(time(NULL) - pClient->m_dwSendKeepALiveTime > TM_KEEPALIVE) { byte pack[1+1]; pack[0] = OP_EMULEPROT; pack[1] = OP_UDPKEEPALIVE; SendUDPPacket(pClient->GetIP(), htons(pClient->GetUDPPort()), pack, 1+1, pClient); T_TRACE("\nSend KeepALive From CSourceExchangeNAT::CheckForTimeOut.\n"); pClient->m_dwSendKeepALiveTime = time(NULL); return; } }
int CTraverseBySourceExchange::SendPingPacket() { T_TRACE("\nSend Ping From Source Exchange, IP : %d Port : %d!\n", m_dwClientIp, ntohs(m_wClientPort)); if(m_dwState & NAT_E_TIMEOUT) return 1; m_nPassivePing++; m_SendPingTime = time(NULL); TRACE("send ping packet for %02X%02X%02X%02X. ConnAck=%08x\n", m_UserHash[0],m_UserHash[1],m_UserHash[2],m_UserHash[3], m_dwConnAskNumber); if(m_dwClientIp && m_wClientPort) { uchar pack[20]; GetMyUserHash(pack); memcpy(pack+16, &m_dwConnAskNumber, 4); return CNatSocket::SendPacket(m_dwClientIp, m_wClientPort, OP_NAT_PING, pack, 20); } return -1; }
int CTraverseBySourceExchange::SendConnectReq() { if(m_dwState & NAT_E_TIMEOUT) return 1; m_SendReqTime = time(NULL); m_nSendReqCount++; m_dwNextSyncInterval = min(64, ExpoBackoff(SYNC_INIT_ATTEMPT_INTERVAL, m_nSendReqCount)); CUpDownClient * pClient = CGlobalVariable::clientlist->FindClientByUserHash(m_UserHash); if (pClient) { const CUpDownClient * pHighClient = pClient->GetSourceExchangeClient(); //ASSERT(pHighClient); //COMMENTED by VC-fengwen on 2007/11/16 : 程序运行过程中帮自己打洞的HighId是有可能不在了的。已做了这方面的处理了。 if (pHighClient == NULL) { return -1; } byte pack[1+1+16+16+4]; pack[0] = OP_EMULEPROT; pack[1] = OP_UDPSENATREQ; memcpy(pack+2, m_UserHash, 16); memcpy(pack+18, thePrefs.GetUserHash(), 16); memcpy(pack+34, &m_dwConnAskNumber, 4); T_TRACE("\nSend UDP SourceExchange NAT Request, IP : %d PORT : %d!\n", pHighClient->GetIP(), pHighClient->GetUDPPort()); return CNatSocket::SendPacket(pHighClient->GetIP(), htons(pHighClient->GetUDPPort()), pack, 1+1+16+16+4); } else { return -1; } }
bool CSourceExchangeNAT::ProcessTCPPacket(const BYTE* packet, uint32 size, UINT opcode, UINT /*uRawSize*/, CClientReqSocket * socket) { try { switch (opcode) { case OP_TCPSENATREQ: { T_TRACE("\nReceive TCP SourceExchange NAT Request!\n"); CSafeMemFile data(packet, size); byte * natpack = new byte[4+1+4+2+16+4]; memset(natpack, 0, 4+1+4+2+16+4); natpack[4] = OP_NAT_SYNC; memcpy(natpack+5, packet, size); uint32 uUserIP = data.ReadUInt32(); uint16 uUdpPort = data.ReadUInt16(); T_TRACE("\nIP:%d Port:%d\n", uUserIP, uUdpPort); uchar userhash[16]; data.ReadHash16(userhash); uint32 con = data.ReadUInt32(); byte * pack = new byte[1+1+16+16+4]; pack[0] = OP_EMULEPROT; pack[1] = OP_UDPSENATACK; memcpy(pack+2, userhash, 16); memcpy(pack+18, thePrefs.GetUserHash(), 16); memcpy(pack+34, &con, 4); T_TRACE("\nSend UDP SourceExchange NAT Response!\n"); if (!socket->client) { return false; // VC-SearchDream[2007-04-18]: } CNatSocket::SendPacket(socket->client->GetIP(), htons(socket->client->GetUDPPort()), pack, 1+1+16+16+4); delete []pack; pack = NULL; theApp.natthread->ProcessPacket(natpack, 4+1+4+2+16+4, socket->client->GetIP(), htons(socket->client->GetUDPPort())); delete []natpack; natpack = NULL; break; } case OP_TCPSENATACK: { CSafeMemFile data(packet, size); byte natpack[4+1+4+2+16+4]; memset(natpack, 0, 4+1+4+2+16+4); natpack[4] = OP_NAT_SYNC; memcpy(natpack+5, packet, size); uint32 uUserIP = data.ReadUInt32(); uint16 uUdpPort = data.ReadUInt16(); uchar userhash[16]; data.ReadHash16(userhash); CUpDownClient* pClient = theApp.clientlist->FindClientByUserHash(userhash); if (pClient) { pClient->SetIP(uUserIP); pClient->SetUDPPort(uUdpPort); T_TRACE("\nReceive TCP SourceExchange NAT Response!\n"); theApp.natthread->ProcessPacket(natpack, 4+1+4+2+16+4, socket->client->GetIP(), htons(socket->client->GetUDPPort())); } break; } case OP_TCPSECALLBACKREQ: { CSafeMemFile data(packet, size); uchar userhash[16]; data.ReadHash16(userhash); // Read the Call Back Target Client's UserHash CUpDownClient * pClient = theApp.clientlist->FindClientByUserHash(userhash); if (pClient) { if (!pClient->IsLowToLowClient() && (pClient->socket && pClient->socket->IsConnected())) { CSafeMemFile fileIO(16+6); fileIO.WriteHash16(socket->client->GetUploadFileID()); fileIO.WriteUInt32(socket->client->GetIP()); fileIO.WriteUInt16(socket->client->GetUserPort()); Packet* pPacket = new Packet(&fileIO, OP_EMULEPROT, OP_SECALLBACK); pClient->socket->SendPacket(pPacket, true, true, 0, true); } else { byte pack[1+1+16+6]; pack[0] = OP_EMULEPROT; pack[1] = OP_SECALLBACK; uint32 ip = socket->client->GetIP(); uint16 port = socket->client->GetUserPort(); memcpy(pack+2, socket->client->GetUploadFileID(), 16); memcpy(pack+18, &ip, 4); memcpy(pack+22, &port, 2); SendUDPPacket(pClient->GetIP(), htons(pClient->GetUDPPort()), pack, 1+1+16+6, pClient); } } break; } case OP_SECALLBACK: { CSafeMemFile data(packet, size); uchar fileid[16]; data.ReadHash16(fileid); CKnownFile* reqfile; if ( (reqfile = theApp.sharedfiles->GetFileByID(fileid)) == NULL ) { if ( (reqfile = theApp.downloadqueue->GetFileByID(fileid)) == NULL) { socket->client->CheckFailedFileIdReqs(fileid); break; } } uint32 ip = data.ReadUInt32(); uint16 tcp = data.ReadUInt16(); CUpDownClient* callback; callback = theApp.clientlist->FindClientByIP(ntohl(ip), tcp); if ( callback == NULL ) { callback = new CUpDownClient(NULL,tcp,ip,0,0, true); theApp.clientlist->AddClient(callback); } callback->TryToConnect(true); break; } default: { return true; } } } catch(...) { return false; // The Process is Over Although Failure } return false; }
bool CSourceExchangeNAT::ProcessUDPPacket(const BYTE* packet, UINT size, uint8 opcode, uint32 ip, uint16 port) { try { switch (opcode) { // VC-SearchDream[2007-04-18]: For SourceExchange NAT Begin case OP_UDPSENATREQ: { CSafeMemFile data(packet, size); uchar userhash[16]; data.ReadHash16(userhash); // Read the NAT Target Client's UserHash T_TRACE("\nReceive UDP SourceExchange NAT Request , IP : %d Port : %d!\n", ip, port); CUpDownClient * pClient = theApp.clientlist->FindClientByUserHash(userhash); if (pClient) { data.ReadHash16(userhash); // Read the Request Client's UserHash uint32 con = data.ReadUInt32(); try { if (!pClient->IsLowToLowClient() && (pClient->socket && pClient->socket->IsConnected())) { //非LTL连接,且处于已连接状态 CSafeMemFile data_out; data_out.WriteUInt32(ip); data_out.WriteUInt16(htons(port)); data_out.WriteHash16(userhash); data_out.WriteUInt32(con); Packet* natreq = new Packet(&data_out, OP_EMULEPROT, OP_TCPSENATREQ); TRACE("\nThe Client is Exist and Send TCP SourceExchange NAT Request!\n"); pClient->socket->SendPacket(natreq, true, true, 0, true); } else { //LTL连接或处于未连接状态 uint16 uPort = htons(port); byte pack[1+1+4+2+16+4]; pack[0] = OP_EMULEPROT; pack[1] = OP_UDPTOUDPSENATREQ; memcpy(pack+2, &ip, 4); memcpy(pack+6, &uPort, 2); memcpy(pack+8, userhash, 16); memcpy(pack+24, &con, 4); T_TRACE("\nThe Client is Exist and Send UDP SourceExchange NAT Request!\n"); SendUDPPacket(pClient->GetIP(), htons(pClient->GetUDPPort()), pack, 1+1+4+2+16+4, pClient); } } catch(...) { return false; } } break; } case OP_UDPSENATACK: { CSafeMemFile data(packet, size); uchar userhash[16]; data.ReadHash16(userhash); // Read the Request Client's UserHash T_TRACE("\nReceive UDP SourceExchange NAT Response , IP : %d Port : %d!\n", ip, port); CUpDownClient * pClient = theApp.clientlist->FindClientByUserHash(userhash); if (pClient) { data.ReadHash16(userhash); // Read the NAT Target Client's UserHash uint32 con = data.ReadUInt32(); try { if (!pClient->IsLowToLowClient() && (pClient->socket && pClient->socket->IsConnected())) { CSafeMemFile data_out; data_out.WriteUInt32(ip); data_out.WriteUInt16(htons(port)); data_out.WriteHash16(userhash); data_out.WriteUInt32(con); Packet* natack = new Packet(&data_out, OP_EMULEPROT, OP_TCPSENATACK); T_TRACE("\nThe Client is Exist and Send TCP SourceExchange NAT Response!\n"); pClient->socket->SendPacket(natack, true, true, 0, true); } else { uint16 uPort = htons(port); byte pack[1+1+4+2+16+4]; pack[0] = OP_EMULEPROT; pack[1] = OP_UDPTOUDPSENATACK; memcpy(pack+2, &ip, 4); memcpy(pack+6, &uPort, 2); memcpy(pack+8, userhash, 16); memcpy(pack+24, &con, 4); T_TRACE("\nThe Client is Exist and Send UDP SourceExchange NAT Response!\n"); SendUDPPacket(pClient->GetIP(), htons(pClient->GetUDPPort()), pack, 1+1+4+2+16+4, pClient); } } catch(...) { return false; } } break; } case OP_UDPTOUDPSENATREQ: { T_TRACE("\nReceive UDP SourceExchange NAT Request!\n"); CSafeMemFile data(packet, size); byte * natpack = new byte[4+1+4+2+16+4]; memset(natpack, 0, 4+1+4+2+16+4); natpack[4] = OP_NAT_SYNC; memcpy(natpack+5, packet, size); uint32 uUserIP = data.ReadUInt32(); uint16 uUdpPort = data.ReadUInt16(); T_TRACE("\nIP:%d Port:%d\n", uUserIP, uUdpPort); uchar userhash[16]; data.ReadHash16(userhash); uint32 con = data.ReadUInt32(); byte * pack = new byte[1+1+16+16+4]; pack[0] = OP_EMULEPROT; pack[1] = OP_UDPSENATACK; memcpy(pack+2, userhash, 16); memcpy(pack+18, thePrefs.GetUserHash(), 16); memcpy(pack+34, &con, 4); T_TRACE("\nSend UDP SourceExchange NAT Response!\n"); CNatSocket::SendPacket(ip, htons(port), pack, 1+1+16+16+4); delete []pack; pack = NULL; theApp.natthread->ProcessPacket(natpack, 4+1+4+2+16+4, ip, htons(port)); delete []natpack; natpack = NULL; break; } case OP_UDPTOUDPSENATACK: { CSafeMemFile data(packet, size); byte natpack[4+1+4+2+16+4]; memset(natpack, 0, 4+1+4+2+16+4); natpack[4] = OP_NAT_SYNC; memcpy(natpack+5, packet, size); uint32 uUserIP = data.ReadUInt32(); uint16 uUdpPort = data.ReadUInt16(); uchar userhash[16]; data.ReadHash16(userhash); CUpDownClient* pClient = theApp.clientlist->FindClientByUserHash(userhash); if (pClient) { pClient->SetIP(uUserIP); pClient->SetUDPPort(uUdpPort); T_TRACE("\nReceive UDP SourceExchange NAT Response!\n"); theApp.natthread->ProcessPacket(natpack, 4+1+4+2+16+4, ip, htons(port)); } break; } case OP_UDPREGISTER: { CSafeMemFile data(packet, size); uchar userhash[16]; data.ReadHash16(userhash); // Read the Request Client's UserHash CUpDownClient* pClient = theApp.clientlist->FindClientByUserHash(userhash); T_TRACE("\nReceive Register From CSourceExchangeNAT::ProcessUDPPacket\n"); if (pClient) { if (port != pClient->GetUDPPort()) { pClient->SetUDPPort(port); } pClient->SetRegisterTime(); } break; } case OP_UDPKEEPALIVE: { CUpDownClient* pClient = theApp.clientlist->FindClientByIP_UDP(ip, port); T_TRACE("\nReceive KeepALive From CSourceExchangeNAT::ProcessUDPPacket\n"); if (pClient) { pClient->SetReceiveALiveTime(); } break; } // VC-SearchDream[2007-04-18]: For SourceExchange NAT End case OP_SECALLBACK: { CSafeMemFile data(packet, size); uchar fileid[16]; data.ReadHash16(fileid); CKnownFile* reqfile; if ( (reqfile = theApp.sharedfiles->GetFileByID(fileid)) == NULL ) { if ( (reqfile = theApp.downloadqueue->GetFileByID(fileid)) == NULL) { /*socket->client->CheckFailedFileIdReqs(fileid);*/ break; } } uint32 ip = data.ReadUInt32(); uint16 tcp = data.ReadUInt16(); CUpDownClient* callback; callback = theApp.clientlist->FindClientByIP(ntohl(ip), tcp); if ( callback == NULL ) { callback = new CUpDownClient(NULL,tcp,ip,0,0, true); theApp.clientlist->AddClient(callback); } callback->TryToConnect(true); break; } default: { return true; } } } catch(...) { return false; // The Process is Over Although Failure } return false; }
void CTraverseByBuddy::OnRecvPing(const uchar * data, int /*len*/, DWORD ip, WORD port) { //UINT realsize=len-1; const uchar * realdata=data+1; const uchar * hash=realdata; DWORD ConnAck=0; memcpy(&ConnAck, hash+16, 4); T_TRACE("recv ping 2. %02X%02X%02X%02X, ConnAck=%d\n", hash[0], hash[1], hash[2], hash[3], ConnAck); CAsyncSocketEx * pASock=NULL; if(ConnAck && !m_dwConnAskNumber) m_dwConnAskNumber = ConnAck; pASock = m_Sock; ASSERT(pASock); if(!pASock) { T_TRACE("no AsyncsocketEx for unconnect sk\n"); Failed(); return; } CNatSocket * nsock = NULL; if( CGlobalVariable::natthread ) { nsock = CGlobalVariable::natthread->FindNatSocket(hash); if(nsock) { Finish(); return ; } } nsock=new CNatSocket(pASock); nsock->m_dwConnAskNumber= m_dwConnAskNumber; sUserModeTCPConfig * tc=new sUserModeTCPConfig(ip, port); nsock->SetConfig(tc); // nsock->m_bTraverseBySvr= true; // m_dwTraverseBySvr++; nsock->m_TraversalType = CNatSocket::Traversal_bybuddy; memcpy(nsock->GetUserHash(), hash, 16); if( CGlobalVariable::natthread ) { CGlobalVariable::natthread->AddNatSocket(pASock, nsock); CGlobalVariable::natthread->RemoveUnconnSocket(hash); //ADDED by VC-fengwen on 2007/10/15 : sock连通后,在unconnectsocket里要清除它。 _AddLogLine(false, _T("NAT traversal connected. %s."), UserHashToString(hash)); CGlobalVariable::natthread->RemoveTempASock(hash); } //pASock->TriggerEvent(FD_CONNECT); //pASock->TriggerEvent(FD_WRITE); CClientReqSocket * pClientSock = NULL; try { pClientSock = DYNAMIC_DOWNCAST(CClientReqSocket, pASock); } catch(...) { TRACE("Exception: %s\n", __FUNCTION__); Failed(); return ; } if(pClientSock && pClientSock->client) { pClientSock->client->SetIP(ip); pClientSock->client->ResetIP2Country(); } else Failed(); Finish(); }
void CTraverseByBuddy::OnRecvSync(const uchar * data, int /*len*/, DWORD /*ip*/, WORD /*port*/) { //UINT realsize=len-1; const uchar * realdata=data+1; DWORD cip = *(DWORD*)(realdata); WORD cport = *(WORD*)(realdata+4); if(cip==0 || cport==0) { return; } const uchar * id=realdata+6; DWORD ConnAck = 0; memcpy(&ConnAck, id+16, 4); T_TRACE("recv sync, ConnAck=%08x\n", ConnAck); #ifdef _DEBUG in_addr addr; addr.s_addr = cip; T_TRACE("peer addr of %02X%02X%02X%02X = %s:%d\n", id[0], id[1], id[2],id[3], inet_ntoa(addr), ntohs(cport)); #endif uchar myid[16]; GetMyUserHash(myid); if(memcmp(id, myid, 16)==0) { _AddLogLine(false, _T("ERROR: recv myself for traversal")); return; } CAsyncSocketEx * pASock=NULL; CUpDownClient * pClient= CGlobalVariable::clientlist->FindClientByUserHash(id); if(pClient) { pASock = pClient->socket; if(! pASock) { CRuntimeClass * pClassSocket = RUNTIME_CLASS(CClientReqSocket); CClientReqSocket * socket = static_cast<CClientReqSocket*>(pClassSocket->CreateObject()); socket->SetClient(pClient); if (!socket->Create()) { socket->Safe_Delete(); return; } pClient->socket = socket; pASock = socket; } ASSERT(pASock); if(! pASock) return; } else { T_TRACE("\n->%s: Accept a incoming sock for %02X%02X%02X%02X\n", __FUNCTION__, id[0],id[1],id[2],id[3]); if( CGlobalVariable::natthread ) pASock = CGlobalVariable::natthread->GetTempASock(id); } m_dwClientIp = cip; m_wClientPort = cport; m_dwState |=NAT_S_SYNC; SendPingPacket(); }
bool CNatThread::ProcessPacket(const BYTE* packet, UINT size, uint32 ip, uint16 port) { uint8 opcode=packet[4]; const uchar * realdata=packet+5; UINT realsize=size-5; CSingleLock locker(&m_Mutex, TRUE); // modiefied by robert, 2010-08-03 // beta版屏蔽try,以求暴露更多问题 #ifndef _BETA try { #endif switch(opcode) { case OP_NAT_REPING: OnReping(ip, port, realdata, realsize); break; case OP_NAT_REGISTER: // VC-SearchDream[2007-06-15]: Add Login Support if (realsize >= 2 && !m_bRegister && ip==m_dwSvrIp && port==m_wSvrPort ) { if (realsize >= 6) { WORD port = *(WORD*)(realdata); DWORD ip = *(DWORD*)(realdata + 2); if (ip != m_dwSvrIp || port != m_wSvrPort) { m_dwSvrIp = ip; m_wSvrPort = port; m_bRegister = false; RegisterMe(m_dwSvrIp,m_wSvrPort); m_dwRegAttemptTimes = 1; m_dwRegNextAttempInterval = INIT_ATTEMPT_INTERVAL*2; break; } } else { WORD port = *(WORD*)(realdata); if (port != m_wSvrPort) { m_wSvrPort = port; m_bRegister = false; RegisterMe(m_dwSvrIp,m_wSvrPort); m_dwRegAttemptTimes = 1; m_dwRegNextAttempInterval = INIT_ATTEMPT_INTERVAL*2; T_TRACE("new server port : %d.", ntohs(port)); break; } } } m_dwSvrRetTime = time(NULL); if(!m_bRegister) { m_bRegister=true; m_dwSvrKeepalive = time(NULL); m_dwRegAttemptTimes = 0; m_dwRegNextAttempInterval = INIT_ATTEMPT_INTERVAL; T_TRACE("reset svr time in register"); AddLogLine(false, _T("Registered to NAT traversal server\n")); } break; case OP_NAT_FAILED: { /* if(realdata[0]==2) { m_bRegister = false; break; } else */if(realdata[0]==1) { realdata++; realsize--; int n=realsize/16; if(ProcessStrategyPacket(realdata, ip, port, packet+4, size-4)) break; for(int i=0; i<n; i++) { TRACE(_T("failed conn request for %s\n"),UserHashToString(realdata)); CUnconnSocket * us= FindUnconnectSocket(realdata); if(us) us->m_dwState |= NAT_E_NOPEER; realdata+=16; } } } break; //case OP_NAT_SYNC2: //if(ProcessStrategyPacket(realdata+6, ip, port, packet+4, size-4)) // break; //OnSync2(ip, port, realdata, realsize); //break; case OP_NAT_SYNC2: case OP_NAT_SYNC: OnSync(ip, port, realdata, realsize); break; case OP_NAT_PING: OnPing(ip, port, realdata, realsize); break; case OP_NAT_DATA: { if(size < 4) // ACK (+ DATA) break; DWORD ConnAck = 0; memcpy(&ConnAck, realdata, 4); realdata += 4; realsize -= 4; CNatSocket* source = FindNatSocket(ip, port, ConnAck); if( source == NULL ) { #ifdef _DEBUG_NAT TRACE("\n*** no nat sock to recv NAT_DATA. connack=%08x\n", ConnAck); #endif uint32 uSequenceNr = PeekUInt32(realdata); if(uSequenceNr==1) { uchar pack[16]; GetMyUserHash(pack); CNatSocket::SendPacket(ip, port, OP_NAT_REPING, pack, 16); } else { CNatSocket::SendPacket(ip, port, OP_NAT_RST, NULL, 0); } break; } if(source->ProcessDataPacket(realdata, realsize)) { //TRACE("source->ProcessDataPacket is OK. tag=%08x. Asyncsock=%08x\n", tag,source->GetParent()); //source->OnReceive(0); source->m_Parent->TriggerEvent(FD_READ); return true; } else { T_TRACE("\nFailed to source->ProcessDataPacket. ConnAck=%08x\n\n", ConnAck); } break; } case OP_NAT_ACK: { DWORD ConnAck = 0; memcpy(&ConnAck, realdata, 4); realdata+=4; realsize-=4; CNatSocket* source = FindNatSocket(ip, port, ConnAck); if( source == NULL ) { #ifdef _DEBUG_NAT TRACE("\nsend RST for no nat sock to do NAT_ACK\n"); #endif CNatSocket::SendPacket(ip, port, OP_NAT_RST,0,0); break; } source->ProcessAckPacket(realdata, realsize); break; } case OP_NAT_RST: { break; } default: TRACE("Unknown command\n"); break; } // modiefied by robert, 2010-08-03 // beta版屏蔽try,以求暴露更多问题 #ifndef _BETA }catch(...) { TRACE("Exception: %s\n", __FUNCTION__); } #endif return true; }
void CNatThread::OnSync(DWORD ip, WORD port, const uchar * pData, int nDataSize) { // modified by robert, 2010-07-30 加锁 CSingleLock locker(&m_Mutex, TRUE); if(ip==m_dwSvrIp && port==m_wSvrPort) { m_dwSvrRetTime = time(NULL); T_TRACE("reset svr time in sync"); } DWORD cip = *(DWORD*)(pData); WORD cport = *(WORD*)(pData+4); if(cip==0 || cport==0) { return; } const uchar * id=pData+6; DWORD ConnAck = 0; memcpy(&ConnAck, id+16, 4); CNatSocket * nsock=FindNatSocket(id); if(nsock) { nsock->SetTargetAddr(cip, cport); if(nsock->m_dwConnAskNumber!=ConnAck) { // VC-linhai[2007-08-06]:warning C4189: “pOldParent” : 局部变量已初始化但不引用 //CAsyncSocketEx * pOldParent=nsock->GetParent(); nsock->RenewNatSock(); nsock->m_dwConnAskNumber = ConnAck; } uchar pack[20]; GetMyUserHash(pack); memcpy(pack+16, &nsock->m_dwConnAskNumber, 4); nsock->SendPacket(OP_NAT_PING, pack, 20); return; } if(WakeupNatSocketFromPool(id, cip, cport, ConnAck)) return; if(ProcessStrategyPacket(id, ip, port, pData-1, nDataSize+1)) // Include opcode return; uchar myid[16]; GetMyUserHash(myid); if(memcmp(id, myid, 16)==0) { _AddLogLine(false, _T("ERROR: recv myself for traversal")); return; } // create a new unconnect socket CAsyncSocketEx * pASock=NULL; pASock = GetTempASock(id); ASSERT(pASock); CUnconnSocket * usock=FindUnconnectSocket(id);// FindUnconnectSocketByIP(cip, cport); if(! usock) { TRACE("create unconnsock for recv sync. asyncsock=%08x\n", pASock); usock = new CUnconnSocket(ip, port, pASock, id); usock->m_dwConnAskNumber = 0; usock->m_dwClientIp = cip; usock->m_wClientPort =cport; m_UnConnectSocket.AddTail(usock); _AddDebugLogLine(false, _T("CNatThread::ProcessPacket Create CUnconnSocket Successful for %s!\n"),ipstr(cip,cport)); } else { //ASSERT(usock->m_MyVSock==tag); usock->m_dwClientIp = cip; usock->m_wClientPort = cport; } usock->m_dwState |=NAT_S_SYNC; usock->SendPingPacket(); }
void CNatThread::OnPing(DWORD ip, WORD port, const uchar * pData, int nDataSize) { // modified by robert, 2010-07-30 加锁 CSingleLock locker(&m_Mutex, TRUE); if(nDataSize==0) { //数据区长度为0 if(ip==m_dwSvrIp && port==m_wSvrPort) { m_dwSvrRetTime = time(NULL); T_TRACE("reset svr time in ping"); return; } POSITION pos = m_SockMap.GetHeadPosition(); while(pos) { CNatSocket * nsock=m_SockMap.GetNext(pos)->m_value; if(nsock && nsock->GetTargetIP()==ip && nsock->GetTargetPort()==port) { #ifdef _DEBUG_NAT const uchar * id=nsock->GetUserHash(); TRACE("recv keepalive from %02X%02X%02X%02X \n", id[0],id[1],id[2],id[3]); #endif nsock->m_dwRecvKeepalive = time(NULL); } } pos = m_NatSockPool.GetHeadPosition(); while(pos) { CNatSocket * nsock=m_NatSockPool.GetNextValue(pos); if(nsock && nsock->GetTargetIP()==ip && nsock->GetTargetPort()==port) { #ifdef _DEBUG_NAT const uchar * id=nsock->GetUserHash(); TRACE("recv keepalive(sock pool) from %02X%02X%02X%02X \n", id[0],id[1],id[2],id[3]); #endif nsock->m_dwRecvKeepalive = time(NULL); } } return; } //数据区长度非0,数据区为user hash, Connack const uchar * hash=pData; if(ProcessStrategyPacket(hash, ip, port, pData-1, nDataSize+1)) // Include opcode return;//必然不返回 DWORD ConnAck=0; memcpy(&ConnAck, hash+16, 4); TRACE("recv ping 1. %02X%02X%02X%02X, ConnAck=%d\n", hash[0], hash[1], hash[2], hash[3], ConnAck); CAsyncSocketEx * pASock=NULL; CUnconnSocket * usock=FindUnconnectSocket(hash); if(usock) { //发现此未连接用户 if(ConnAck && !usock->m_dwConnAskNumber) usock->m_dwConnAskNumber = ConnAck; pASock = usock->m_Sock; if(!pASock) { //未发现此用户套接字 TRACE("no AsyncsocketEx for unconnect sk\n"); POSITION pos = m_UnConnectSocket.GetHeadPosition(), curPos; while(pos) { curPos = pos; CUnconnSocket * us= m_UnConnectSocket.GetNext(pos); if(us && memcmp(us->m_ClientId, hash, 16)==0) { TRACE("remove invalid unconnected sk\n"); RemoveSocketInUnconn(curPos); break; } } return; } } else { //未发现此未连接用户 if(nDataSize>20) return; CNatSocket * nsock = FindNatSocket(hash); if(! nsock) { //未发现此nat用户 nsock =WakeupNatSocketFromPool(hash); if(! nsock) { TRACE("*** recv a invalid ping. %02X%02X%02X%02X\n", hash[0], hash[1], hash[2], hash[3]); return; } if(ConnAck) nsock->m_dwConnAskNumber = ConnAck; } if(nsock->m_dwConnAskNumber!=ConnAck) { T_TRACE("invalid ConnAck for ping.ConnAck=%d", ConnAck); return; //nsock->DumpData(); } nsock->m_UserModeTCPConfig->TargetIP = ip; nsock->m_UserModeTCPConfig->TargetPort = port; uchar pack[21]; GetMyUserHash(pack); memcpy(pack+16, &ConnAck, 4); nsock->SendPacket(OP_NAT_PING, pack, 21); TRACE("I am connected, echo a ping for connecting. %02X%02X%02X%02X\n", hash[0], hash[1], hash[2], hash[3]); //nsock->GetParent()->TriggerEvent(FD_CONNECT); return; } //发现此用户套接字,此部分不可能被执行到 ASSERT(pASock); CNatSocket * nsock=new CNatSocket(pASock); nsock->m_dwConnAskNumber= usock->m_dwConnAskNumber; sUserModeTCPConfig * tc=new sUserModeTCPConfig(ip, port); nsock->SetConfig(tc); nsock->m_dwRecvKeepalive = time(NULL); //if(! usock->m_bByBuddy) //{ // nsock->m_bTraverseBySvr= true; // m_dwTraverseBySvr++; //} nsock->m_TraversalType = CNatSocket::Traversal_bysvr; ASSERT(m_SockMap.Lookup(pASock)==0); //m_SockMap.SetAt(pASock, nsock); AddNatSocket(pASock, nsock); memcpy(nsock->GetUserHash(), hash, 16); POSITION pos =m_UnConnectSocket.Find(usock); if(pos) { m_UnConnectSocket.RemoveAt(pos); } _AddLogLine(false, _T("NAT traversal connected. %s."), UserHashToString(hash)); RemoveTempASock(hash); //nsock->m_Parent->TriggerEvent(FD_CONNECT); //nsock->m_Parent->TriggerEvent(FD_WRITE); CClientReqSocket * pClientSock = DYNAMIC_DOWNCAST(CClientReqSocket, pASock); if(pClientSock && pClientSock->client) { pClientSock->client->SetIP(ip); pClientSock->client->ResetIP2Country(); } delete usock; }
void CNatThread::OnReping(DWORD ip, WORD port, const uchar * pData, int nDataSize) { CNatSocket * nsock=NULL; // modified by robert, 2010-07-30 加锁 CSingleLock locker(&m_Mutex, TRUE); POSITION pos = m_SockMap.GetHeadPosition(); while(pos) { CNatSocket * tmp=m_SockMap.GetNext(pos)->m_value; if(tmp && memcmp(pData, tmp->GetUserHash(), 16)==0) { nsock = tmp; break; } } T_TRACE("%s, nDataSize=%d. %02X%02X%02X%02X", __FUNCTION__ , nDataSize, pData[0],pData[1],pData[2],pData[3]); if(nDataSize==16) { if(!nsock) { T_TRACE("no NatSock for REPING 1. %02X%02X%02X%02X", pData[0],pData[1],pData[2],pData[3]); return; } uchar pack[20]; GetMyUserHash(pack); memcpy(pack+16, &nsock->m_dwConnAskNumber, 4); CNatSocket::SendPacket(ip, port, OP_NAT_REPING, pack, 20); } else if(nDataSize==20) { DWORD dwConnAck=0; memcpy(&dwConnAck, pData+16, 4); T_TRACE("reping tell ConnAck=%d", dwConnAck); if(! dwConnAck) return; if(nsock) { nsock->m_dwConnAskNumber = dwConnAck; return; } // from natsock pool CNatSocket * nsock_inpool=NULL; if(m_NatSockPool.Lookup(pData, nsock_inpool)) { m_NatSockPool.RemoveKey(pData); nsock_inpool->m_Parent = CGlobalVariable::listensocket->OnAcceptEx(0); nsock_inpool->m_dwConnAskNumber=dwConnAck; ASSERT(nsock_inpool->m_UserModeTCPConfig); nsock_inpool->m_UserModeTCPConfig->TargetIP = ip; nsock_inpool->m_UserModeTCPConfig->TargetPort = port; //m_SockMap.SetAt(nsock_inpool->m_Parent, nsock_inpool); AddNatSocket(nsock_inpool->m_Parent, nsock_inpool); RemoveUnconnSocket(pData); //ADDED by VC-fengwen on 2007/10/15 : sock连通后,在unconnectsocket里要清除它。 return; } CAsyncSocketEx * pASock = RemoveUnconnSocket(pData); if(!pASock) pASock = CGlobalVariable::listensocket->OnAcceptEx(0); CNatSocket * nsock=new CNatSocket(pASock); nsock->m_dwConnAskNumber =dwConnAck ; memcpy(nsock->GetUserHash(), pData, 16); sUserModeTCPConfig * tc=new sUserModeTCPConfig(ip, port); nsock->SetConfig(tc); nsock->m_dwRecvKeepalive = time(NULL); //m_SockMap.SetAt(pASock, nsock); AddNatSocket(pASock, nsock); } }