Ejemplo n.º 1
0
size_t Connection::fill_packet(Packet_ptr packet, const char* buffer, size_t n, Seq seq) {
  Expects(!packet->has_tcp_data());

  auto written = packet->fill(buffer, std::min(n, (size_t)SMSS()));

  packet->set_seq(seq).set_ack(cb.RCV.NXT).set_flag(ACK);

  Ensures(written <= n);

  return written;
}
Ejemplo 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");
}