void Connection::segment_arrived(TCP::Packet_ptr incoming) { signal_packet_received(incoming); if(incoming->has_options()) { try { parse_options(incoming); } catch(TCPBadOptionException err) { debug("<TCP::Connection::receive> %s \n", err.what()); } } // Let state handle what to do when incoming packet arrives, and modify the outgoing packet. switch(state_->handle(*this, incoming)) { case State::OK: { // Do nothing. break; } case State::CLOSED: { debug("<TCP::Connection::receive> (%s => %s) State handle finished with CLOSED. We're done, ask host() to delete the connection.\n", prev_state_->to_string().c_str(), state_->to_string().c_str()); writeq_reset(); signal_close(); break; }; case State::CLOSE: { debug("<TCP::Connection::receive> State handle finished with CLOSE. onDisconnect has been called, close the connection. \n"); state_->close(*this); break; }; } }
void Connection::parse_options(TCP::Packet_ptr packet) { assert(packet->has_options()); debug("<TCP::parse_options> Parsing options. Offset: %u, Options: %u \n", packet->offset(), packet->options_length()); auto* opt = packet->options(); while((char*)opt < packet->data()) { auto* option = (TCP::Option*)opt; switch(option->kind) { case Option::END: { return; } case Option::NOP: { opt++; break; } case Option::MSS: { // unlikely if(option->length != 4) throw TCPBadOptionException{Option::MSS, "length != 4"}; // unlikely if(!packet->isset(SYN)) throw TCPBadOptionException{Option::MSS, "Non-SYN packet"}; auto* opt_mss = (Option::opt_mss*)option; uint16_t mss = ntohs(opt_mss->mss); cb.SND.MSS = mss; debug2("<TCP::parse_options@Option:MSS> MSS: %u \n", mss); opt += option->length; break; } default: return; } } }