Max OS 0.3
Loading...
Searching...
No Matches
tcp.cpp
Go to the documentation of this file.
1
9#include <net/tcp.h>
10#include "net/udp.h"
11
12
13using namespace MaxOS;
14using namespace MaxOS::net;
15using namespace MaxOS::common;
16using namespace MaxOS::memory;
17
19
21
22TCPPayloadHandler::~TCPPayloadHandler() = default;
23
34
43
52
60
61 switch(event->type) {
62 case TCPPayloadHandlerEvents::CONNECTED:
63 connected(((ConnectedEvent*) event)->socket);
64 break;
65 case TCPPayloadHandlerEvents::DISCONNECTED:
67 break;
68 case TCPPayloadHandlerEvents::DATA_RECEIVED:
70 ((DataReceivedEvent*) event)->data,
71 ((DataReceivedEvent*) event)->size);
72 break;
73 }
74
75 return event;
76}
77
83TCPSocket::TCPSocket(TransmissionControlProtocolHandler* transmission_control_protocol_handler) {
84 //Set the default values
85 this->transmission_control_protocol_handler = transmission_control_protocol_handler;
86
87 //Closed as default
88 state = TCPSocketState::CLOSED;
89}
90
91TCPSocket::~TCPSocket() = default;
92
101 auto* event = new DataReceivedEvent(this, data, size);
104 return true;
105}
106
114 //Wait for the socket to be connected
115 while(state != TCPSocketState::ESTABLISHED);
116
117 //Pass the data to the backend
119 (uint16_t) TCPFlag::PSH |
120 (uint16_t) TCPFlag::ACK);
121}
122
129
134 auto* event = new DisconnectedEvent(this);
137
138}
139
144 auto* event = new ConnectedEvent(this);
147
148}
149
151
153
161 : IPV4PayloadHandler(internet_protocol_handler, 0x06) {
162 this->error_messages = error_messages;
163
164}
165
166TransmissionControlProtocolHandler::~TransmissionControlProtocolHandler() = default;
167
175 return ((x & 0xFF000000) >> 24)
176 | ((x & 0x00FF0000) >> 8)
177 | ((x & 0x0000FF00) << 8)
178 | ((x & 0x000000FF) << 24);
179}
180
188 return ((x & 0xFF00) >> 8)
189 | ((x & 0x00FF) << 8);
190}
191
202
203 error_messages->write("TCP: Handling TCP message\n");
204
205 //Check if the size is too small
206 if(size < 13) {
207 return false;
208 }
209
210 // If it's smaller than the header, return
211 if(size < 4 * payload_data[12] / 16) // The lower 4 bits of the 13th byte is the header length
212 {
213 return false;
214 }
215
216 //Get the header
217 auto* msg = (TCPHeader*) payload_data;
218
219 //Get the connection values (convert to host endian)
220 uint16_t local_port = big_endian_16(msg->dst_port);
221 uint16_t remote_port = big_endian_16(msg->src_port);
222
223 //Create the socket
224 TCPSocket* socket = nullptr;
225
226 for(auto& current_socket : sockets) {
227 if(current_socket->local_port ==
228 local_port //Check if the local port is the same as the destination port
229 && current_socket->local_ip ==
230 destination_ip //Check if the local IP is the same as the destination IP
231 && current_socket->state ==
232 TCPSocketState::LISTEN //Check if the socket is in the LISTEN state
233 && (((msg->flags) & ((uint16_t) TCPFlag::SYN | (uint16_t) TCPFlag::ACK)) ==
234 (uint16_t) TCPFlag::SYN)) //Check if the SYN flag is set (allow for acknoweldgement)
235 {
236 socket = current_socket;
237 } else if(current_socket->local_port ==
238 local_port //Check if the local port is the same as the destination port
239 && current_socket->local_ip ==
240 destination_ip //Check if the local IP is the same as the destination IP
241 && current_socket->remotePort ==
242 remote_port //Check if the remote port is the same as the source port
243 && current_socket->remote_ip ==
244 destination_ip) //Check if the remote IP is the same as the source IP
245 {
246 socket = current_socket;
247 }
248 }
249
250
251 bool reset = false;
252
253 //Check if the socket is found and if the socket wants to reset
254 if(socket != nullptr && msg->flags & (uint16_t) TCPFlag::RST) {
255 socket->state = TCPSocketState::CLOSED;
256 socket->disconnected();
257 }
258
259 //Check if the socket is found and if the socket is not closed
260 if(socket != nullptr && socket->state != TCPSocketState::CLOSED) {
261 switch((msg->flags) & ((uint16_t) TCPFlag::SYN | (uint16_t) TCPFlag::ACK | (uint16_t) TCPFlag::FIN)) {
262 /*
263 * Example for explanation:
264 * socket -> state = SYN_RECEIVED; //The state of the socket, e.g. recieved, or established. This is used to know how to handle the socket
265 * socket -> remotePort = msg -> srcPort; //The remote port, e.g. the port of the server
266 * socket -> remoteIP = srcIP_BE; //The remote IP, e.g. the IP of the server
267 * socket -> acknowledgementNumber = bigEndian32( msg -> sequenceNumber ) + 1; //The acknowledgement number, the number used to keep track of what has been received, this is just incremented by 1 each time
268 * socket -> sequenceNumber = 0xbeefcafe; //The sequence number, the number of the next set that is to be sent but in this case sequence isn't enabled so just set it to anything
269 * Send(socket, 0,0, SYN|ACK); //The response command, genneraly has to have the acknoledgement flag set
270 * socket -> sequenceNumber++; //Increment the sequence number
271 *
272 */
273
274 case (uint16_t) TCPFlag::SYN:
275 if(socket->state == TCPSocketState::LISTEN) {
276 socket->state = TCPSocketState::SYN_RECEIVED;
277 socket->remotePort = msg->src_port;
278 socket->remote_ip = source_ip;
279 socket->acknowledgement_number = big_endian_32(msg->sequence_number) + 1;
280 socket->sequence_number = 0xbeefcafe;
282 (uint16_t) TCPFlag::SYN | (uint16_t) TCPFlag::ACK);
283 socket->sequence_number++;
284 } else
285 reset = true;
286 break;
287
288
289 case (uint16_t) TCPFlag::SYN | (uint16_t) TCPFlag::ACK:
290 if(socket->state == TCPSocketState::SYN_SENT) {
291 socket->state = TCPSocketState::ESTABLISHED;
292 socket->acknowledgement_number = big_endian_32(msg->sequence_number) + 1;
293 socket->sequence_number++;
294 send_transmission_control_protocol_packet(socket, nullptr, 0, (uint16_t) TCPFlag::ACK);
295 } else
296 reset = true;
297 break;
298
299
300 case (uint16_t) TCPFlag::SYN | (uint16_t) TCPFlag::FIN:
301 case (uint16_t) TCPFlag::SYN | (uint16_t) TCPFlag::FIN | (uint16_t) TCPFlag::ACK:
302 reset = true;
303 break;
304
305
306 case (uint16_t) TCPFlag::FIN:
307 case (uint16_t) TCPFlag::FIN | (uint16_t) TCPFlag::ACK:
308 if(socket->state == TCPSocketState::ESTABLISHED) {
309 socket->state = TCPSocketState::CLOSE_WAIT;
310 socket->acknowledgement_number++;
311 send_transmission_control_protocol_packet(socket, nullptr, 0, (uint16_t) TCPFlag::ACK);
313 (uint16_t) TCPFlag::FIN | (uint16_t) TCPFlag::ACK);
314 socket->disconnected();
315 } else if(socket->state == TCPSocketState::CLOSE_WAIT) {
316 socket->state = TCPSocketState::CLOSED;
317 } else if(socket->state == TCPSocketState::FIN_WAIT1 || socket->state == TCPSocketState::FIN_WAIT2) {
318 socket->state = TCPSocketState::CLOSED;
319 socket->acknowledgement_number++;
320 send_transmission_control_protocol_packet(socket, nullptr, 0, (uint16_t) TCPFlag::ACK);
321 socket->disconnected();
322 } else
323 reset = true;
324 break;
325
326
327 case (uint16_t) TCPFlag::ACK:
328 if(socket->state == TCPSocketState::SYN_RECEIVED) {
329 socket->state = TCPSocketState::ESTABLISHED;
330 socket->connected();
331 return false;
332 } else if(socket->state == TCPSocketState::FIN_WAIT1) {
333 socket->state = TCPSocketState::FIN_WAIT2;
334 return false;
335 } else if(socket->state == TCPSocketState::CLOSE_WAIT) {
336 socket->state = TCPSocketState::CLOSED;
337 break;
338 }
339
340 if(msg->flags == (uint16_t) TCPFlag::ACK)
341 break;
342
343 // no break, because of piggybacking
344 [[fallthrough]];
345
346 default:
347
348 // By default, handle the data
349
350 if(big_endian_32(msg->sequence_number) == socket->acknowledgement_number) {
351
353 payload_data + msg->header_size_32 * 4,
354 size - msg->header_size_32 * 4));
355 if(!reset) {
356 uint32_t x = 0; //The number of bytes to send back
357 for(uint32_t i = msg->header_size_32 * 4;
358 i < size; i++) //Loop through the data
359 if(payload_data[i] !=
360 0) //Check if the data is not 0
361 x = i; //Set the number of bytes to send back to the current index
362 socket->acknowledgement_number += x - msg->header_size_32 * 4 +
363 1; //Increment the acknowledgement number by the number of bytes to send back
365 (uint16_t) TCPFlag::ACK); //Send the acknowledgement
366 }
367 } else {
368 // data in wrong order
369 reset = true;
370 }
371
372 }
373 }
374
375
376 if(reset) //If the socket is to be reset
377 {
378 if(socket !=
379 nullptr) //If the socket exists then send a reset flag
380 {
381 send_transmission_control_protocol_packet(socket, nullptr, 0, (uint16_t) TCPFlag::RST);
382 } else //If it doesn't exist then create a new socket and send a reset flag
383 {
384 TCPSocket new_socket(this); //Create a new socket
385 new_socket.remotePort = msg->src_port; //Set the remote port
386 new_socket.remote_ip = source_ip; //Set the remote IP
387 new_socket.local_port = msg->dst_port; //Set the local port
388 new_socket.local_ip = destination_ip; //Set the local IP
389 new_socket.sequence_number = big_endian_32(
390 msg->acknowledgement_number); //Set the sequence number
391 new_socket.acknowledgement_number =
392 big_endian_32(msg->sequence_number) + 1; //Set the acknowledgement number
394 (uint16_t) TCPFlag::RST); //Send the reset flag
395 }
396 }
397
398
399 error_messages->write("TCP: Handled packet\n");
400
401 if(socket != nullptr && socket->state ==
402 TCPSocketState::CLOSED) //If the socket is closed then remove it from the list
403 {
404 sockets.erase(socket);
405 return true;
406 }
407
408
409 return false;
410}
411
421 //Get the total size of the packet and the packet with the pseudo header
422 uint16_t total_length = size + sizeof(TCPHeader);
423 uint16_t length_incl_p_hdr = total_length + sizeof(TCPPseudoHeader);
424
425 //Create a buffer for the packet
428 buffer + sizeof(TCPHeader) + sizeof(TCPPseudoHeader);
429
430 //Create the headers
431 auto* phdr = (TCPPseudoHeader*) buffer;
432 auto* msg = (TCPHeader*) (buffer + sizeof(TCPPseudoHeader));
433
434 //Size is translated into 32bit
435 msg->header_size_32 = sizeof(TCPHeader) / 4;
436
437 //Set the ports
438 msg->src_port = big_endian_16(socket->local_port);
439 msg->dst_port = big_endian_16(socket->remotePort);
440
441 //Set TCP related data
442 msg->acknowledgement_number = big_endian_32(socket->acknowledgement_number);
443 msg->sequence_number = big_endian_32(socket->sequence_number);
444 msg->reserved = 0;
445 msg->flags = flags;
446 msg->window_size = 0xFFFF;
447 msg->urgent_ptr = 0;
448
449 //Through the options allow for the MSS to be set
450 msg->options = ((flags & (uint16_t) TCPFlag::SYN) != 0) ? 0xB4050402 : 0;
451
452 //Increase the sequence number
453 socket->sequence_number += size;
454
455 // Check if the data is not null
456 if(data != nullptr) {
457 //Copy the data into the buffer
458 for(int i = 0; i < size; i++)
459 buffer2[i] = data[i];
460 }
461
462 //Set the pseudo header
463 phdr->src_ip = socket->local_ip;
464 phdr->dst_ip = socket->remote_ip;
465 phdr->protocol = 0x0600;
466 phdr->total_length = ((total_length & 0x00FF) << 8) | ((total_length & 0xFF00) >> 8);
467
468 //Calculate the checksum
469 msg->checksum = 0;
471
472
473 //Send and then free the data
474 send(socket->remote_ip, (uint8_t*) msg, total_length);
475 MemoryManager::kfree(buffer);
476}
477
485 //Create a new socket
486 auto* socket = (TCPSocket*) MemoryManager::kmalloc(
487 sizeof(TCPSocket));
488
489 //If there is space for the socket
490 if(socket != nullptr) {
491 //Set the socket
492 new(socket) TCPSocket(this);
493
494 //Set local and remote addresses
495 socket->remotePort = port;
496 socket->remote_ip = ip;
497 socket->local_port = free_ports++;
499
500 //Convert into big endian
501 socket->remotePort = ((socket->remotePort & 0xFF00) >> 8) | ((socket->remotePort & 0x00FF) << 8);
502 socket->local_port = ((socket->local_port & 0xFF00) >> 8) | ((socket->local_port & 0x00FF) << 8);
503
504 //Set the socket into the socket array and then set its state
505 sockets.push_back(socket);
506 socket->state = TCPSocketState::SYN_SENT;
507
508 //Dummy sequence number
509 socket->sequence_number = 0xbeefcafe;
510
511 //Send a sync packet
512 send_transmission_control_protocol_packet(socket, nullptr, 0, (uint16_t) TCPFlag::SYN);
513 }
514
515 return socket;
516}
517
528
529 return nullptr;
530}
531
538
539 socket->state = TCPSocketState::FIN_WAIT1; //Begin fin wait sequence
540 send_transmission_control_protocol_packet(socket, nullptr, 0, (uint16_t) TCPFlag::FIN +
541 (uint16_t) TCPFlag::ACK); //Send FIN|ACK packet
542 socket->sequence_number++; //Increase the sequence number
543}
544
552 //Create a new socket
553 auto* socket = (TCPSocket*) MemoryManager::kmalloc(
554 sizeof(TCPSocket));
555
556 //If there is space for the socket
557 if(socket != nullptr) {
558 //Set the socket
559 new(socket) TCPSocket(this);
560
561 //Configure the socket
562 socket->state = TCPSocketState::LISTEN;
564 socket->local_port = ((port & 0xFF00) >> 8) | ((port & 0x00FF) << 8);
565
566 //Add the socket to the socket array
567 sockets.push_back(socket);
568 }
569
570 //Return the socket
571 return socket;
572}
573
574
584
585
595 : Event(TCPPayloadHandlerEvents::DATA_RECEIVED) {
596 this->socket = socket;
597 this->data = data;
598 this->size = size;
599}
600
601DataReceivedEvent::~DataReceivedEvent() = default;
602
609 : Event(TCPPayloadHandlerEvents::CONNECTED) {
610 this->socket = socket;
611}
612
613ConnectedEvent::~ConnectedEvent() = default;
614
621 : Event(TCPPayloadHandlerEvents::DISCONNECTED) {
622 this->socket = socket;
623}
624
625DisconnectedEvent::~DisconnectedEvent() = default;
Vector< Event< TCPPayloadHandlerEvents > * > raise_event(Event< TCPPayloadHandlerEvents > *event)
Calls the on_event function of all the event m_handlers connected to the event manager and returns a ...
void connect_event_handler(EventHandler< EventType > *handler)
connect an event handler to the event manager if it is not already connected
Used to store information about an event, has a type and a return value.
A stream that strings can be written to.
void write(string string_to_write) override
Writes a string to the output stream.
Stores the left, top, width and height of a rectangle.
Definition rectangle.h:22
static void * kmalloc(size_t size)
Allocates a block of memory in the KERNEL space.
static void kfree(void *pointer)
Frees a block of memory using the kernel memory manager.
Event for when a TCP socket is connected.
Definition tcp.h:136
TCPSocket * socket
The socket that is connected.
Definition tcp.h:138
ConnectedEvent(TCPSocket *socket)
Construct a new connected Event object.
Definition tcp.cpp:608
Event for when data is received on a TCP socket.
Definition tcp.h:123
uint16_t size
The size of the data received.
Definition tcp.h:127
TCPSocket * socket
The socket that received the data.
Definition tcp.h:125
DataReceivedEvent(TCPSocket *socket, uint8_t *data, uint16_t size)
Construct a new Data Received Event object.
Definition tcp.cpp:594
uint8_t * data
The data received.
Definition tcp.h:126
Event for when a TCP socket is disconnected.
Definition tcp.h:147
TCPSocket * socket
The socket that is disconnected.
Definition tcp.h:149
DisconnectedEvent(TCPSocket *socket)
Construct a new disconnected Event object.
Definition tcp.cpp:620
Handles the payload of a specific IP protocol.
Definition ipv4.h:66
void send(InternetProtocolAddress destination_ip, uint8_t *payload_data, uint32_t size)
Sends an IP packet.
Definition ipv4.cpp:93
InternetProtocolHandler * internet_protocol_handler
The Internet protocol handler this payload handler is connected to.
Definition ipv4.h:70
Handles IPv4 packets over Ethernet frames.
Definition ipv4.h:85
InternetProtocolAddress get_internet_protocol_address() const
Gets the IP address of this device.
Definition ipv4.cpp:345
static uint16_t checksum(const uint16_t *data, uint32_t length_in_bytes)
Creates a checksum for the given data.
Definition ipv4.cpp:249
Handler for TCP payloads.
Definition tcp.h:158
virtual void disconnected(TCPSocket *socket)
Handle a TCP disconnection on the socket.
Definition tcp.cpp:49
virtual void connected(TCPSocket *socket)
Handle a new TCP connection on the socket.
Definition tcp.cpp:40
common::Event< TCPPayloadHandlerEvents > * on_event(common::Event< TCPPayloadHandlerEvents > *event) override
Handle an event occurring on the TCP payload handler.
Definition tcp.cpp:59
virtual void handle_transmission_control_protocol_payload(TCPSocket *socket, uint8_t *data, uint16_t size)
Handle TCP data received on the socket.
Definition tcp.cpp:31
A TCP socket. Allows for sending and receiving data over TCP at a port.
Definition tcp.h:174
TCPSocket(TransmissionControlProtocolHandler *transmission_control_protocol_handler)
Construct a new TCP Socket object.
Definition tcp.cpp:83
uint32_t acknowledgement_number
The number used to keep track of what has been received, incremented by 1 each time.
Definition tcp.h:185
virtual void send(uint8_t *data, uint16_t size)
send data over the socket
Definition tcp.cpp:113
TransmissionControlProtocolHandler * transmission_control_protocol_handler
The TCP handler this socket is using.
Definition tcp.h:187
uint16_t local_port
The port on this device.
Definition tcp.h:182
void disconnected()
Raise the disconnected event.
Definition tcp.cpp:133
uint32_t local_ip
The IP address of this device.
Definition tcp.h:183
virtual void disconnect()
disconnect the socket
Definition tcp.cpp:126
bool handle_transmission_control_protocol_payload(uint8_t *data, uint16_t size)
Handle the TCP message (socket end)
Definition tcp.cpp:100
void connected()
Raise the connected event.
Definition tcp.cpp:143
uint16_t remotePort
The port on the external device.
Definition tcp.h:180
uint32_t sequence_number
The current order number of the data being sent.
Definition tcp.h:184
TCPSocketState state
The state of the socket.
Definition tcp.h:188
uint32_t remote_ip
The IP address of the external device.
Definition tcp.h:181
Handles TCP packets and manages TCP sockets.
Definition tcp.h:206
void disconnect(TCPSocket *socket)
Begin the disconnect process.
Definition tcp.cpp:537
common::OutputStream * error_messages
Where to write error messages.
Definition tcp.h:210
static TransmissionControlProtocolPort free_ports
The next free port to use for new sockets.
Definition tcp.h:213
TCPSocket * connect(InternetProtocolAddress ip, TransmissionControlProtocolPort port)
connect to a remote host through the TCP protocol
Definition tcp.cpp:484
TransmissionControlProtocolHandler(InternetProtocolHandler *internet_protocol_handler, common::OutputStream *error_messages)
Construct a new Transmission Control Protocol Handler object.
Definition tcp.cpp:160
void send_transmission_control_protocol_packet(TCPSocket *socket, const uint8_t *data, uint16_t size, uint16_t flags=0)
send a packet (Throught the provider)
Definition tcp.cpp:420
bool handle_internet_protocol_payload(net::InternetProtocolAddress source_ip, net::InternetProtocolAddress destination_ip, uint8_t *payload_data, uint32_t size) override
Handle the TCP message (provider end)
Definition tcp.cpp:201
common::Vector< TCPSocket * > sockets
The list of connected sockets.
Definition tcp.h:211
virtual void bind(TCPSocket *socket, TCPPayloadHandler *handler)
bind a data handler to this socket
Definition tcp.cpp:581
virtual TCPSocket * listen(uint16_t port)
Begin listening on a port.
Definition tcp.cpp:551
uint32_t InternetProtocolAddress
An IPv4 address.
Definition ipv4.h:18
The header of a TCP packet.
Definition tcp.h:65
The pseudo header used for TCP checksum calculation.
Definition tcp.h:94
uint32_t big_endian_32(uint32_t x)
Convert a 32-bit integer to big-endian format.
Definition tcp.cpp:174
uint32_t big_endian_16(uint16_t x)
Convert a 16-bit integer to big-endian format.
Definition tcp.cpp:187
Defines the Transmission Control Protocol (TCP) structures and classes for handling TCP sockets and p...
TCPPayloadHandlerEvents
Events for the TCPPayloadHandler.
Definition tcp.h:113
uint16_t TransmissionControlProtocolPort
TCP port.
Definition tcp.h:19
Defines the User Datagram Protocol (UDP) for network communication.