예제 #1
0
void Listener::segment_arrived(Packet_ptr packet) {
  debug2("<Listener::segment_arrived> Received packet: %s\n",
    packet->to_string().c_str());
  // if it's an reply to any of our half-open connections
  if(!packet->isset(SYN))
  {
    // if there is a connection waiting for the packet
    for(auto conn : syn_queue_) // take a copy to avoid conn->segment_arrived to make a reference invalid
    {
      if(conn->remote() == packet->source())
      {
        debug("<Listener::segment_arrived> Found packet receiver: %s\n",
          conn->to_string().c_str());
        conn->segment_arrived(packet);
        debug2("<Listener::segment_arrived> Connection done handling segment\n");
        return;
      }
    }
  }
  // if it's a new attempt (SYN)
  else
  {
    // Stat increment number of connection attempts
    host_.connection_attempts_++;

    // if we don't like this client, do nothing
    if(! on_accept_(packet->source()) )
      return;

    // remove oldest connection if queue is full
    debug2("<Listener::segment_arrived> SynQueue: %u\n", syn_queue_.size());
    if(syn_queue_full())
    {
      debug2("<Listener::segment_arrived> Queue is full\n");
      Expects(not syn_queue_.empty());
      debug("<Listener::segment_arrived> Connection %s dropped to make room for new connection\n",
        syn_queue_.back()->to_string().c_str());

      syn_queue_.pop_back();
    }

    auto& conn = *(syn_queue_.emplace(syn_queue_.begin(),
      std::make_shared<Connection>( host_, port_, packet->source() )));
    // Call Listener::connected when Connection is connected
    conn->on_connect(ConnectCallback::from<Listener, &Listener::connected>(this));
    conn->_on_cleanup(CleanupCallback::from<Listener, &Listener::remove>(this));
    // Open connection
    conn->open(false);
    Ensures(conn->is_listening());
    debug("<Listener::segment_arrived> Connection %s created\n",
      conn->to_string().c_str());
    conn->segment_arrived(packet);
    debug2("<Listener::segment_arrived> Connection done handling segment\n");
    return;
  }
  debug2("<Listener::segment_arrived> No receipent\n");
}
예제 #2
0
void Listener::segment_arrived(Packet_ptr packet) {
  debug2("<Listener::segment_arrived> Received packet: %s\n",
    packet->to_string().c_str());

  auto it = std::find_if(syn_queue_.begin(), syn_queue_.end(),
    [dest = packet->source()]
    (Connection_ptr conn) {
      return conn->remote() == dest;
    });

  // if it's an reply to any of our half-open connections
  if(it != syn_queue_.end())
  {
    auto conn = *it;
    debug("<Listener::segment_arrived> Found packet receiver: %s\n",
      conn->to_string().c_str());
    conn->segment_arrived(std::move(packet));
    debug2("<Listener::segment_arrived> Connection done handling segment\n");
    return;
  }
  // if it's a new attempt (SYN)
  else
  {
    // don't waste time if the packet does not have SYN
    if(UNLIKELY(not packet->isset(SYN) or packet->has_tcp_data()))
    {
      host_.send_reset(*packet);
      return;
    }

    // Stat increment number of connection attempts
    host_.connection_attempts_++;

    // if we don't like this client, do nothing
    if(UNLIKELY(on_accept_(packet->source()) == false))
      return;

    // remove oldest connection if queue is full
    debug2("<Listener::segment_arrived> SynQueue: %u\n", syn_queue_.size());
    // SYN queue is full
    if(syn_queue_.size() >= host_.max_syn_backlog())
    {
      debug2("<Listener::segment_arrived> Queue is full\n");
      Expects(not syn_queue_.empty());
      debug("<Listener::segment_arrived> Connection %s dropped to make room for new connection\n",
        syn_queue_.back()->to_string().c_str());

      syn_queue_.pop_back();
    }

    auto& conn = *(syn_queue_.emplace(
      syn_queue_.cbegin(),
      std::make_shared<Connection>(host_, packet->destination(), packet->source(), ConnectCallback{this, &Listener::connected})
      )
    );
    conn->_on_cleanup({this, &Listener::remove});
    // Open connection
    conn->open(false);
    Ensures(conn->is_listening());
    debug("<Listener::segment_arrived> Connection %s created\n",
      conn->to_string().c_str());
    conn->segment_arrived(std::move(packet));
    debug2("<Listener::segment_arrived> Connection done handling segment\n");
    return;
  }
  debug2("<Listener::segment_arrived> No receipent\n");
}