Esempio n. 1
0
///////////////////////////////////////////////////////////////////////////////
/// 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);
    }
}
Esempio n. 2
0
///////////////////////////////////////////////////////////////////////////////
/// 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);
}
Esempio n. 3
0
///////////////////////////////////////////////////////////////////////////////
/// 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);
    }
}
Esempio n. 4
0
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);
    }
}
Esempio n. 5
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;
}
Esempio n. 6
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;
}
Esempio n. 7
0
//컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴
//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();
	}
}
Esempio n. 8
0
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;
}