void CTraverseBySourceExchange::SendPacket() { m_bFailed = m_dwState & NAT_E_NOPEER; try { if(!m_bFailed && (m_dwState&NAT_S_SYNC)==0 && time(NULL)-m_SendReqTime > 5) // 5 seconds { // failed to connect if(m_nSendReqCount > 12) { m_dwState|=NAT_E_TIMEOUT; if(m_nSendReqCount>23) Failed(); m_nSendReqCount++; } else { if(m_nSendReqCount==0) _AddLogLine(false, _T("Begin to connect %s."), UserHashToString(m_UserHash)); SendConnectReq(); } } if(m_bFailed) { if(m_Sock)// && pClientSock->client) { //m_Sock->m_bUseNat = false; } if(m_dwState & NAT_E_NOPEER) { _AddLogLine(false, _T("Unconnected NatSock was deleted. server return E_NOPEER. %s."), UserHashToString(m_UserHash)); } else { _AddLogLine(false, _T("Unconnected NatSock was deleted. time out. %s."), UserHashToString(m_UserHash)); } } if(m_dwState & NAT_S_SYNC && time(NULL)-m_SendPingTime >4) { if(m_nPassivePing> 15) { _AddLogLine(false, _T("Passive Unconnected NatSock was deleted. timeout. %s."), UserHashToString(m_UserHash)); Failed(); } else { SendPingPacket(); } } } catch(...) { // the CAsyncSocketEx maybe is deleted Failed(); } }
void CNatThread::RemoveNatSocket(const uchar *UserId) { USERHASH k(UserId); CNatSocket * nsock=NULL; CSingleLock locker(&m_Mutex, TRUE); if(m_NatSockPool.Lookup(k, nsock)) { m_NatSockPool.RemoveKey(k); _AddLogLine(false, _T("NatSock (in sock pool) was deleted. by above application. %s."), UserHashToString(nsock->GetUserHash())); delete nsock; } }
void CTraverseByBuddy::SendPacket() { try { if(!m_bFailed && (m_dwState&NAT_S_SYNC)==0 && time(NULL)-m_SendReqTime > 10) { // failed to connect if(m_nSendReqCount>60) { m_dwState|=NAT_E_TIMEOUT; if(m_nSendReqCount>70) Failed(); m_nSendReqCount++; } else { SendConnectReq(); SendPingPacket(); } } if(m_bFailed) { if(m_Sock)// && pClientSock->client) { //m_Sock->m_bUseNat = false; } _AddLogLine(false, _T("Unconnected NatSock was deleted. time out. %s."), UserHashToString(m_UserHash)); } } catch(...) { // the CAsyncSocketEx maybe is deleted TRACE("Exception: %s\n", __FUNCTION__); Failed(); } }
void CNatThread::RemoveSocket(CAsyncSocketEx * sock,bool bDisconnectAll/*=false*/,const uchar* pUserHash/*=NULL*/) { //AFX_MANAGE_STATE(AfxGetStaticModuleState()) CSingleLock locker(&m_Mutex, TRUE); CNatSocket *nsock=NULL; m_SockMap.Lookup(sock, nsock); if(nsock) { #ifdef _DEBUG_NAT _AddLogLine(false, _T("NatSock was put into pool. by above application. %s."), UserHashToString(nsock->GetUserHash())); #endif m_SockMap.RemoveKey(sock); RemoveTempASock(nsock->GetUserHash()); if(bDisconnectAll) { delete nsock; } else { nsock->DumpData(); nsock->m_Parent = NULL; nsock->m_dwConnAskNumber = 0; m_NatSockPool.SetAt(nsock->GetUserHash(), nsock); } } RemoveSocketInUnconn(sock); if( bDisconnectAll && pUserHash ) { RemoveStrategy( pUserHash ); RemoveNatSocket( pUserHash ); } }
void CTraverseBySourceExchange::OnRecvPing(const uchar * data, int /*len*/, DWORD ip, WORD port) { if( NULL==CGlobalVariable::natthread ) return; TRACE("\nReceive Ping From Source Exchange!\n"); // For the strict design Process if (!(m_dwState & NAT_S_SYNC)) { TRACE("\nReceive Ping before Sync!\n"); return; } //UINT realsize=len-1;// VC-linhai[2007-08-06]:warning C4189: “realsize” : 局部变量已初始化但不引用 const uchar * realdata=data+1; const uchar * hash=realdata; DWORD ConnAck=0; memcpy(&ConnAck, hash+16, 4); TRACE("recv ping 3. %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) { TRACE("no AsyncsocketEx for unconnect sk\n"); Failed(); return; } CNatSocket * 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_TraversalType = CNatSocket::Traversal_byexchangesource; memcpy(nsock->GetUserHash(), hash, 16); 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 = DYNAMIC_DOWNCAST(CClientReqSocket, pASock); if(pClientSock && pClientSock->client) { pClientSock->client->SetIP(ip); pClientSock->client->ResetIP2Country(); } Finish(); }
void CTraverseBySourceExchange::OnRecvSync(const uchar * data, int /*len*/, DWORD /*ip*/, WORD /*port*/) { TRACE("Receive NAT Sync Request From Source Exchange!\n"); //UINT realsize=len-1;// VC-linhai[2007-08-06]:warning C4189: “realsize” : 局部变量已初始化但不引用 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); TRACE("recv sync, ConnAck=%08x\n", ConnAck); #ifdef _DEBUG in_addr addr; addr.s_addr = cip; 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 { TRACE("\n->%s: Accept a incoming sock for %02X%02X%02X%02X\n", __FUNCTION__, id[0],id[1],id[2],id[3]); pASock = CGlobalVariable::natthread->GetTempASock(id); } m_dwClientIp = cip; m_wClientPort = cport; m_dwState |=NAT_S_SYNC; SendPingPacket(); }
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 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::CheckConnection() { // modified by robert, 2010-07-30 加锁 CSingleLock locker(&m_Mutex, TRUE); POSITION pos = NULL, posCur=NULL; if(! m_UnConnectSocket.IsEmpty()) { pos = m_UnConnectSocket.GetHeadPosition(); for(; pos!=NULL; ) { posCur = pos; CUnconnSocket * usock=m_UnConnectSocket.GetNext(pos); if(!usock) { m_UnConnectSocket.RemoveAt(posCur); continue; } if(usock->m_dwState & NAT_S_SYNC && time(NULL)-usock->m_SendPingTime >4) { if(usock->m_nPassivePing> 15) { if(usock->m_Sock) { usock->m_Sock->TriggerEvent(FD_FAILED, 1); } _AddLogLine(false, _T("Passive Unconnected NatSock was deleted. timeout. %s."), UserHashToString(usock->m_ClientId)); RemoveSocketInUnconn(posCur); } else usock->SendPingPacket(); } } } pos = m_SockMap.GetHeadPosition(); while(pos) { posCur=pos; CNatSocket * nsock=m_SockMap.GetNextValue(pos); if(!nsock) { m_SockMap.RemoveAt(posCur); continue; } if(time(NULL) - nsock->m_dwRecvKeepalive > 4*TM_KEEPALIVE) { _AddLogLine(false, _T("NatSock was deleted. timeout. %s."), UserHashToString(nsock->GetUserHash())); m_SockMap.RemoveAt(posCur); delete nsock; } } // check natsock pool pos = m_NatSockPool.GetHeadPosition(); while(pos) { posCur=pos; CNatSocket * nsock=m_NatSockPool.GetNextValue(pos); if(!nsock) { m_SockMap.RemoveAt(posCur); continue; } if(time(NULL) - nsock->m_dwRecvKeepalive > 4*TM_KEEPALIVE) { _AddLogLine(false, _T("NatSock(in pool) was deleted. timeout. %s."), UserHashToString(nsock->GetUserHash())); m_NatSockPool.RemoveAt(posCur); delete nsock; } } if (NULL != theApp.emuledlg) PostMessage(theApp.emuledlg->GetSafeHwnd(), UM_NAT_CHECK_STRATEGIES, 0, 0); }
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; }