// Send a USB descriptor string. The string is stored in PROGMEM as a // plain ASCII string but is sent out as UTF-16 with the correct 2-byte // prefix static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len) { SendControl(2 + string_len * 2); SendControl(3); for(u8 i = 0; i < string_len; i++) { bool r = SendControl(pgm_read_byte(&string_P[i])); r &= SendControl(0); // high byte if(!r) { return false; } } return true; }
// Send a USB descriptor string. The string is stored in PROGMEM as a // plain ASCII string but is sent out as UTF-16 with the correct 2-byte // prefix static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len, uint8_t flags) { SendControl(2 + string_len * 2); SendControl(3); bool pgm = flags & TRANSFER_PGM; for(u8 i = 0; i < string_len; i++) { bool r = SendControl(pgm ? pgm_read_byte(&string_P[i]) : string_P[i]); r &= SendControl(0); // high byte if(!r) { return false; } } return true; }
TInt DDisplayLdd::SendMsg(TMessageBase* aMsg) { TThreadMessage& m=*(TThreadMessage*)aMsg; TInt id = m.iValue; TInt r = KErrNone; // close msg or cancel if (id == (TInt)ECloseMsg || id == KMaxTInt) { r = DLogicalChannel::SendMsg(aMsg); } //asynchronous request else if (id < 0) { TRequestStatus* pS=(TRequestStatus*)m.Ptr0(); r = SendRequest(aMsg); if (r != KErrNone) Kern::RequestComplete(pS,r); } // synchronous request else{ r = SendControl(aMsg); } return r; }
void CNetConnection::Disconnect(const char *pReason) { if(State() == NET_CONNSTATE_OFFLINE) return; if(m_RemoteClosed == 0) { if(pReason) SendControl(NET_CTRLMSG_CLOSE, pReason, str_length(pReason)+1); else SendControl(NET_CTRLMSG_CLOSE, 0, 0); m_ErrorString[0] = 0; if(pReason && pReason != m_ErrorString) str_copy(m_ErrorString, pReason, sizeof(m_ErrorString)); } Reset(); }
int USB_SendControl(uint8_t flags, const void* d, int len) { int sent = len; const uint8_t* data = (const uint8_t*)d; bool pgm = flags & TRANSFER_PGM; while (len--) { uint8_t c = pgm ? pgm_read_byte(data++) : *data++; if (!SendControl(c)) return (-1); } return (sent); }
// Clipped by _cmark/_cend int USB_SendControl(u8 flags, const void* d, int len) { int sent = len; const u8* data = (const u8*)d; bool pgm = flags & TRANSFER_PGM; while (len--) { u8 c = pgm ? pgm_read_byte(data++) : *data++; if (!SendControl(c)) return -1; } return sent; }
int CNetConnection::Connect(NETADDR *pAddr) { if(State() != NET_CONNSTATE_OFFLINE) return -1; // init connection Reset(); m_PeerAddr = *pAddr; mem_zero(m_ErrorString, sizeof(m_ErrorString)); m_State = NET_CONNSTATE_CONNECT; SendControl(NET_CTRLMSG_CONNECT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC)); return 0; }
/*----------------------------------------------------------------------------- - FUNCTION: PacketCheck - - DATE: November 21st, 2013 - - REVISIONS: - 2013/12/02 - Vincent - Created - - - DESIGNER: Vincent Lau - - PROGRAMMER: Vincent Lau - German Villarreal - - INTERFACE: BOOL PacketCheck(HWND hwnd, CHAR* packet) - - RETURNS: void, nothing. - - PARAMETERS: HWND hwnd - a dynamic char buffer that contains the whole file - CHAR* packet: 1024 bytes of data - - NOTES: This is a function that cecks the packet for data. - - -----------------------------------------------------------------------------*/ BOOL PacketCheck(HWND hwnd, CHAR* packet) { char* data = (CHAR*) malloc(1020); data[1020] = '\0'; int lengthOfData = strlen(data); //Make sure we're getting our own packets, not some other packet switch (packet[0]) { case SYN: break; default: // discard packet return FALSE; } switch (packet[1]) { case ENQ: bENQReceived = TRUE; //SendControl(hComm, ACK); bWantToSendACK = TRUE; // Set "what we're waiting for" flag to DC1 waitForType = DC1; break; case ACK: // check if we wanted an ACK if (waitForType == ACK) { // check if we're actually bidding for the line if (bWantLine) ReleaseSemaphore(hWaitForLineSemaphore, 1, NULL); else // check if we're sending a file ReleaseSemaphore(hACKWaitSemaphore, 1, NULL); } break; case DC1: //if we're waiting for a DC2 packet if(waitForType == DC2 || !ErrorCheck(packet+2))//pass data+crcbits { SendControl(hComm, NAK); break; } waitForType = DC2; bWantToSendACK = TRUE; GetData(packet, data); AddToBuffer(data); break; case DC2: // if we're waiting for a DC1 packet if (waitForType == DC1 || !ErrorCheck(packet+2)) { SendControl(hComm, NAK); break; } waitForType = DC1; bWantToSendACK = TRUE; GetData(packet, data); AddToBuffer(data); break; case NAK: //Set "What we're waiting for" flag to ACK waitForType = ACK; SendData(hComm, Packet); // send the previous packet break; case EOT: bENQReceived = FALSE; if (bENQToSend) { ReleaseSemaphore(hWaitForLineSemaphore, 1, NULL); break; } // GO back to IDLE state waitForType = ENQ; break; } return TRUE; }
// connection-less msg packet without token-support void CNetServer::OnPreConnMsg(NETADDR &Addr, CNetPacketConstruct &Packet) { bool IsCtrl = Packet.m_Flags&NET_PACKETFLAG_CONTROL; int CtrlMsg = m_RecvUnpacker.m_Data.m_aChunkData[0]; // log flooding //TODO: remove if (g_Config.m_Debug) { int64 Now = time_get(); if (Now - m_TimeNumConAttempts > time_freq()) // reset m_NumConAttempts = 0; m_NumConAttempts++; if (m_NumConAttempts > 100) { dbg_msg("security", "flooding detected"); m_TimeNumConAttempts = Now; m_NumConAttempts = 0; } } if (IsCtrl && CtrlMsg == NET_CTRLMSG_CONNECT) { if (g_Config.m_SvVanillaAntiSpoof && g_Config.m_Password[0] == '\0') { // detect flooding int64 Now = time_get(); if(Now <= m_VConnFirst + time_freq()) { m_VConnNum++; } else { m_VConnHighLoad = m_VConnNum > g_Config.m_SvVanConnPerSecond; m_VConnNum = 1; m_VConnFirst = Now; } bool Flooding = m_VConnNum > g_Config.m_SvVanConnPerSecond || m_VConnHighLoad; if (g_Config.m_Debug && Flooding) { dbg_msg("security", "vanilla connection flooding detected"); } // simulate accept SendControl(Addr, NET_CTRLMSG_CONNECTACCEPT, NULL, 0, NET_SECURITY_TOKEN_UNSUPPORTED); // Begin vanilla compatible token handshake // The idea is to pack a security token in the gametick // parameter of NETMSG_SNAPEMPTY. The Client then will // return the token/gametick in NETMSG_INPUT, allowing // us to validate the token. // https://github.com/eeeee/ddnet/commit/b8e40a244af4e242dc568aa34854c5754c75a39a // Before we can send NETMSG_SNAPEMPTY, the client needs // to load a map, otherwise it might crash. The map // should be as small as is possible and directly available // to the client. Therefore a dummy map is sent in the same // packet. To reduce the traffic we'll fallback to a default // map if there are too many connection attempts at once. // send mapchange + map data + con_ready + 3 x empty snap (with token) CMsgPacker MapChangeMsg(NETMSG_MAP_CHANGE); if (Flooding) { // Fallback to dm1 MapChangeMsg.AddString("dm1", 0); MapChangeMsg.AddInt(0xf2159e6e); MapChangeMsg.AddInt(5805); } else { // dummy map MapChangeMsg.AddString("dummy", 0); MapChangeMsg.AddInt(DummyMapCrc); MapChangeMsg.AddInt(sizeof(g_aDummyMapData)); } CMsgPacker MapDataMsg(NETMSG_MAP_DATA); if (Flooding) { // send empty map data to keep 0.6.4 support MapDataMsg.AddInt(1); // last chunk MapDataMsg.AddInt(0); // crc MapDataMsg.AddInt(0); // chunk index MapDataMsg.AddInt(0); // map size MapDataMsg.AddRaw(NULL, 0); // map data } else { // send dummy map data MapDataMsg.AddInt(1); // last chunk MapDataMsg.AddInt(DummyMapCrc); // crc MapDataMsg.AddInt(0); // chunk index MapDataMsg.AddInt(sizeof(g_aDummyMapData)); // map size MapDataMsg.AddRaw(g_aDummyMapData, sizeof(g_aDummyMapData)); // map data } CMsgPacker ConReadyMsg(NETMSG_CON_READY); CMsgPacker SnapEmptyMsg(NETMSG_SNAPEMPTY); SECURITY_TOKEN SecurityToken = GetVanillaToken(Addr); SnapEmptyMsg.AddInt((int)SecurityToken); SnapEmptyMsg.AddInt((int)SecurityToken + 1); // send all chunks/msgs in one packet const CMsgPacker *Msgs[] = {&MapChangeMsg, &MapDataMsg, &ConReadyMsg, &SnapEmptyMsg, &SnapEmptyMsg, &SnapEmptyMsg}; SendMsgs(Addr, Msgs, 6); } else { // accept client directly SendControl(Addr, NET_CTRLMSG_CONNECTACCEPT, NULL, 0, NET_SECURITY_TOKEN_UNSUPPORTED); TryAcceptClient(Addr, NET_SECURITY_TOKEN_UNSUPPORTED); } } else if(!IsCtrl && g_Config.m_SvVanillaAntiSpoof && g_Config.m_Password[0] == '\0') { CNetChunkHeader h; unsigned char *pData = Packet.m_aChunkData; pData = h.Unpack(pData); CUnpacker Unpacker; Unpacker.Reset(pData, h.m_Size); int Msg = Unpacker.GetInt() >> 1; if (Msg == NETMSG_INPUT) { SECURITY_TOKEN SecurityToken = Unpacker.GetInt(); if (SecurityToken == GetVanillaToken(Addr)) { if (g_Config.m_Debug) dbg_msg("security", "new client (vanilla handshake)"); // try to accept client skipping auth state TryAcceptClient(Addr, NET_SECURITY_TOKEN_UNSUPPORTED, true); } else if (g_Config.m_Debug) dbg_msg("security", "invalid token (vanilla handshake)"); } else { if (g_Config.m_Debug) { dbg_msg("security", "invalid preconn msg %d", Msg); } } }
int CNetConnection::Update() { int64 Now = time_get(); if(State() == NET_CONNSTATE_ERROR && m_TimeoutSituation && (Now-m_LastRecvTime) > time_freq()*g_Config.m_ConnTimeoutProtection) { m_TimeoutSituation = false; SetError("Timeout Protection over"); } if(State() == NET_CONNSTATE_OFFLINE || State() == NET_CONNSTATE_ERROR) return 0; m_TimeoutSituation = false; // check for timeout if(State() != NET_CONNSTATE_OFFLINE && State() != NET_CONNSTATE_CONNECT && (Now-m_LastRecvTime) > time_freq()*g_Config.m_ConnTimeout) { m_State = NET_CONNSTATE_ERROR; SetError("Timeout"); m_TimeoutSituation = true; } // fix resends if(m_Buffer.First()) { CNetChunkResend *pResend = m_Buffer.First(); // check if we have some really old stuff laying around and abort if not acked if(Now-pResend->m_FirstSendTime > time_freq()*g_Config.m_ConnTimeout) { m_State = NET_CONNSTATE_ERROR; char aBuf[512]; str_format(aBuf, sizeof(aBuf), "Too weak connection (not acked for %d seconds)", g_Config.m_ConnTimeout); SetError(aBuf); m_TimeoutSituation = true; } else { // resend packet if we havn't got it acked in 1 second if(Now-pResend->m_LastSendTime > time_freq()) ResendChunk(pResend); } } // send keep alives if nothing has happend for 250ms if(State() == NET_CONNSTATE_ONLINE) { if(time_get()-m_LastSendTime > time_freq()/2) // flush connection after 500ms if needed { int NumFlushedChunks = Flush(); if(NumFlushedChunks && g_Config.m_Debug) dbg_msg("connection", "flushed connection due to timeout. %d chunks.", NumFlushedChunks); } if(time_get()-m_LastSendTime > time_freq()) SendControl(NET_CTRLMSG_KEEPALIVE, 0, 0); } else if(State() == NET_CONNSTATE_CONNECT) { if(time_get()-m_LastSendTime > time_freq()/2) // send a new connect every 500ms SendControl(NET_CTRLMSG_CONNECT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC)); } else if(State() == NET_CONNSTATE_PENDING) { if(time_get()-m_LastSendTime > time_freq()/2) // send a new connect/accept every 500ms SendControl(NET_CTRLMSG_CONNECTACCEPT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC)); } return 0; }
int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr, SECURITY_TOKEN SecurityToken) { if (State() != NET_CONNSTATE_OFFLINE && m_SecurityToken != NET_SECURITY_TOKEN_UNKNOWN && m_SecurityToken != NET_SECURITY_TOKEN_UNSUPPORTED) { // supposed to have a valid token in this packet, check it if (pPacket->m_DataSize < (int)sizeof(m_SecurityToken)) return 0; pPacket->m_DataSize -= sizeof(m_SecurityToken); if (m_SecurityToken != ToSecurityToken(&pPacket->m_aChunkData[pPacket->m_DataSize])) { if(g_Config.m_Debug) dbg_msg("security", "token mismatch, expected %d got %d", m_SecurityToken, ToSecurityToken(&pPacket->m_aChunkData[pPacket->m_DataSize])); return 0; } } int64 Now = time_get(); // check if resend is requested if(pPacket->m_Flags&NET_PACKETFLAG_RESEND) Resend(); // if(pPacket->m_Flags&NET_PACKETFLAG_CONTROL) { int CtrlMsg = pPacket->m_aChunkData[0]; if(CtrlMsg == NET_CTRLMSG_CLOSE) { if(net_addr_comp(&m_PeerAddr, pAddr) == 0) { m_State = NET_CONNSTATE_ERROR; m_RemoteClosed = 1; char Str[128] = {0}; if(pPacket->m_DataSize > 1) { // make sure to sanitize the error string form the other party if(pPacket->m_DataSize < 128) str_copy(Str, (char *)&pPacket->m_aChunkData[1], pPacket->m_DataSize); else str_copy(Str, (char *)&pPacket->m_aChunkData[1], sizeof(Str)); str_sanitize_strong(Str); } if(!m_BlockCloseMsg) { // set the error string SetError(Str); } if(g_Config.m_Debug) dbg_msg("conn", "closed reason='%s'", Str); } return 0; } else { if(State() == NET_CONNSTATE_OFFLINE) { if(CtrlMsg == NET_CTRLMSG_CONNECT) { NETADDR nAddr; mem_copy(&nAddr, pAddr, sizeof(nAddr)); nAddr.port = 0; m_PeerAddr.port = 0; #ifndef FUZZING if(net_addr_comp(&m_PeerAddr, &nAddr) == 0 && time_get() - m_LastUpdateTime < time_freq() * 3) return 0; #endif // send response and init connection Reset(); m_State = NET_CONNSTATE_PENDING; m_PeerAddr = *pAddr; mem_zero(m_ErrorString, sizeof(m_ErrorString)); m_LastSendTime = Now; m_LastRecvTime = Now; m_LastUpdateTime = Now; if (m_SecurityToken == NET_SECURITY_TOKEN_UNKNOWN && pPacket->m_DataSize >= (int)(1 + sizeof(SECURITY_TOKEN_MAGIC) + sizeof(m_SecurityToken)) && !mem_comp(&pPacket->m_aChunkData[1], SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC))) { m_SecurityToken = SecurityToken; if(g_Config.m_Debug) dbg_msg("security", "generated token %d", m_SecurityToken); } else { if(g_Config.m_Debug) dbg_msg("security", "token not supported by client (packet size %d)", pPacket->m_DataSize); m_SecurityToken = NET_SECURITY_TOKEN_UNSUPPORTED; } SendControl(NET_CTRLMSG_CONNECTACCEPT, SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC)); if(g_Config.m_Debug) dbg_msg("connection", "got connection, sending connect+accept"); } } else if(State() == NET_CONNSTATE_CONNECT) { // connection made if(CtrlMsg == NET_CTRLMSG_CONNECTACCEPT) { if (m_SecurityToken == NET_SECURITY_TOKEN_UNKNOWN && pPacket->m_DataSize >= (int)(1 + sizeof(SECURITY_TOKEN_MAGIC) + sizeof(m_SecurityToken)) && !mem_comp(&pPacket->m_aChunkData[1], SECURITY_TOKEN_MAGIC, sizeof(SECURITY_TOKEN_MAGIC))) { m_SecurityToken = ToSecurityToken(&pPacket->m_aChunkData[1 + sizeof(SECURITY_TOKEN_MAGIC)]); if(g_Config.m_Debug) dbg_msg("security", "got token %d", m_SecurityToken); } else { m_SecurityToken = NET_SECURITY_TOKEN_UNSUPPORTED; if(g_Config.m_Debug) dbg_msg("security", "token not supported by server"); } m_LastRecvTime = Now; SendControl(NET_CTRLMSG_ACCEPT, 0, 0); m_State = NET_CONNSTATE_ONLINE; if(g_Config.m_Debug) dbg_msg("connection", "got connect+accept, sending accept. connection online"); } } } } else { if(State() == NET_CONNSTATE_PENDING) { m_LastRecvTime = Now; m_State = NET_CONNSTATE_ONLINE; if(g_Config.m_Debug) dbg_msg("connection", "connecting online"); } } if(State() == NET_CONNSTATE_ONLINE) { m_LastRecvTime = Now; AckChunks(pPacket->m_Ack); } return 1; }
int CNetConnection::Update() { int64 Now = time_get(); if(State() == NET_CONNSTATE_OFFLINE || State() == NET_CONNSTATE_ERROR) return 0; // check for timeout if(State() != NET_CONNSTATE_OFFLINE && State() != NET_CONNSTATE_CONNECT && (Now-m_LastRecvTime) > time_freq()*10) { m_State = NET_CONNSTATE_ERROR; SetError("timeout"); } // fix resends if(m_Buffer.First()) { CNetChunkResend *pResend = m_Buffer.First(); // check if we have some really old stuff laying around and abort if not acked if(Now-pResend->m_FirstSendTime > time_freq()*10) { m_State = NET_CONNSTATE_ERROR; SetError("too weak connection (not acked for 10 seconds)"); } else { // resend packet if we havn't got it acked in 1 second if(Now-pResend->m_LastSendTime > time_freq()) ResendChunk(pResend); } } // send keep alives if nothing has happend for 250ms if(State() == NET_CONNSTATE_ONLINE) { if(time_get()-m_LastSendTime > time_freq()/2) // flush connection after 500ms if needed { int NumFlushedChunks = Flush(); if(NumFlushedChunks && g_Config.m_Debug) dbg_msg("connection", "flushed connection due to timeout. %d chunks.", NumFlushedChunks); } if(time_get()-m_LastSendTime > time_freq()) SendControl(NET_CTRLMSG_KEEPALIVE, 0, 0); } else if(State() == NET_CONNSTATE_CONNECT) { if(time_get()-m_LastSendTime > time_freq()/2) // send a new connect every 500ms SendControl(NET_CTRLMSG_CONNECT, 0, 0); } else if(State() == NET_CONNSTATE_PENDING) { if(time_get()-m_LastSendTime > time_freq()/2) // send a new connect/accept every 500ms SendControl(NET_CTRLMSG_CONNECTACCEPT, 0, 0); } return 0; }
int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) { int64 Now = time_get(); m_LastRecvTime = Now; // check if resend is requested if(pPacket->m_Flags&NET_PACKETFLAG_RESEND) Resend(); // if(pPacket->m_Flags&NET_PACKETFLAG_CONTROL) { int CtrlMsg = pPacket->m_aChunkData[0]; if(CtrlMsg == NET_CTRLMSG_CLOSE) { if(net_addr_comp(&m_PeerAddr, pAddr) == 0) { m_State = NET_CONNSTATE_ERROR; m_RemoteClosed = 1; if(pPacket->m_DataSize) { // make sure to sanitize the error string form the other party char Str[128]; if(pPacket->m_DataSize < 128) str_copy(Str, (char *)pPacket->m_aChunkData, pPacket->m_DataSize); else str_copy(Str, (char *)pPacket->m_aChunkData, sizeof(Str)); str_sanitize_strong(Str); // set the error string SetError(Str); } else SetError("no reason given"); if(g_Config.m_Debug) dbg_msg("conn", "closed reason='%s'", ErrorString()); } return 0; } else { if(State() == NET_CONNSTATE_OFFLINE) { if(CtrlMsg == NET_CTRLMSG_CONNECT) { // send response and init connection Reset(); m_State = NET_CONNSTATE_PENDING; m_PeerAddr = *pAddr; m_LastSendTime = Now; m_LastRecvTime = Now; m_LastUpdateTime = Now; SendControl(NET_CTRLMSG_CONNECTACCEPT, 0, 0); if(g_Config.m_Debug) dbg_msg("connection", "got connection, sending connect+accept"); } } else if(State() == NET_CONNSTATE_CONNECT) { // connection made if(CtrlMsg == NET_CTRLMSG_CONNECTACCEPT) { SendControl(NET_CTRLMSG_ACCEPT, 0, 0); m_State = NET_CONNSTATE_ONLINE; if(g_Config.m_Debug) dbg_msg("connection", "got connect+accept, sending accept. connection online"); } } else if(State() == NET_CONNSTATE_ONLINE) { // connection made /* if(ctrlmsg == NET_CTRLMSG_CONNECTACCEPT) { }*/ } } } else { if(State() == NET_CONNSTATE_PENDING) { m_State = NET_CONNSTATE_ONLINE; if(g_Config.m_Debug) dbg_msg("connection", "connecting online"); } } if(State() == NET_CONNSTATE_ONLINE) { AckChunks(pPacket->m_Ack); } return 1; }
int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) { // check if actual ack value is valid(own sequence..latest peer ack) if(m_Sequence >= m_PeerAck) { if(pPacket->m_Ack < m_PeerAck || pPacket->m_Ack > m_Sequence) return 0; } else { if(pPacket->m_Ack < m_PeerAck && pPacket->m_Ack > m_Sequence) return 0; } m_PeerAck = pPacket->m_Ack; int64 Now = time_get(); if(pPacket->m_Token == NET_TOKEN_NONE || pPacket->m_Token != m_Token) return 0; // check if resend is requested if(pPacket->m_Flags&NET_PACKETFLAG_RESEND) Resend(); if(pPacket->m_Flags&NET_PACKETFLAG_CONNLESS) return 1; // if(pPacket->m_Flags&NET_PACKETFLAG_CONTROL) { int CtrlMsg = pPacket->m_aChunkData[0]; if(CtrlMsg == NET_CTRLMSG_CLOSE) { if(net_addr_comp(&m_PeerAddr, pAddr) == 0) { m_State = NET_CONNSTATE_ERROR; m_RemoteClosed = 1; char Str[128] = {0}; if(pPacket->m_DataSize > 1) { // make sure to sanitize the error string form the other party if(pPacket->m_DataSize < 128) str_copy(Str, (char *)&pPacket->m_aChunkData[1], pPacket->m_DataSize); else str_copy(Str, (char *)&pPacket->m_aChunkData[1], sizeof(Str)); str_sanitize_strong(Str); } if(!m_BlockCloseMsg) { // set the error string SetError(Str); } if(g_Config.m_Debug) dbg_msg("conn", "closed reason='%s'", Str); } return 0; } else { if(CtrlMsg == NET_CTRLMSG_TOKEN) { m_PeerToken = pPacket->m_ResponseToken; if(State() == NET_CONNSTATE_TOKEN) { m_LastRecvTime = Now; m_State = NET_CONNSTATE_CONNECT; SendControlWithToken(NET_CTRLMSG_CONNECT); dbg_msg("connection", "got token, replying, token=%x mytoken=%x", m_PeerToken, m_Token); } else if(g_Config.m_Debug) dbg_msg("connection", "got token, token=%x", m_PeerToken); } else { if(State() == NET_CONNSTATE_OFFLINE) { if(CtrlMsg == NET_CTRLMSG_CONNECT) { // send response and init connection TOKEN Token = m_Token; Reset(); m_State = NET_CONNSTATE_PENDING; m_PeerAddr = *pAddr; m_PeerToken = pPacket->m_ResponseToken; m_Token = Token; m_LastSendTime = Now; m_LastRecvTime = Now; m_LastUpdateTime = Now; SendControl(NET_CTRLMSG_CONNECTACCEPT, 0, 0); if(g_Config.m_Debug) dbg_msg("connection", "got connection, sending connect+accept"); } } else if(State() == NET_CONNSTATE_CONNECT) { // connection made if(CtrlMsg == NET_CTRLMSG_CONNECTACCEPT) { m_LastRecvTime = Now; SendControl(NET_CTRLMSG_ACCEPT, 0, 0); m_State = NET_CONNSTATE_ONLINE; if(g_Config.m_Debug) dbg_msg("connection", "got connect+accept, sending accept. connection online"); } } } } } else { if(State() == NET_CONNSTATE_PENDING) { m_LastRecvTime = Now; m_State = NET_CONNSTATE_ONLINE; if(g_Config.m_Debug) dbg_msg("connection", "connecting online"); } } if(State() == NET_CONNSTATE_ONLINE) { m_LastRecvTime = Now; AckChunks(pPacket->m_Ack); } return 1; }