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 IpVerify::PrintAuthTable(int dprintf_level) { struct in6_addr host; UserPerm_t * ptable; PermHashTable->startIterations(); while (PermHashTable->iterate(host, ptable)) { MyString userid; perm_mask_t mask; ptable->startIterations(); while( ptable->iterate(userid,mask) ) { // Call has_user() to get the full mask has_user(ptable, userid.Value(), mask); MyString auth_entry_str; AuthEntryToString(host,userid.Value(),mask, auth_entry_str); dprintf(dprintf_level,"%s\n", auth_entry_str.Value()); } } dprintf(dprintf_level,"Authorizations yet to be resolved:\n"); DCpermission perm; for ( perm=FIRST_PERM; perm < LAST_PERM; perm=NEXT_PERM(perm) ) { PermTypeEntry* pentry = PermTypeArray[perm]; ASSERT( pentry ); MyString allow_users,deny_users; if( pentry->allow_users ) { UserHashToString(pentry->allow_users,allow_users); } if( pentry->deny_users ) { UserHashToString(pentry->deny_users,deny_users); } if( allow_users.Length() ) { dprintf(dprintf_level,"allow %s: %s\n", PermString(perm), allow_users.Value()); } if( deny_users.Length() ) { dprintf(dprintf_level,"deny %s: %s\n", PermString(perm), deny_users.Value()); } } }
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(); }
int CTraverseByBuddy::SendConnectReq() { if(m_dwState & NAT_E_TIMEOUT) return 1; m_SendReqTime = time(NULL); m_nSendReqCount++; CClientReqSocket * pClientSock = NULL; try { pClientSock=DYNAMIC_DOWNCAST(CClientReqSocket, m_Sock); } catch(...) { TRACE("Exception: %s\n", __FUNCTION__); Failed(); return 1; } if(pClientSock && pClientSock->client) { m_dwTraverseIp = pClientSock->client->GetBuddyIP(); m_wTraversePort = htons(pClientSock->client->GetBuddyPort()); //if(!m_dwTraverseIp || !m_wTraversePort) // return 1; } else { //T_TRACE("failed to get buddy addr by CUpdownClient"); Failed(); return 1; } Kademlia::CUInt128 uBuddyID(true); uBuddyID.Xor(pClientSock->client->GetBuddyID()); byte cID[16]; uBuddyID.ToByteArray(cID); #ifdef _DEBUG_NAT const uchar *uh=m_UserHash; TRACE(_T("send sync to connect %02X%02X%02X%02X by buddy. kad id=%s\n"), uh[0],uh[1],uh[2],uh[3], UserHashToString(cID)); CString str=ipstr(m_dwTraverseIp, ntohs(m_wTraversePort)); TRACE(_T("\n\n******* buddy dest addr: %s\n"), (LPCTSTR)str); #endif // header + opcode + kadid&reserve + vc_header + sync + myaddr + myid + connack uchar Buf[2+32+1+4+1+6+16+4]; Buf[0] =OP_EMULEPROT; Buf[1] = OP_REASKCALLBACKUDP; // target kad id memcpy(Buf+2, pClientSock->client->GetBuddyID(), 16); memset(Buf+18,0,16); Buf[34] = OP_VC_NAT_HEADER; DWORD packsize=rand(); memcpy(Buf+35, &packsize, 4); Buf[39] = OP_NAT_SYNC; GetMyUserHash((uchar*)Buf+46); memcpy(Buf+62, &m_dwConnAskNumber, 4); //SendPingPacket(); return CNatSocket::SendPacket(m_dwTraverseIp, m_wTraversePort, Buf, 2+32+1+4+1+6+16+4); }
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(); }
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::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; }
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; } }