More robust system

This commit is contained in:
Baptiste Wicht 2016-09-15 23:09:35 +02:00
parent 303ab91887
commit 9bb52223a3

View File

@ -16,9 +16,13 @@
#include "kernel_utils.hpp" #include "kernel_utils.hpp"
#include "circular_buffer.hpp" #include "circular_buffer.hpp"
#include "timer.hpp"
namespace { namespace {
static constexpr size_t timeout_ms = 1000;
static constexpr size_t max_tries = 5;
using flag_data_offset = std::bit_field<uint16_t, uint8_t, 12, 4>; using flag_data_offset = std::bit_field<uint16_t, uint8_t, 12, 4>;
using flag_reserved = std::bit_field<uint16_t, uint8_t, 9, 3>; using flag_reserved = std::bit_field<uint16_t, uint8_t, 9, 3>;
using flag_ns = std::bit_field<uint16_t, uint8_t, 8, 1>; using flag_ns = std::bit_field<uint16_t, uint8_t, 8, 1>;
@ -207,6 +211,11 @@ void network::tcp::finalize_packet(network::interface_descriptor& interface, net
// Compute the checksum // Compute the checksum
compute_checksum(p); compute_checksum(p);
if (!p.user) {
logging::logf(logging::log_level::ERROR, "tcp: Function uniquely implemented for user packets!\n");
return; //TODO Fail
}
auto source = socket.local_port; auto source = socket.local_port;
auto target = socket.server_port; auto target = socket.server_port;
@ -214,47 +223,75 @@ void network::tcp::finalize_packet(network::interface_descriptor& interface, net
if (!listener_ptr) { if (!listener_ptr) {
logging::logf(logging::log_level::ERROR, "tcp: Unable to find listener!\n"); logging::logf(logging::log_level::ERROR, "tcp: Unable to find listener!\n");
return; return; //TODO Fail
} }
auto& listener = *listener_ptr; auto& listener = *listener_ptr;
listener.active = true; listener.active = true;
// Give the packet to the IP layer for finalization uint32_t seq = 0;
network::ip::finalize_packet(interface, p); uint32_t ack = 0;
uint32_t seq; bool received = false;
uint32_t ack;
while (true) { for(size_t t = 0; t < max_tries; ++t){
// TODO Need a timeout // Give the packet to the IP layer for finalization
listener.queue.sleep(); network::ip::finalize_packet(interface, p);
auto received_packet = listener.packets.pop();
auto* tcp_header = reinterpret_cast<header*>(received_packet.payload + received_packet.index); auto before = timer::milliseconds();
auto flags = switch_endian_16(tcp_header->flags); auto after = before;
logging::logf(logging::log_level::TRACE, "tcp: Received answer\n"); while(true){
// Make sure we don't wait for more than the timeout
if (after > before + timeout_ms) {
break;
}
if (*flag_ack(&flags)) { auto remaining = timeout_ms - (after - before);
logging::logf(logging::log_level::TRACE, "tcp: Received ACK\n");
seq = switch_endian_32(tcp_header->sequence_number); if(listener.queue.sleep(remaining)){
ack = switch_endian_32(tcp_header->ack_number); auto received_packet = listener.packets.pop();
delete[] received_packet.payload; auto* tcp_header = reinterpret_cast<header*>(received_packet.payload + received_packet.index);
auto flags = switch_endian_16(tcp_header->flags);
if (*flag_ack(&flags)) {
logging::logf(logging::log_level::TRACE, "tcp: Received ACK\n");
seq = switch_endian_32(tcp_header->sequence_number);
ack = switch_endian_32(tcp_header->ack_number);
delete[] received_packet.payload;
received = true;
break;
} else {
logging::logf(logging::log_level::TRACE, "tcp: Received unrelated answer\n");
}
delete[] received_packet.payload;
}
}
if(received){
break; break;
} }
delete[] received_packet.payload; after = timer::milliseconds();
} }
// Stop listening
listener.active = false; listener.active = false;
socket.seq_number = ack; if(received){
socket.ack_number = seq; // Set the future sequence and acknowledgement numbers
socket.seq_number = ack;
socket.ack_number = seq;
} else {
//TODO We need to be able to make finalize fail!
}
} }
std::expected<void> network::tcp::connect(network::socket& sock, network::interface_descriptor& interface) { std::expected<void> network::tcp::connect(network::socket& sock, network::interface_descriptor& interface) {