Max OS 0.3
Loading...
Searching...
No Matches
MaxOS::net::TransmissionControlProtocolHandler Class Reference

Handles TCP packets and manages TCP sockets. More...

#include <tcp.h>

Inheritance diagram for MaxOS::net::TransmissionControlProtocolHandler:
MaxOS::net::IPV4PayloadHandler

Public Member Functions

 TransmissionControlProtocolHandler (InternetProtocolHandler *internet_protocol_handler, common::OutputStream *error_messages)
 Construct a new Transmission Control Protocol Handler object.
 
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)
 
TCPSocketconnect (InternetProtocolAddress ip, TransmissionControlProtocolPort port)
 connect to a remote host through the TCP protocol
 
void disconnect (TCPSocket *socket)
 Begin the disconnect process.
 
virtual TCPSocketlisten (uint16_t port)
 Begin listening on a port.
 
virtual void bind (TCPSocket *socket, TCPPayloadHandler *handler)
 bind a data handler to this socket
 

Static Public Member Functions

static TCPSocketconnect (const string &address)
 connect to a remote host through the TCP protocol
 

Protected Member Functions

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)
 

Protected Attributes

common::OutputStreamerror_messages
 Where to write error messages.
 
common::Vector< TCPSocket * > sockets
 The list of connected sockets.
 

Static Protected Attributes

static TransmissionControlProtocolPort free_ports = 0x8000
 The next free port to use for new sockets.
 

Friends

class TCPSocket
 

Detailed Description

Handles TCP packets and manages TCP sockets.

Definition at line 206 of file tcp.h.

Constructor & Destructor Documentation

◆ TransmissionControlProtocolHandler()

TransmissionControlProtocolHandler::TransmissionControlProtocolHandler ( InternetProtocolHandler internet_protocol_handler,
common::OutputStream error_messages 
)

Construct a new Transmission Control Protocol Handler object.

Parameters
internet_protocol_handlerThe Internet protocol handler
error_messagesWhere to write error messages

Definition at line 160 of file tcp.cpp.

163
164}
Handles the payload of a specific IP protocol.
Definition ipv4.h:66
InternetProtocolHandler * internet_protocol_handler
The Internet protocol handler this payload handler is connected to.
Definition ipv4.h:70
common::OutputStream * error_messages
Where to write error messages.
Definition tcp.h:210

References error_messages.

Member Function Documentation

◆ bind()

void TransmissionControlProtocolHandler::bind ( TCPSocket socket,
TCPPayloadHandler handler 
)
virtual

bind a data handler to this socket

Parameters
socketThe socket to bind the handler to
handlerThe handler to bind

Definition at line 581 of file tcp.cpp.

581 {
583}
void connect_event_handler(EventHandler< EventType > *handler)
connect an event handler to the event manager if it is not already connected
Stores the left, top, width and height of a rectangle.
Definition rectangle.h:22

References MaxOS::common::EventManager< EventType >::connect_event_handler().

◆ connect() [1/2]

TCPSocket * TransmissionControlProtocolHandler::connect ( const string address)
static

connect to a remote host through the TCP protocol

Parameters
addressThe address to connect to in the form "IP:PORT"
Returns
The socket that is connected to the remote host, nullptr if it failed
Todo:
Implement string parsing for address

Definition at line 527 of file tcp.cpp.

527 {
528
529 return nullptr;
530}

◆ connect() [2/2]

TCPSocket * TransmissionControlProtocolHandler::connect ( InternetProtocolAddress  ip,
TransmissionControlProtocolPort  port 
)

connect to a remote host through the TCP protocol

Parameters
ipThe IP of the remote host
portThe port of the remote host
Returns
The socket that is connected to the remote host, 0 if it failed

Definition at line 484 of file tcp.cpp.

484 {
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}
static void * kmalloc(size_t size)
Allocates a block of memory in the KERNEL space.
InternetProtocolAddress get_internet_protocol_address() const
Gets the IP address of this device.
Definition ipv4.cpp:345
A TCP socket. Allows for sending and receiving data over TCP at a port.
Definition tcp.h:174
uint16_t remotePort
The port on the external device.
Definition tcp.h:180
static TransmissionControlProtocolPort free_ports
The next free port to use for new sockets.
Definition tcp.h:213
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
common::Vector< TCPSocket * > sockets
The list of connected sockets.
Definition tcp.h:211

References free_ports, MaxOS::net::InternetProtocolHandler::get_internet_protocol_address(), MaxOS::net::IPV4PayloadHandler::internet_protocol_handler, MaxOS::memory::MemoryManager::kmalloc(), MaxOS::net::TCPSocket::remotePort, send_transmission_control_protocol_packet(), and sockets.

◆ disconnect()

void TransmissionControlProtocolHandler::disconnect ( TCPSocket socket)

Begin the disconnect process.

Parameters
socketThe socket to disconnect

Definition at line 537 of file tcp.cpp.

537 {
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}
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

References send_transmission_control_protocol_packet(), MaxOS::net::TCPSocket::sequence_number, and MaxOS::net::TCPSocket::state.

Referenced by MaxOS::net::TCPSocket::disconnect().

◆ handle_internet_protocol_payload()

bool TransmissionControlProtocolHandler::handle_internet_protocol_payload ( net::InternetProtocolAddress  source_ip,
net::InternetProtocolAddress  destination_ip,
uint8_t payload_data,
uint32_t  size 
)
overridevirtual

Handle the TCP message (provider end)

Parameters
source_ipThe source IP address
destination_ipThe destination IP address
payload_dataThe payload
sizeThe size of the payload
Returns
True if data is to be sent back or false if not

Reimplemented from MaxOS::net::IPV4PayloadHandler.

Definition at line 201 of file tcp.cpp.

201 {
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}
void write(string string_to_write) override
Writes a string to the output stream.
uint32_t acknowledgement_number
The number used to keep track of what has been received, incremented by 1 each time.
Definition tcp.h:185
void disconnected()
Raise the disconnected event.
Definition tcp.cpp:133
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
uint32_t remote_ip
The IP address of the external device.
Definition tcp.h:181
The header of a TCP packet.
Definition tcp.h:65
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
TCPFlag
The flags in a TCP header.
Definition tcp.h:46
TCPSocketState
The state of a TCP socket.
Definition tcp.h:25

References MaxOS::net::TCPSocket::acknowledgement_number, big_endian_16(), big_endian_32(), MaxOS::net::TCPSocket::connected(), MaxOS::net::TCPSocket::disconnected(), error_messages, MaxOS::net::TCPSocket::handle_transmission_control_protocol_payload(), MaxOS::net::TCPSocket::remote_ip, MaxOS::net::TCPSocket::remotePort, send_transmission_control_protocol_packet(), MaxOS::net::TCPSocket::sequence_number, sockets, MaxOS::net::TCPSocket::state, and MaxOS::common::OutputStream::write().

◆ listen()

TCPSocket * TransmissionControlProtocolHandler::listen ( uint16_t  port)
virtual

Begin listening on a port.

Parameters
portThe port to listen on
Returns
The socket that will handle the connection

Definition at line 551 of file tcp.cpp.

551 {
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}

References MaxOS::net::InternetProtocolHandler::get_internet_protocol_address(), MaxOS::net::IPV4PayloadHandler::internet_protocol_handler, MaxOS::memory::MemoryManager::kmalloc(), sockets, and MaxOS::net::TCPSocket::state.

◆ send_transmission_control_protocol_packet()

void TransmissionControlProtocolHandler::send_transmission_control_protocol_packet ( TCPSocket socket,
const uint8_t data,
uint16_t  size,
uint16_t  flags = 0 
)
protected

send a packet (Throught the provider)

Parameters
socketThe socket to send the packet from
dataThe data to send
sizeThe size of the data
flagsThe flags to send

Definition at line 420 of file tcp.cpp.

420 {
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}
static void kfree(void *pointer)
Frees a block of memory using the kernel memory manager.
void send(InternetProtocolAddress destination_ip, uint8_t *payload_data, uint32_t size)
Sends an IP packet.
Definition ipv4.cpp:93
static uint16_t checksum(const uint16_t *data, uint32_t length_in_bytes)
Creates a checksum for the given data.
Definition ipv4.cpp:249
uint16_t local_port
The port on this device.
Definition tcp.h:182
uint32_t local_ip
The IP address of this device.
Definition tcp.h:183
The pseudo header used for TCP checksum calculation.
Definition tcp.h:94

References MaxOS::net::TCPSocket::acknowledgement_number, big_endian_16(), big_endian_32(), MaxOS::net::InternetProtocolHandler::checksum(), MaxOS::memory::MemoryManager::kfree(), MaxOS::memory::MemoryManager::kmalloc(), MaxOS::net::TCPSocket::local_ip, MaxOS::net::TCPSocket::local_port, MaxOS::net::TCPSocket::remote_ip, MaxOS::net::TCPSocket::remotePort, MaxOS::net::IPV4PayloadHandler::send(), and MaxOS::net::TCPSocket::sequence_number.

Referenced by connect(), disconnect(), handle_internet_protocol_payload(), and MaxOS::net::TCPSocket::send().

Friends And Related Symbol Documentation

◆ TCPSocket

friend class TCPSocket
friend

Definition at line 207 of file tcp.h.

Member Data Documentation

◆ error_messages

common::OutputStream* MaxOS::net::TransmissionControlProtocolHandler::error_messages
protected

Where to write error messages.

Definition at line 210 of file tcp.h.

Referenced by handle_internet_protocol_payload(), and TransmissionControlProtocolHandler().

◆ free_ports

TransmissionControlProtocolPort TransmissionControlProtocolHandler::free_ports = 0x8000
staticprotected

The next free port to use for new sockets.

Handler///

Definition at line 213 of file tcp.h.

Referenced by connect().

◆ sockets

common::Vector<TCPSocket*> MaxOS::net::TransmissionControlProtocolHandler::sockets
protected

The list of connected sockets.

Definition at line 211 of file tcp.h.

Referenced by connect(), handle_internet_protocol_payload(), and listen().


The documentation for this class was generated from the following files: