/////////////////////////////////////////////////////////////////////////////// /// CSRConnection::CSRConnection /// @description Send function for the CSRConnection. Sending using this /// protocol involves an alternating bit scheme. Messages can expire and /// delivery won't be attempted after the deadline is passed. Killed messages /// are noted in the next outgoing message. The reciever tracks the killed /// messages and uses them to help maintain ordering. /// @pre The protocol is intialized. /// @post At least one message is in the channel and actively being resent. /// The send window is greater than or equal to one. The timer for the /// resend is freshly set or is currently running for a resend. /// If a message is written to the channel, the m_killable flag is set. /// @param msg The message to write to the channel. /////////////////////////////////////////////////////////////////////////////// void CSRConnection::Send(CMessage msg) { Logger.Debug << __PRETTY_FUNCTION__ << std::endl; ptree x = static_cast<ptree>(msg); unsigned int msgseq; if(m_outsync == false) { SendSYN(); } CMessage outmsg(x); msgseq = m_outseq; outmsg.SetSequenceNumber(msgseq); m_outseq = (m_outseq+1) % SEQUENCE_MODULO; outmsg.SetSourceUUID(GetConnection()->GetConnectionManager().GetUUID()); outmsg.SetSourceHostname(GetConnection()->GetConnectionManager().GetHostname()); outmsg.SetProtocol(GetIdentifier()); outmsg.SetSendTimestampNow(); if(!outmsg.HasExpireTime()) { Logger.Notice<<"Set Expire time"<<std::endl; outmsg.SetExpireTimeFromNow(boost::posix_time::milliseconds(3000)); } m_window.push_back(outmsg); if(m_window.size() == 1) { Write(outmsg); boost::system::error_code x; Resend(x); } }
/////////////////////////////////////////////////////////////////////////////// /// CSRConnection::SendSYN /// @description Composes an SYN and writes it to the channel. /// @param The message to SYN. /// @pre A message has been accepted. /// @post A syn has been written to the channel /////////////////////////////////////////////////////////////////////////////// void CSRConnection::SendSYN() { Logger.Debug << __PRETTY_FUNCTION__ << std::endl; unsigned int seq = m_outseq; freedm::broker::CMessage outmsg; if(m_window.size() == 0) { m_outseq = (m_outseq+1)%SEQUENCE_MODULO; } else { //Don't bother if front of queue is already a SYN if(m_window.front().GetStatus() == CMessage::Created) { return; } //Set it as the seq before the front of queue seq = m_window.front().GetSequenceNumber(); if(seq == 0) { seq = SEQUENCE_MODULO-1; } else { seq--; } } // Presumably, if we are here, the connection is registered outmsg.SetSourceUUID(GetConnection()->GetConnectionManager().GetUUID()); outmsg.SetSourceHostname(GetConnection()->GetConnectionManager().GetHostname()); outmsg.SetStatus(freedm::broker::CMessage::Created); outmsg.SetSequenceNumber(seq); outmsg.SetSendTimestampNow(); outmsg.SetProtocol(GetIdentifier()); Write(outmsg); m_window.push_front(outmsg); m_outsync = true; /// Hook into resend until the message expires. boost::system::error_code x; Resend(x); }
/////////////////////////////////////////////////////////////////////////////// /// CSRConnection::RecieveACK /// @description Marks a message as acknowledged by the reciever and moves to /// transmit the next message. /// @pre A message has been sent. /// @post If the ACK corresponds to the head of window by a match of sequence /// number and the message hash, the the message is popped and the /// killable flag is set to false, since the head of the window has never /// been sent. /// If the there is still an message in the window to send, the /// resend function is called. /////////////////////////////////////////////////////////////////////////////// void CSRConnection::RecieveACK(const CMessage &msg) { Logger.Debug << __PRETTY_FUNCTION__ << std::endl; unsigned int seq = msg.GetSequenceNumber(); ptree pp = msg.GetProtocolProperties(); size_t hash = pp.get<size_t>("src.hash"); if(m_window.size() > 0) { // Assuming hash collisions are small, we will check the hash // of the front message. On hit, we can accept the acknowledge. unsigned int fseq = m_window.front().GetSequenceNumber(); if(fseq == seq && m_window.front().GetHash() == hash) { m_sendkill = fseq; m_window.pop_front(); } } if(m_window.size() > 0) { boost::system::error_code x; Resend(x); } }
void CSUConnection::RecieveACK(const CMessage &msg) { unsigned int seq = msg.GetSequenceNumber(); while(m_window.size() > 0) { unsigned int fseq = m_window.front().msg.GetSequenceNumber(); unsigned int bounda = fseq; unsigned int boundb = (fseq+WINDOW_SIZE)%SEQUENCE_MODULO; if(bounda <= seq || (seq < boundb and boundb < bounda)) { m_window.pop_front(); } else { break; } } if(m_window.size() > 0) { boost::system::error_code x; Resend(x); } }
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::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; }
//컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴 //Procedure AggregatorGetPackets //Date Thu 20 Mar 1997 //------------------------------------------------------------------------------ void Aggregator::AggregatorGetPackets() //Bool reset, Bool timercall) { LPACPACKET RecPacket; HRESULT res; ULong n,m; bool SendResult; myDPID from; DWORD BufferLen; char* Buffer; #ifndef NDEBUG if (!_DPlay.Host) _Error.SayAndQuit("Player processing packets to aggregator!!!!!"); #endif if (ResetFlag) { InitAggregator(); #ifdef AGGLOGS Log("RESET aggregator\n"); #endif } else if (Running) { // calls from timer are every 1/50 sec. Use to determine timeout time++; clearbuffertime++; GetAllMessages(); MakeAndSendAggPacket(); if (buffer) { // only resend packets or clear buffers if we are REAL game mode, not whilst // in resync!!!!!!!!!!!!! if (AllowResendOrBurstCatchUp()) { SLong entry=RequireResend(); if (entry!=-1) { Resend(entry); } else if (BurstInBuffer()) { BurstCatchup(); } } } } else { // receive and junk all messages to aggregator as we are not ready for them yet!!!! ClearMessageQueue(); } }
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; }