Example #1
0
void
LX::CommandModeQuick(Port &port, OperationEnvironment &env)
{
  SendSYN(port);
  env.Sleep(500);
  SendSYN(port);
  env.Sleep(500);
  SendSYN(port);
  env.Sleep(500);
}
Example #2
0
void
LX::CommandModeQuick(Port &port, OperationEnvironment &env)
{
  SendSYN(port);
  env.Sleep(std::chrono::milliseconds(500));
  SendSYN(port);
  env.Sleep(std::chrono::milliseconds(500));
  SendSYN(port);
  env.Sleep(std::chrono::milliseconds(500));
}
Example #3
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);
    }
}
Example #4
0
///////////////////////////////////////////////////////////////////////////////
/// CSRConnection::CSRConnection
/// @description Handles refiring ACKs and Sent Messages.
/// @pre The connection has received or sent at least one message.
/// @post One of the following conditions or combination of states is 
///       upheld:
///       1) An ack for a message that has not yet expired has been resent and
///          a timer to call resend has been set.
///       2) Message(s) has/have expired and are removed from the queue. The
///          flag to send kills is set.
///       3) The window is empty and no message is set to the channel, the
///          timer is not re-set.
///       4) A message expired and then next message will cause the sequence
///          numbers to wrap, (or they have wrapped since the last time a message
///          was successfully sent) so a sync is inserted at the front of the queue
///          to skip that case on the receiver side. The sendkill flag is cleared
///          and the sendkill value is cleared.
///       5) If there is still a message to resend, the timer is reset.
/// @param err The timer error code. If the err is 0 then the timer expired
///////////////////////////////////////////////////////////////////////////////
void CSRConnection::Resend(const boost::system::error_code& err)
{
    Logger.Debug << __PRETTY_FUNCTION__ << std::endl;
    if(!err)
    {
        boost::posix_time::ptime now;
        now = boost::posix_time::microsec_clock::universal_time();
        CMessage ack;
        // Check if the front of the queue is an ACK
        if(m_currentack.GetStatus() == freedm::broker::CMessage::Accepted)
        {
            if(!m_currentack.IsExpired())
            {
                Write(m_currentack);
                m_timeout.cancel();
                m_timeout.expires_from_now(boost::posix_time::milliseconds(REFIRE_TIME));
                m_timeout.async_wait(boost::bind(&CSRConnection::Resend,this,
                    boost::asio::placeholders::error));
            }
        }
        while(m_window.size() > 0 && m_window.front().IsExpired())
        {
            //First message in the window should be the only one
            //ever to have been written.
            m_sendkills = true;
            Logger.Notice<<"Message Expired: "<<m_window.front().GetHash()
                          <<":"<<m_window.front().GetSequenceNumber()<<std::endl;
            m_window.pop_front();
        }
        if(m_window.size() > 0)
        {
            if(m_sendkills &&  m_sendkill > m_window.front().GetSequenceNumber())
            {
                // If we have expired a message and caused the seqnos
                // to wrap, we resync the connection. This shouldn't
                // happen very often.
                // If we wrap, don't send kills
                m_sendkills = false;
                m_sendkill = 0;
                SendSYN();
            }
            if(m_sendkills)
            {
                // kill will be set to the last message accepted by receiver
                // (and whose ack has been received)
                ptree x;
                x.put("src.kill",m_sendkill);
                m_window.front().SetProtocolProperties(x);
            }
            Write(m_window.front());
            // Head of window can be killed.
            m_timeout.cancel();
            m_timeout.expires_from_now(boost::posix_time::milliseconds(REFIRE_TIME));
            m_timeout.async_wait(boost::bind(&CSRConnection::Resend,this,
                boost::asio::placeholders::error));
        }
    }
}
Example #5
0
///////////////////////////////////////////////////////////////////////////////
/// CConnection::Send
/// @description: Given a message and wether or not it should be sequenced,
///   write that message to the channel.
/// @pre: The CConnection object is initialized.
/// @post: If the window is in not full, the message will have been written to
///   to the channel. Before being sent the message has been signed with the
///   UUID, source hostname and sequence number (if it is being sequenced).
///   If the message is being sequenced  and the window is not already full,
///   the timeout timer is cancelled and reset.
/// @param p_mesg: A CMessage to write to the channel.
/// @param sequence: if true, the message will be sequenced and reliably
///   delievered in order. Otherwise it is immediately fired and forgotten.
///   this is mostly meant for use with ACKs. True by default.
///////////////////////////////////////////////////////////////////////////////
void CConnection::Send(CMessage p_mesg, bool sequence)
{
    Logger::Debug << __PRETTY_FUNCTION__ << std::endl;

    //Make a call to the dispatcher to sign the messages
    //With a bunch of shiny stuff.
    ptree x = static_cast<ptree>(p_mesg);
    unsigned int msgseq;

    //m_dispatch.HandleWrite(x);  

    CMessage outmsg(x);

    // Sign the message with the hostname, uuid, and squencenumber
    if(sequence == true)
    {
        if(m_synched == false)
        {
            m_synched = true;
            SendSYN();
        }
        msgseq = m_outsequenceno;
        outmsg.SetSequenceNumber(msgseq);
        m_outsequenceno = (m_outsequenceno+1) % GetSequenceModulo();
    }
    outmsg.SetSourceUUID(GetConnectionManager().GetUUID()); 
    outmsg.SetSourceHostname(GetConnectionManager().GetHostname());

    if(sequence == true)
    {
        // If it isn't squenced then don't put it in the queue.
        m_queue.Push( QueueItem(msgseq,outmsg) );
    }
    // Before, we would put it into a queue to be sent later, now we are going
    // to immediately write it to channel.

    if(m_queue.size() <= GetWindowSize() || sequence == false)
    {
        // Only try to write to the socket if the window isn't already full.
        // Or it is an unsequenced message
        
        HandleSend(outmsg);
        if(sequence == true)
        {
            m_timeout.cancel();
            m_timeout.expires_from_now(boost::posix_time::milliseconds(1000));
            m_timeout.async_wait(boost::bind(&CConnection::Resend,this,
                boost::asio::placeholders::error));
        }
    }
}
Example #6
0
bool
LX::CommandMode(Port &port, OperationEnvironment &env)
{
  /* switch to command mode, first attempt */

  if (!SendSYN(port) || !port.FullFlush(env, 50, 200))
    return false;

  /* the port is clean now; try the SYN/ACK procedure up to three
     times */
  for (unsigned i = 0; i < 100 && !env.IsCancelled(); ++i)
    if (Connect(port, env))
      /* make sure all remaining ACKs are flushed */
      return port.FullFlush(env, 200, 500);

  return false;
}
Example #7
0
///////////////////////////////////////////////////////////////////////////////
/// CSRConnection::Recieve
/// @description Accepts a message into the protocol, if that message should
///   be accepted. If this function returns true, the message is passed to
///   the dispatcher. Since this message accepts SYNs there might be times
///   when processing and state changes but the message is marked as "rejected"
///   this is normal.
/// @pre Accept logic can be complicated, there are several scenarios that
///      should be addressed.
///      1) A bad request has been recieved
///      2) A SYN message is recieved for the first time
///      3) A SYN message is recieved as a duplicate.
///      4) A Message has been recieved before the connection has been synced.
///      5) A Message has been recieved with the expected sequenceno with or
///         without a kill flag.
///      6) A message has been recieved with a kill flag. The kill is greater
///         than the expected sequence number
///      7) A message has been recieved with a kill flag. The kill is less than
///         the expected sequence number. However, the message's number is less
///         than the expected sequence number
///      8) A message has been received with a kill flag. The kill is less than
///         the expected sequence number and the message's sequence number is
///         greater than the expected sequence number.
/// @post Cases are handled as follows:
///      1) The connection is resynced.
///      2) The message is ACKed, the send time of the sync is noted, and the
///         connection is synced.
///      3) The SYN is ignored.
///      4) A bad request message is generated and sent to the source.
///      5) The message is accepted.
///      6) The message is rejected. Kills should only ever be less than the
///         expected sequence number unless the message is arrived out of order
///      7) The message is simply old but still arriving at the socket, and can
///         be rejected.
///      8) The message should be accepted because one or more message expired
///         in the gap of sequence numbers.
/// @return True if the message is accepted, false otherwise.
///////////////////////////////////////////////////////////////////////////////
bool CSRConnection::Recieve(const CMessage &msg)
{
    Logger.Debug << __PRETTY_FUNCTION__ << std::endl;
    unsigned int kill = 0;
    bool usekill = false; //If true, we should accept any inseq
    if(msg.GetStatus() == freedm::broker::CMessage::BadRequest)
    {
        //See if we are already trying to sync:
        if(m_window.front().GetStatus() != freedm::broker::CMessage::Created)
        {
            if(m_outsynctime != msg.GetSendTimestamp())
            {
                m_outsynctime = msg.GetSendTimestamp();
                SendSYN();
            }
            else
            {
                Logger.Notice<<"Already synced for this time"<<std::endl;
            }
        }
        return false;
    }
    if(msg.GetStatus() == freedm::broker::CMessage::Created)
    {
        //Check to see if we've already seen this SYN:
        if(msg.GetSendTimestamp() == m_insynctime)
        {
            return false;
            Logger.Notice<<"Duplicate Sync"<<std::endl;
        }
        Logger.Notice<<"Got Sync"<<std::endl;
        m_inseq = (msg.GetSequenceNumber()+1)%SEQUENCE_MODULO;
        m_insynctime = msg.GetSendTimestamp();
        m_inresyncs++;
        m_insync = true;
        SendACK(msg);
        return false;
    }
    if(m_insync == false)
    {
        Logger.Notice<<"Connection Needs Resync"<<std::endl;
        //If the connection hasn't been synchronized, we want to
        //tell them it is a bad request so they know they need to sync.
        freedm::broker::CMessage outmsg;
        // Presumably, if we are here, the connection is registered 
        outmsg.SetSourceUUID(GetConnection()->GetConnectionManager().GetUUID());
        outmsg.SetSourceHostname(GetConnection()->GetConnectionManager().GetHostname());
        outmsg.SetStatus(freedm::broker::CMessage::BadRequest);
        outmsg.SetSequenceNumber(m_inresyncs%SEQUENCE_MODULO);
        outmsg.SetSendTimestamp(msg.GetSendTimestamp());
        outmsg.SetProtocol(GetIdentifier());
        Write(outmsg);
        return false;
    }
    // See if the message contains kill data. If it does, read it and mark
    // we should use it. 
    try
    {
        ptree pp = msg.GetProtocolProperties();
        kill = pp.get<unsigned int>("src.kill");
        usekill = true;
    }
    catch(std::exception &e)
    {
        kill = msg.GetSequenceNumber();
        usekill = false;
    }
    //Consider the window you expect to see
    // If the killed message is the one immediately preceeding this
    // message in terms of sequence number we should accept it
    if(msg.GetSequenceNumber() == m_inseq)
    {
        //m_insync = true;
        m_inseq = (m_inseq+1)%SEQUENCE_MODULO;
        return true;
    }
    else if(usekill == true && kill< m_inseq
            && msg.GetSequenceNumber() > m_inseq)
    {
        //m_inseq will be right for the next expected message.
        m_inseq = (msg.GetSequenceNumber()+1)%SEQUENCE_MODULO;
        return true;
    }
    else if(usekill == true)
    {
        Logger.Notice<<"KILL: "<<kill<<" INSEQ "<<m_inseq<<" SEQ: "
                      <<msg.GetSequenceNumber()<<std::endl;
    }
    // Justin case.
    return false;
}
Example #8
0
 /**
  * Send SYN and wait for ACK.
  *
  * @return true on success
  */
 static inline bool
 Connect(Port &port, OperationEnvironment &env, unsigned timeout_ms=500)
 {
   return SendSYN(port) && ExpectACK(port, env, timeout_ms);
 }