This commit is contained in:
louiscklaw
2025-02-01 01:59:20 +08:00
commit e1e1c21cb6
57 changed files with 2652 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
/**
*Copyright (C) 2023 Carnegie Mellon University and
*Hong Kong University of Science and Technology
*This repository is adopted from the TCP in the
*Wild course project from the Computer Networks
*course taught at Carnegie Mellon University, and
*is used for the Computer Networks (ELEC 3120)
*course taught at Hong Kong University of Science
*and Technology.
*No part of the project may be copied and/or
*distributed without the express permission of
*the course staff. Everyone is prohibited from
*releasing their forks in any public places.
*
*
* This file defines the function signatures for the CMU-TCP backend that should
* be exposed. The backend runs in a different thread and handles all the socket
* operations separately from the application.
*/
#ifndef PROJECT_1_ELEC3120_INC_BACKEND_H_
#define PROJECT_1_ELEC3120_INC_BACKEND_H_
/**
* Launches the CMU-TCP backend.
*
* @param in the socket to be used for backend processing.
*/
void* begin_backend(void* in);
#endif // PROJECT_1_ELEC3120_INC_BACKEND_H_

View File

@@ -0,0 +1,182 @@
/**
*Copyright (C) 2023 Carnegie Mellon University and
*Hong Kong University of Science and Technology
*This repository is adopted from the TCP in the
*Wild course project from the Computer Networks
*course taught at Carnegie Mellon University, and
*is used for the Computer Networks (ELEC 3120)
*course taught at Hong Kong University of Science
*and Technology.
*No part of the project may be copied and/or
*distributed without the express permission of
*the course staff. Everyone is prohibited from
*releasing their forks in any public places.
*
* Defines a CMU-TCP packet and define helper functions to create and manipulate
* packets.
*
* Do NOT modify this file.
*/
#ifndef PROJECT_1_ELEC3120_INC_CMU_PACKET_H_
#define PROJECT_1_ELEC3120_INC_CMU_PACKET_H_
#include <stdint.h>
typedef struct {
uint32_t identifier; // Identifier for the CMU-TCP protocol.
uint16_t source_port; // Source port.
uint16_t destination_port; // Destination port.
uint32_t seq_num; // Sequence number.
uint32_t ack_num; // Acknowledgement number.
uint16_t hlen; // Header length.
uint16_t plen; // Packet length.
uint8_t flags; // Flags.
uint16_t advertised_window; // Advertised window.
uint16_t extension_length; // Extension length.
uint8_t extension_data[]; // Extension data.
} __attribute__((__packed__)) cmu_tcp_header_t;
#define SYN_FLAG_MASK 0x8
#define ACK_FLAG_MASK 0x4
#define FIN_FLAG_MASK 0x2
#define IDENTIFIER 15441
// Maximum Segment Size. Make sure to update this if your CCA requires extension
// data for all packets, as this reduces the payload and thus the MSS.
#define MSS (MAX_LEN - sizeof(cmu_tcp_header_t))
/* Helper functions to get/set fields in the header */
uint16_t get_src(cmu_tcp_header_t* header);
uint16_t get_dst(cmu_tcp_header_t* header);
uint32_t get_seq(cmu_tcp_header_t* header);
uint32_t get_ack(cmu_tcp_header_t* header);
uint16_t get_hlen(cmu_tcp_header_t* header);
uint16_t get_plen(cmu_tcp_header_t* header);
uint8_t get_flags(cmu_tcp_header_t* header);
uint16_t get_advertised_window(cmu_tcp_header_t* header);
uint16_t get_extension_length(cmu_tcp_header_t* header);
uint8_t* get_extension_data(cmu_tcp_header_t* header);
void set_src(cmu_tcp_header_t* header, uint16_t src);
void set_dst(cmu_tcp_header_t* header, uint16_t dst);
void set_seq(cmu_tcp_header_t* header, uint32_t seq);
void set_ack(cmu_tcp_header_t* header, uint32_t ack);
void set_hlen(cmu_tcp_header_t* header, uint16_t hlen);
void set_plen(cmu_tcp_header_t* header, uint16_t plen);
void set_flags(cmu_tcp_header_t* header, uint8_t flags);
void set_advertised_window(cmu_tcp_header_t* header,
uint16_t advertised_window);
void set_extension_length(cmu_tcp_header_t* header, uint16_t extension_length);
void set_extension_data(cmu_tcp_header_t* header, uint8_t* extension_data);
/**
* Sets all the header fields.
*
* Review TCP headers for more information about what each field means.
*
* @param header The header to set the fields.
* @param src Source port.
* @param dst Destination port.
* @param seq Sequence number.
* @param ack Acknowledgement number.
* @param hlen Header length.
* @param plen Packet length.
* @param flags Packet flags.
* @param advertised_window Advertised window.
* @param extension_length Header extension length.
* @param extension_data Header extension data.
*/
void set_header(cmu_tcp_header_t* header, uint16_t src, uint16_t dst,
uint32_t seq, uint32_t ack, uint16_t hlen, uint16_t plen,
uint8_t flags, uint16_t adv_window, uint16_t ext,
uint8_t* ext_data);
/**
* Gets a pointer to the packet payload.
*
* @param pkt The packet to get the payload.
*
* @return A pointer to the payload.
*/
uint8_t* get_payload(uint8_t* pkt);
/**
* Gets the length of the packet payload.
*
* @param pkt The packet to get the payload length.
*
* @return The length of the payload.
*/
uint16_t get_payload_len(uint8_t* pkt);
/**
* Sets the packet payload.
*
* @param pkt The packet to set the payload.
* @param payload A pointer to the payload to be set.
* @param payload_len The length of the payload.
*/
void set_payload(uint8_t* pkt, uint8_t* payload, uint16_t payload_len);
/**
* Allocates and initializes a packet.
*
* @param src The source port.
* @param dst The destination port.
* @param seq The sequence number.
* @param ack The acknowledgement number.
* @param hlen The header length.
* @param plen The packet length.
* @param flags The flags.
* @param adv_window The advertised window.
* @param ext_len The header extension length.
* @param ext_data The header extension data.
* @param payload The payload.
* @param payload_len The length of the payload.
*
* @return A pointer to the newly allocated packet. User must `free` after use.
*/
uint8_t* create_packet(uint16_t src, uint16_t dst, uint32_t seq, uint32_t ack,
uint16_t hlen, uint16_t plen, uint8_t flags,
uint16_t adv_window, uint16_t ext_len, uint8_t* ext_data,
uint8_t* payload, uint16_t payload_len);
/**
* Checks if a given sequence number comes before another sequence number.
*
* @param seq1 the first sequence number.
* @param seq2 the second sequence number.
* @return 1 if seq1 comes before seq2, 0 otherwise.
*/
static inline int before(uint32_t seq1, uint32_t seq2) {
return (int32_t)(seq1 - seq2) < 0;
}
/**
* Checks if a given sequence number comes after another sequence number.
*
* @param seq1 the first sequence number.
* @param seq2 the second sequence number.
* @return 1 if seq1 comes after seq2, 0 otherwise.
*/
static inline int after(uint32_t seq1, uint32_t seq2) {
return before(seq2, seq1);
}
/**
* Checks if a given sequence number is between two others.
*
* @param seq the sequence number.
* @param low the lower bound.
* @param high the upper bound.
* @return 1 if low <= seq <= high, 0 otherwise.
*/
static inline int between(uint32_t seq, uint32_t low, uint32_t high) {
return high - low >= seq - low;
}
#endif // PROJECT_1_ELEC3120_INC_CMU_PACKET_H_

View File

@@ -0,0 +1,145 @@
/**
*Copyright (C) 2023 Carnegie Mellon University and
*Hong Kong University of Science and Technology
*This repository is adopted from the TCP in the
*Wild course project from the Computer Networks
*course taught at Carnegie Mellon University, and
*is used for the Computer Networks (ELEC 3120)
*course taught at Hong Kong University of Science
*and Technology.
*No part of the project may be copied and/or
*distributed without the express permission of
*the course staff. Everyone is prohibited from
*releasing their forks in any public places.
*
*
* This file defines the API for the CMU TCP implementation.
*/
#ifndef PROJECT_1_ELEC3120_INC_CMU_TCP_H_
#define PROJECT_1_ELEC3120_INC_CMU_TCP_H_
#include <netinet/in.h>
#include <pthread.h>
#include <stdint.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "cmu_packet.h"
#include "grading.h"
#define EXIT_SUCCESS 0
#define EXIT_ERROR -1
#define EXIT_FAILURE 1
typedef struct {
uint32_t next_seq_expected;
uint32_t last_ack_received;
pthread_mutex_t ack_lock;
} window_t;
/**
* CMU-TCP socket types. (DO NOT CHANGE.)
*/
typedef enum {
TCP_INITIATOR = 0,
TCP_LISTENER = 1,
} cmu_socket_type_t;
/**
* This structure holds the state of a socket. You may modify this structure as
* you see fit to include any additional state you need for your implementation.
*/
typedef struct {
int socket;
pthread_t thread_id;
uint16_t my_port;
struct sockaddr_in conn;
uint8_t* received_buf;
int received_len;
pthread_mutex_t recv_lock;
pthread_cond_t wait_cond;
uint8_t* sending_buf;
int sending_len;
cmu_socket_type_t type;
pthread_mutex_t send_lock;
int dying;
pthread_mutex_t death_lock;
window_t window;
} cmu_socket_t;
/*
* DO NOT CHANGE THE DECLARATIONS BELOW
*/
/**
* Read mode flags supported by a CMU-TCP socket.
*/
typedef enum {
NO_FLAG = 0, // Default behavior: block indefinitely until data is available.
NO_WAIT, // Return immediately if no data is available.
TIMEOUT, // Block until data is available or the timeout is reached.
} cmu_read_mode_t;
/**
* Constructs a CMU-TCP socket.
*
* An Initiator socket is used to connect to a Listener socket.
*
* @param sock The structure with the socket state. It will be initialized by
* this function.
* @param socket_type Indicates the type of socket: Listener or Initiator.
* @param port Port to either connect to, or bind to. (Based on socket_type.)
* @param server_ip IP address of the server to connect to. (Only used if the
* socket is an initiator.)
*
* @return 0 on success, -1 on error.
*/
int cmu_socket(cmu_socket_t* sock, const cmu_socket_type_t socket_type,
const int port, const char* server_ip);
/**
* Closes a CMU-TCP socket.
*
* @param sock The socket to close.
*
* @return 0 on success, -1 on error.
*/
int cmu_close(cmu_socket_t* sock);
/**
* Reads data from a CMU-TCP socket.
*
* If there is data available in the socket buffer, it is placed in the
* destination buffer.
*
* @param sock The socket to read from.
* @param buf The buffer to read into.
* @param length The maximum number of bytes to read.
* @param flags Flags that determine how the socket should wait for data. Check
* `cmu_read_mode_t` for more information. `TIMEOUT` is not
* implemented for CMU-TCP.
*
* @return The number of bytes read on success, -1 on error.
*/
int cmu_read(cmu_socket_t* sock, void* buf, const int length,
cmu_read_mode_t flags);
/**
* Writes data to a CMU-TCP socket.
*
* @param sock The socket to write to.
* @param buf The data to write.
* @param length The number of bytes to write.
*
* @return 0 on success, -1 on error.
*/
int cmu_write(cmu_socket_t* sock, const void* buf, int length);
/*
* You can declare more functions after this point if you need to.
*/
#endif // PROJECT_1_ELEC3120_INC_CMU_TCP_H_

View File

@@ -0,0 +1,43 @@
/**
*Copyright (C) 2023 Carnegie Mellon University and
*Hong Kong University of Science and Technology
*This repository is adopted from the TCP in the
*Wild course project from the Computer Networks
*course taught at Carnegie Mellon University, and
*is used for the Computer Networks (ELEC 3120)
*course taught at Hong Kong University of Science
*and Technology.
*No part of the project may be copied and/or
*distributed without the express permission of
*the course staff. Everyone is prohibited from
*releasing their forks in any public places.
*
*
* This files defines constants used for grading. Do NOT modify this file as
* any changes will be overwritten by the autograder.
*/
#ifndef PROJECT_1_ELEC3120_INC_GRADING_H_
#define PROJECT_1_ELEC3120_INC_GRADING_H_
/*
* DO NOT CHANGE THIS FILE
* This contains the variables for your TCP implementation
* and we will replace this file during the autolab testing with new variables.
*/
// packet lengths
#define MAX_LEN 1400
// window variables
#define WINDOW_INITIAL_WINDOW_SIZE (MSS * 16)
#define WINDOW_INITIAL_SSTHRESH (MSS * 64)
#define WINDOW_INITIAL_RTT 3000 // ms
#define WINDOW_INITIAL_ADVERTISED MSS
// Max TCP Buffer
#define MAX_NETWORK_BUFFER 65535 // (2^16 - 1) bytes
#endif // PROJECT_1_ELEC3120_INC_GRADING_H_