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