Κοινή χρήση τεχνολογίας

Raw Socket (1) Εφαρμογή TCP τριπλής χειραψίας

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

εργαστηριακό περιβάλλον:
Φυσική μηχανή Windows: 192.168.1.4
WSL Ubuntu 20.04.6 LTS:172.19.32.196
Ένας διακομιστής http κάτω από τα Windows: HFS, μάλλον μοιάζει με αυτό:
Εισαγάγετε την περιγραφή της εικόνας εδώ
Ο πελάτης είναι το Ubuntu, ο διακομιστής είναι ο διακομιστής http (στο εξής θα αναφέρεται ως διακομιστής ή διακομιστής) και η IP του διακομιστή μεταβιβάζεται στο πρόγραμμα μέσω παραμέτρων.

Ο πηγαίος κώδικας βρίσκεται στο τέλος.

Το κύριο πρόγραμμα λειτουργιών χωρίζεται στα ακόλουθα μέρη:
1. Λάβετε παραμέτρους , και επιλέξτε την κάρτα δικτύου για επικοινωνία μέσω επικοινωνίας netlink (στην πραγματικότητα το Ubuntu έχει μόνο μία κάρτα δικτύου, η ip είναι 172.19.32.196) και αρχικοποιήστε την ip και τη θύρα του διακομιστή και του πελάτη. Για πληροφορίες σχετικά με την επιλογή κάρτας δικτύου για επικοινωνία μέσω netlink επικοινωνίας, ανατρέξτε στον παρακάτω σύνδεσμο:
Επικοινωνία Netlink - διαβάστε τον πίνακα δρομολόγησης για να λάβετε την IP της κάρτας δικτύου επικοινωνίας
Μέρος του κώδικα:

	...
	// netlink通信
	uint32_t src_address = getLocalIPAddress(inet_addr(dst));
	...
	src_addr.sin_family = AF_INET;
	src_addr.sin_port = htons((uint16_t) getpid());  // 将当前进程ID作为源端口
	src_addr.sin_addr = *(struct in_addr *) &src_address;

	dst_addr.sin_family = AF_INET;
	dst_addr.sin_port = htons(HTTP_PORT);
	dst_addr.sin_addr.s_addr = inet_addr(dst);
	...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2. Δημιουργήστε δύο υποδοχές, αποστολή υποδοχής και υποδοχής λήψης, δεσμεύστε τον πελάτη (αυτό το βήμα είναι προαιρετικό, επειδή το τετραπλό σε αυτό το παράδειγμα δεν έχει αλλάξει) και ορίστε τα χαρακτηριστικά του πρωτοκόλλου υποδοχής.
Μέρος του κώδικα:

	...
	send_sock_fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
	recv_sock_fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
	bind(recv_sock_fd, (const struct sockaddr *) &src_addr,
			sizeof(struct sockaddr_in)) < 0);
	int one = 1;
	setsockopt(recv_sock_fd, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one));
	...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

       Δημιουργία υποδοχών αποστολής και λήψης:
Το AF_INET αντιπροσωπεύει τη σουίτα πρωτοκόλλων TCP/IP – IPv4.
SOCK_RAW υποδηλώνει ότι ο τύπος υποδοχής είναι ακατέργαστη υποδοχή.
Η τρίτη παράμετρος είναι η παράμετρος του πρωτοκόλλου IPPROTO_RAW σημαίνει ότι οι προγραμματιστές μπορούν να κατασκευάσουν και να αναλύσουν τα πακέτα δεδομένων IP , υποδεικνύοντας ότι το ληφθέν πακέτο δεδομένων είναι ένα πακέτο δεδομένων TCP.
       Σύνδεση ip και θύρας πελάτη: Αυτό το βήμα δεν είναι απαραίτητο, όπως αναφέρθηκε παραπάνω, οι διευθύνσεις IP και οι θύρες και των δύο μερών παραμένουν αμετάβλητες.
       Ορισμός ιδιοτήτων πρωτοκόλλου υποδοχής:setsockopt ορίζει τις ιδιότητες της υποδοχής λήψης Η δεύτερη παράμετρος είναι η επιλογή υποδοχής.
       (1) Επιλογές επιπέδου υποδοχής(SOL_SOCKET)
SO_REUSEADDR: Να επιτρέπεται η επαναχρησιμοποίηση των τοπικών διευθύνσεων.
SO_RCVBUF: Ορίστε το μέγεθος του buffer λήψης.
SO_SNDBUF: Ορίστε το μέγεθος του buffer αποστολής.
SO_BROADCAST: Επιτρέπει την αποστολή μηνυμάτων μετάδοσης.
SO_KEEPALIVE: Ενεργοποιήστε τον μηχανισμό διατήρησης και ελέγξτε εάν η σύνδεση είναι έγκυρη.
       (2) Επιλογή επιπέδου IP (IPPROTO_IP)
IP_TTL: Ρυθμίστε το χρόνο ζωής (TTL) των δεδομένων IP.
IP_HDRINCL: Καθοδηγεί την εφαρμογή να παρέχει κεφαλίδες IP.
       (3) Επιλογή επιπέδου TCP (IPPROTO_TCP)
TCP_NODELAY: Απενεργοποιήστε τον αλγόριθμο Nagle για να μειώσετε την καθυστέρηση.
TCP_MAXSEG: Ορίστε το μέγιστο μέγεθος τμήματος TCP.
Σε αυτό το παράδειγμα, η επιλογή υποδοχής έχει οριστεί στην επιλογή επιπέδου IP IP_HDRINCL του IPPROTO_IP - υποδεικνύοντας ότι το ληφθέν πακέτο περιέχει μια κεφαλίδα IP.

       

Ξεκινήστε τρεις χειραψίες

connect_tcp(send_sock_fd, recv_sock_fd, &dst_addr, &src_addr);
  • 1
//Blocking call
int connect_tcp(int send_fd, int recv_fd, struct sockaddr_in* dst_addr,
		struct sockaddr_in* src_addr)
{
	int ret = 0;

// Initialize the TCP Session State with the given details
	bzero(&tcp_state, sizeof(tcp_state__t));
	tcp_state.max_segment_size = MAX_CLIENT_SEGMENT_SIZE;    // 初始化MSS
	tcp_state.client_window_size = CLIENT_WINDOW_SIZE;       // 初始化拥塞窗口
	tcp_state.client_next_seq_num = STARTING_SEQUENCE;       // 客户端下个包的seq
	tcp_state.session_info.dst_addr = *dst_addr;             // 目的地址
	tcp_state.session_info.src_addr = *src_addr;             // 源地址
	tcp_state.session_info.recv_fd = recv_fd;                // 接收句柄
	tcp_state.session_info.send_fd = send_fd;                // 发送句柄
	tcp_state.syn_retries = 5;                               // 重传次数
	tcp_state.cwindow_size = 1;    // 拥塞窗口值
	initialize_mutex(&tcp_state.tcp_state_lock);
	initialize_mutex(&tcp_state.session_info.send_fd_lock);

	tcp_flags_t flags = {0};
	flags.ack = 1;
	flags.syn = 1;
	if (((ret = send_syn()) < 0) || ((ret = receive_syn_ack_segment(&flags)) < 0)
	                             || ((ret = send_ack_segment(0)) < 0))
	{
		printf("Failed to set up TCP Connection!!");
		ret = -1;
		goto EXIT;
	}
	tcp_state.tcp_current_state = ESTABLISHED;

	EXIT: return ret;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

Η διαδικασία της χειραψίας είναι περίπου η εξής:
Εισαγάγετε την περιγραφή της εικόνας εδώ
Μπορεί να φανεί ότι χωρίζεται σε τρία στάδια:
       1. Αποστολή πακέτου SYN, η αντίστοιχη συνάρτηση είναι: send_syn();
Η create_packet() δημιουργεί ένα πακέτο TCP Αυτή η συνάρτηση είναι πολύ σημαντική και υλοποιείται πολύ έξυπνα Με τη ρύθμιση του δείκτη μετατόπισης, η κεφαλίδα IP, η κεφαλίδα TCP και τα δεδομένα μπορούν να βρεθούν. Η σημαία SYN του TCP πρέπει να οριστεί σε 1 και, στη συνέχεια, κατασκευάζεται η κεφαλίδα - build_packet_headers Η συγκεκριμένη εργασία είναι η ενθυλάκωση της κεφαλίδας TCP, ο υπολογισμός του αθροίσματος ελέγχου TCP, η ενθυλάκωση της κεφαλίδας IP και ο υπολογισμός του αθροίσματος ελέγχου. Στο διάγραμμα μετάβασης κατάστασης TCP, αφού ο πελάτης στείλει το πακέτο SYN, η κατάστασή του αλλάζει από ΚΛΕΙΣΤΟ σε SYN_SENT, επομένως η κατάσταση TCP πρέπει να οριστεί: tcp_state.tcp_current_state = SYN_SENT Για να στείλετε δεδομένα, Για να δημιουργήσετε ένα χρονόμετρο αναμετάδοσης, ρυθμίστε τη λειτουργία επανάκλησης Μετά την αποστολή του πακέτου SYN, εάν δεν ληφθεί απάντηση εντός του χρονικού ορίου, το πακέτο SYN πρέπει να αναμεταδοθεί. Επομένως, είναι επίσης απαραίτητο να γράψετε το απεσταλμένο πακέτο στην κυκλική ουρά αποστολής Μετά το πέρας του χρονικού ορίου, τα αποθηκευμένα δεδομένα αφαιρούνται από την κυκλική ουρά αποστολής και αποστέλλονται ξανά.
       2. Λάβετε πακέτα SYN/ACK, η αντίστοιχη συνάρτηση είναι receive_syn_ack_segment(&flags);
Χρησιμοποιήστε τη συνάρτηση recvfrom για να λάβετε δεδομένα Αφού τα λάβετε, πρέπει να κάνετε μια σειρά δοκιμών, όπως να ελέγξετε το άθροισμα ελέγχου IP, να ελέγξετε εάν οι θύρες προέλευσης και προορισμού και η IP είναι σωστές, να ελέγξετε το άθροισμα ελέγχου TCP και να ελέγξετε εάν το πακέτο. είναι ένα πακέτο αναμετάδοσης. Στη συνέχεια, πρέπει επίσης να ορίσετε τις κατευθύνσεις μετατόπισης της κεφαλίδας IP, της κεφαλίδας TCP και των δεδομένων στο πακέτο δεδομένων. Στη συνέχεια, μπορείτε να προσδιορίσετε εάν η σημαία SYN και η σημαία ACK του λαμβανόμενου πακέτου είναι 1 και εάν είναι πακέτο RST. Μετά την ολοκλήρωση αυτών των εργασιών, πρέπει ακόμα να επεξεργαστείτε αυτό το πακέτο SYN/ACK, συμπεριλαμβανομένου του ορισμού της ακολουθίας του επόμενου πακέτου από τον διακομιστή, της ρύθμισης της ακολουθίας του επόμενου πακέτου από τον πελάτη, της ενημέρωσης της τιμής του παραθύρου λήψης του διακομιστή, της ενημέρωσης του τιμή του παραθύρου συμφόρησης και ξεκινώντας από το παράθυρο λήψης Διαγράψτε αυτό το πακέτο απόκρισης από την κυκλική ουρά (επειδή έχει υποστεί επεξεργασία), αφήστε το χώρο που ανοίγει για τη λήψη αυτού του πακέτου και ενημερώστε το MSS.
       3. Αποστολή πακέτου ACK, η αντίστοιχη συνάρτηση είναι send_ack_segment(0);
Το τρίτο βήμα είναι πολύ απλό Στείλτε μια απάντηση, υποδεικνύοντας ότι η τριπλή χειραψία είναι επιτυχής. Ορίστε την κατάσταση TCP σε ESTABLISHED.

Ποιο είναι λοιπόν το αποτέλεσμα Εκτελέστε το πρόγραμμα και χρησιμοποιήστε το wireshark για να καταγράψετε το πακέτο:
Εισαγάγετε την περιγραφή της εικόνας εδώ

Εισαγάγετε την περιγραφή της εικόνας εδώ
       Μπορεί να φανεί ότι μετά την αποστολή του πακέτου SYN και τη λήψη του SYN/ACK, ο πελάτης έστειλε με κάποιο τρόπο ένα άλλο πακέτο RST και στη συνέχεια έστειλε το πακέτο ACK αποτυχημένη σύνδεση. .
       Ποιος είναι ο λόγος για αυτό;

        Αυτό το πρόγραμμα χρησιμοποιεί ακατέργαστες υποδοχές για επικοινωνία, όχι κλήσεις συστήματος Όταν ο πελάτης στέλνει SYN/ACK, το λειτουργικό σύστημα λαμβάνει πρώτα το πακέτο και, στη συνέχεια, ελέγχει εάν υπάρχει μια αντίστοιχη υποδοχή (που δημιουργήθηκε με χρήση κλήσεων συστήματος) τοπικά δεν είναι κανένας, τότε θα σταλεί ένα πακέτο RST και, στη συνέχεια, η τριπλή χειραψία θα αποτύχει να δημιουργήσει τη σύνδεση. .

       Πώς να το λύσετε λοιπόν;

Επειδή αυτό το πρόγραμμα είναι κυρίως για πειραματική μάθηση, η λύση μπορεί να είναι η χρήση iptables για την απόρριψη των πακέτων RST που αποστέλλονται από το μηχάνημα Αυτή τη στιγμή, ο διακομιστής δεν θα λάβει τα πακέτα RST που αποστέλλονται από τον πελάτη και η σύνδεση μπορεί να δημιουργηθεί με επιτυχία !
Εφαρμοσμένο σενάριο φλοιού:

#!/bin/sh

if ! iptables -C OUTPUT -p tcp --tcp-flags RST RST -j DROP; then
    iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP
fi

./handshake "$@" 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Πρώτα ελέγξτε αν εκτελείται η εντολή iptables -C OUTPUT -p tcp --tcp-flags RST RST -j DROP. Εάν όχι, εκτελέστε την ξανά.

Προβολή αποτελεσμάτων:
Εισαγάγετε την περιγραφή της εικόνας εδώ
επιτυχία!

       Τέλος, αυτό το πρόγραμμα εφαρμόζει μόνο την τριπλή χειραψία και δεν εφαρμόζει το κύμα τεσσάρων κατευθύνσεων.
       Πηγαίος κώδικας
τρέχω.sh

#!/bin/sh

if ! iptables -C OUTPUT -p tcp --tcp-flags RST RST -j DROP; then
    iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP
fi

./handshake "$@"

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Makefile

CFLAGS= -g -Werror -lrt -lpthread
CC=gcc

all:
	$(CC) handshake.c routing_table.c tcp_handler.c $(CFLAGS) -o handshake

clean:
	rm -rf handshake 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

χειραψία.γ

#include "routing_table.h"
#include "tcp_handler.h"
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>

#define WRITE_BUFFER_SIZE 2048
#define RECV_BUFFER_LENGTH 32768
#define REQ_LENGTH 256
#define STRIP_LEADING_NEWLINE_CHAR(ptr) 
	while(*ptr == 'n') 
		ptr++;
#define STRIP_LEADING_WHITESPACES(ptr) 
	while(*ptr == ' ') 
		ptr++;
#define STRIP_TRAILING_CARRIAGE_RETURN(ptr) (ptr[strlen(ptr)-1] = '0')

int main(int argc, char** argv)
{

	int send_sock_fd = -1, recv_sock_fd = -1;
	struct sockaddr_in src_addr, dst_addr;
	char dst[REQ_LENGTH] = {0};

	if (argc != 2)
	{
		printf("Usage: ./rawhttpget ipn");
		exit(1);
	}

	strncpy(dst, argv[1], REQ_LENGTH);

	memset(&src_addr, 0, sizeof(struct sockaddr_in));
	memset(&dst_addr, 0, sizeof(struct sockaddr_in));

    // netlink通信
	uint32_t src_address = getLocalIPAddress(inet_addr(dst));

	src_addr.sin_family = AF_INET;
	src_addr.sin_port = htons((uint16_t) getpid());  // 将当前进程ID作为源端口
	src_addr.sin_addr = *(struct in_addr *) &src_address;

	dst_addr.sin_family = AF_INET;
	dst_addr.sin_port = htons(HTTP_PORT);
	dst_addr.sin_addr.s_addr = inet_addr(dst);

	send_sock_fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); // IPPROTO_RAW:表示开发人员可以自己构造和解析 IP 数据包
	if (send_sock_fd < 0)
	{
		printf("Error: Creation of Raw Socket failed: %s!!n", strerror(errno));
		exit(1);
	}

	recv_sock_fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);  // IPPROTO_TCP表示接收TCP包

	if (recv_sock_fd < 0)
	{
		printf("Error: Creation of Raw Socket failed: %s!!n", strerror(errno));
		exit(1);
	}

	if (bind(recv_sock_fd, (const struct sockaddr *) &src_addr,
			sizeof(struct sockaddr_in)) < 0)
	{
		printf("Error: Unable to bind the receiving socket: %sn",
				strerror(errno));
		exit(1);
	}

	//IP_HDRINCL to tell the kernel that headers are included in the packet
	int one = 1;
	if (setsockopt(recv_sock_fd, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)) < 0) // IP_HDRINCL:数据中包含IP头
	{
		perror("Error setting IP_HDRINCL");
		exit(1);
	}

	char psrc_addr[256] = {0}, pdst_addr[256] = {0};
	printf("Src Address: %s Destination Address: %sn",
			inet_ntop(AF_INET, &src_addr.sin_addr.s_addr, psrc_addr, 256),
			inet_ntop(AF_INET, &dst_addr.sin_addr.s_addr, pdst_addr, 256));

	if (connect_tcp(send_sock_fd, recv_sock_fd, &dst_addr, &src_addr) < 0)
	{
		printf("TCP Connection Failedn");
		goto EXIT;
	}
	else
		printf("TCP Connection Successfuln");

	EXIT: close(send_sock_fd);
	close(recv_sock_fd);

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95

routing_table.γ

#include <stdio.h>
#include <stdlib.h>
#include <bits/sockaddr.h>
#include <asm/types.h>
#include <linux/rtnetlink.h>
#include <sys/socket.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>

#define BUFFER_LENGTH 8192
typedef struct rt_request
{
	struct nlmsghdr nl;
	struct rtmsg rt;
	char payload[BUFFER_LENGTH];
} rt_request;

uint32_t fetch_interface_ip(uint32_t if_index)
{
	int family;
	struct ifreq ifreq;
	char host[256] =
	{ 0 }, if_name[256] =
	{ 0 };
	uint32_t src_addr;
	int fd;

	if_indextoname(if_index, if_name);  // 根据索引值获取网络接口名,如eth0
	fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (fd < 0)
	{
		perror("socket()");
		exit(EXIT_FAILURE);
	}

	memset(&ifreq, 0, sizeof ifreq);
	strncpy(ifreq.ifr_name, if_name, IFNAMSIZ);
	if (ioctl(fd, SIOCGIFADDR, &ifreq) != 0)    // 获取接口ip
	{
		/* perror(name); */
		return -1; /* ignore */
	}

	switch (family = ifreq.ifr_addr.sa_family)
	{
	case AF_UNSPEC:
		// return;
		return -1; /* ignore */
	case AF_INET:
	case AF_INET6:
		getnameinfo(&ifreq.ifr_addr, sizeof ifreq.ifr_addr, host, sizeof host,
				0, 0, NI_NUMERICHOST);
		break;
	default:
		sprintf(host, "unknown  (family: %d)", family);
	}
	inet_pton(AF_INET, host, &src_addr);
	close(fd);
	return src_addr;
}

void formRequest(rt_request* req)
{
	bzero(req, sizeof(req));
/*
struct nlmsghdr 为 netlink socket 自己的消息头,
这用于多路复用和多路分解 netlink 定义的所有协议类型以及其它一些控制,
netlink 的内核实现将利用这个消息头来多路复用和多路分解已经其它的一些控制,
因此它也被称为netlink 控制块。因此,应用在发送 netlink 消息时必须提供该消息头。
*/
	req->nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
	req->nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;  // NLM_F_REQUEST表示消息是一个请求
	req->nl.nlmsg_type = RTM_GETROUTE;  // nlmsg_type消息内容

    // 填充rtmsg结构体,即路由表管理结构体,对于上面的RTM_GETROUTE操作来说,只需要定义下面两个内容
	req->rt.rtm_family = AF_INET;
	req->rt.rtm_table = RT_TABLE_MAIN;

}

void sendRequest(int sock_fd, struct sockaddr_nl *pa, rt_request* req)
{
	struct msghdr msg;    // sendmsg和recvmsg的参数,描述发送消息和接收消息的结构体
	struct iovec iov;     // iovec结构体用于描述一个数据缓冲区
	int rtn;

	bzero(pa, sizeof(pa));
	pa->nl_family = AF_NETLINK;

	bzero(&msg, sizeof(msg));
	msg.msg_name = pa;
	msg.msg_namelen = sizeof(*pa);

	iov.iov_base = (void *) req;
	iov.iov_len = req->nl.nlmsg_len;

	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;

	while (1)
	{
		if ((rtn = sendmsg(sock_fd, &msg, 0)) < 0)
		{
			if (errno == EINTR)
				continue;
			else
			{
				printf("Error: Unable to send NetLink message:%sn",
						strerror(errno));
				exit(1);
			}
		}
		break;
	}

}

int receiveReply(int sock_fd, char* response_buffer)
{
	char* p;
	int nll, rtl, rtn;
	struct nlmsghdr *nlp;
	struct rtmsg *rtp;

	bzero(response_buffer, BUFFER_LENGTH);
	p = response_buffer;
	nll = 0;

	while (1)
	{
		if ((rtn = recv(sock_fd, p, BUFFER_LENGTH - nll, 0)) < 0)
		{
			if (errno == EINTR)
				continue;
			else
			{
				printf("Failed to read from NetLink Socket: %sn",
						strerror(errno));
				exit(1);
			}

		}

		nlp = (struct nlmsghdr*) p;
		if (nlp->nlmsg_type == NLMSG_DONE)
			break;

		p += rtn;
		nll += rtn;
	}
	return nll;
}

uint32_t readReply(char *response, int nll, in_addr_t dst_address)
{
	struct nlmsghdr *nlp = NULL;
	struct rtmsg *rtp = NULL;
	struct rtattr *rtap = NULL;
	int rtl = 0, found_route = 0, default_route = 0;
	uint32_t route_addr, net_mask;
	uint32_t if_index = -1;

	nlp = (struct nlmsghdr*) response;
	for (; NLMSG_OK(nlp, nll); nlp = NLMSG_NEXT(nlp, nll))  // NLMSG_OK:检查nlh地址是否是一条完整的消息
	{                                                       // NLMSG_NEXT:当前消息地址,返回下一个消息地址
		rtp = (struct rtmsg *) NLMSG_DATA(nlp);        // NLMSG_DATA:从nlh首地址向后移动到data起始位置

		if (rtp->rtm_table != RT_TABLE_MAIN)
			continue;

		// RTM_RTA:输入route message指针,返回route第一个属性首地址
		rtap = (struct rtattr *) RTM_RTA(rtp);    // rtattr结构体封装可选路由信息的通用结构,用于表示 Netlink 消息的属性
		rtl = RTM_PAYLOAD(nlp);    // RTM_PAYLOAD:即rtmsg层封装的数据长度,相当于TCP数据包去掉IP报头和TCP报头长度得到TCP数据部分长度
		found_route = 0;
		default_route = 1;

		for (; RTA_OK(rtap, rtl); rtap = RTA_NEXT(rtap, rtl))  // RTA_OK:判断一个属性rta是否正确
		{                                                      // RTA_NEXT:先对attrlen减去rta属性内容的全部长度,然后返回下一个rtattr的首地址
			switch (rtap->rta_type)
			{
			// destination IPv4 address
			case RTA_DST:
				default_route = 0;
				route_addr = *((uint32_t*) RTA_DATA (rtap));
				net_mask = 0xFFFFFFFF;
				net_mask <<= (32 - rtp->rtm_dst_len);
				net_mask = ntohl(net_mask);
				if (route_addr == (dst_address & net_mask))
					found_route = 1;
				else if (route_addr == 0)
					default_route = 1;
				break;

				// unique ID associated with the network
				// interface
			case RTA_OIF:  // Output interface index
				if (found_route || default_route)
					if_index = *((uint32_t*) RTA_DATA (rtap));
				break;

			default:
				break;
			}
		}

		if (found_route)
			break;
	}

	return if_index;

}
// Netlink分层模型及消息格式:https://onestraw.github.io/linux/netlink-message/
uint32_t getLocalIPAddress(in_addr_t dst_address)
{
	int route_sock_fd = -1, res_len = 0;
	struct sockaddr_nl sa, pa;    // sa为消息接收者的 netlink 地址
	uint32_t if_index;

	rt_request req = {0};
	char response_payload[BUFFER_LENGTH] = {0};

	// Open Routing Socket
	if ((route_sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1)
	{
		printf("Error: Failed to open routing socket: %sn", strerror(errno));
		exit(1);
	}

	bzero(&sa, sizeof(sa));
	// nl_groups == 0 表示该消息为单播
	sa.nl_family = AF_NETLINK;
	sa.nl_pid = getpid();  // nl_pid表示接收消息者的进程ID

	bind(route_sock_fd, (struct sockaddr*) &sa, sizeof(sa));

	formRequest(&req);    // 构造netlink消息
	sendRequest(route_sock_fd, &pa, &req);    // 发送消息
	res_len = receiveReply(route_sock_fd, response_payload);    // 接收消息
	if_index = readReply(response_payload, res_len, dst_address);  // 从接收的消息中获取if(network interface)

	close(route_sock_fd);
	return fetch_interface_ip(if_index);    // 从if_index获取接口ip
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251

routing_table.h

#include <sys/types.h>
#include <netinet/in.h>

#ifndef ROUTING_TABLE_H
#define ROUTING_TABLE_H

uint32_t getLocalIPAddress(in_addr_t dst_address);

#endif

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

tcp_handler.c

#include "tcp_handler.h"

#define STARTING_SEQUENCE 1
#define TCP_WORD_LENGTH_WITH_NO_OPTIONS 5
#define HAS_TCP_OPTIONS(ptr) (ptr->doff > TCP_WORD_LENGTH_WITH_NO_OPTIONS)
#define TCP_OPTION_OFFSET(ptr) ((char*)ptr + (TCP_WORD_LENGTH_WITH_NO_OPTIONS * WORD_LENGTH))
#define TCP_OPTION_LENGTH(ptr) ((ptr->doff - TCP_WORD_LENGTH_WITH_NO_OPTIONS) * WORD_LENGTH)
#define END_OF_TCP_OPTION_CHECK(ptr) ((*ptr) == 0)
#define TCP_OPTIONS_LEN(ptr) ((ptr->doff - TCP_WORD_LENGTH_WITH_NO_OPTIONS) * WORD_LENGTH )
#define IS_NO_OPERATION(ptr) ((*ptr) == 1)
#define IS_MSS(ptr) ((*ptr) == 2)
#define OPTION_LENGTH(ptr) (*(ptr+1))
#define min(a,b) 
   ({ __typeof__ (a) _a = (a); 
       __typeof__ (b) _b = (b); 
     _a < _b ? _a : _b; })
#define TCP_OPTION_DATA_OFFSET 2

#define IS_DUPLICATE_TCP_SEGMENT(tcph) (ntohl(tcph->seq) < tcp_state.server_next_seq_num)
#define IS_DUPLICATE_ACK(tcph) (tcph->ack && (tcph->ack_seq == tcp_state.last_acked_seq_num) )
#define WRAP_ROUND_BUFFER_SIZE(index) 
		({ __typeof__ (index) _index = (index); 
		 ( _index + 1) > MAX_BUFFER_SIZE ? 0 : (_index + 1); })

tcp_state__t tcp_state;

/*
 Generic checksum calculation function
 */
static unsigned short csum(uint16_t *ptr, unsigned int nbytes)
{
	uint32_t sum;
	uint16_t answer;

	sum = 0;
	while (nbytes > 1)
	{
		sum += *ptr++;
		nbytes -= 2;    // 以16位的字为单位计算和
	}
	if (nbytes == 1)   // 如果总长度为奇数个字节,则在最后增添一个位都为0的字节
	{
		sum += *(unsigned char*) ptr;
	}
	// 将32bit数据压缩成16bit数据,即将高16bit与低16bit相加,将进位加到低16位上,最后取反
	sum = (sum >> 16) + (sum & 0xffff);
	sum = sum + (sum >> 16);
	answer = (short) ~sum;

	return (answer);
}

static void calculate_tcp_checksum(struct tcphdr* tcph,
		uint16_t tcp_payload_len, uint32_t src_addr, uint32_t dst_addr)
{
	pseudo_header psh;
	char* pseudogram;
	uint16_t tcphdr_len = (tcph->doff * WORD_LENGTH);  // tcph->doff:以32位字为单位表示TCP头长

	// pseudoheader
	bzero(&psh, sizeof(pseudo_header));
	psh.source_address = src_addr;
	psh.dest_address = dst_addr;
	psh.protocol = IPPROTO_TCP;
	psh.tcp_length = htons(tcphdr_len + tcp_payload_len);

	int psize = sizeof(pseudo_header) + tcphdr_len + tcp_payload_len;
	pseudogram = malloc(psize);

	// TCP伪首部、TCP头、TCP数据
	bzero(pseudogram, psize);
	memcpy(pseudogram, &psh, sizeof(pseudo_header));
	memcpy(pseudogram + sizeof(pseudo_header), tcph,
			tcphdr_len + tcp_payload_len);

	// 计算校验和
	tcph->check = csum((uint16_t*) pseudogram, (unsigned int) psize);
	free(pseudogram);
}

static int validate_ip_checksum(struct iphdr* iph)
{
	int ret = -1;
	uint16_t received_checksum = iph->check;
	iph->check = 0;

	if (received_checksum
			== csum((uint16_t*) iph, (unsigned int) (iph->ihl * WORD_LENGTH)))
		ret = 1;

	return ret;
}

static int validate_tcp_checksum(struct tcphdr* tcph,
		uint16_t tcp_payload_length)
{
	int ret = -1;
	uint16_t received_checksum = tcph->check;
	tcph->check = 0;
	calculate_tcp_checksum(tcph, tcp_payload_length,
			*(uint32_t *) &tcp_state.session_info.dst_addr.sin_addr.s_addr,
			*(uint32_t *) &tcp_state.session_info.src_addr.sin_addr.s_addr);
	if (received_checksum == tcph->check)
		ret = 1;

	if (ret < 0) {
		printf("received_checksum:%d, tcph->check:%dn", received_checksum, tcph->check);
	char psrc_addr[256] = {0}, pdst_addr[256] = {0};
	printf("Src Address: %s Destination Address: %sn",
			inet_ntop(AF_INET, &tcp_state.session_info.src_addr.sin_addr.s_addr, psrc_addr, 256),
			inet_ntop(AF_INET, &tcp_state.session_info.dst_addr.sin_addr.s_addr, pdst_addr, 256));
	}
	return ret;
}

static packet_t* create_packet()
{
	packet_t* packet = malloc(sizeof(packet_t));

	// send tcp syn
	bzero(packet, sizeof(packet_t));
	packet->offset[IP_OFFSET] = packet->payload;
	packet->offset[TCP_OFFSET] = packet->payload + sizeof(struct iphdr);
	packet->offset[DATA_OFFSET] = packet->payload + sizeof(struct tcphdr)
			+ sizeof(struct iphdr);
	packet->retransmit_timer_id = NULL;
	return packet;
}

static void adjust_layer_offset(packet_t* packet)
{
	struct tcphdr *tcph;
	struct iphdr *iph;

	iph = (struct iphdr *) packet->payload;
	tcph = (struct tcphdr *) (packet->payload + (iph->ihl * WORD_LENGTH));
	packet->offset[TCP_OFFSET] = (char*) tcph;
	packet->offset[DATA_OFFSET] = (char*) (packet->offset[TCP_OFFSET]
			+ (tcph->doff * WORD_LENGTH));
}

static void destroy_packet(packet_t* packet)
{
	if (packet->retransmit_timer_id != NULL)
		timer_delete(packet->retransmit_timer_id);

	free(packet);
}

static void remove_acked_entries(uint32_t next_expected_seq)
{
	pthread_mutex_lock(&tcp_state.sender_info.tcp_retx_lock);
	while ((tcp_state.sender_info.retx_buffer[tcp_state.sender_info.retx_buffer_head].packet_seq
			< next_expected_seq)
			&& !(tcp_state.sender_info.retx_buffer_head
					== tcp_state.sender_info.retx_buffer_tail))
	{
		destroy_packet(
				tcp_state.sender_info.retx_buffer[tcp_state.sender_info.retx_buffer_head].packet);
		tcp_state.sender_info.retx_buffer[tcp_state.sender_info.retx_buffer_head].packet = NULL;
		tcp_state.sender_info.retx_buffer_head =
		WRAP_ROUND_BUFFER_SIZE(tcp_state.sender_info.retx_buffer_head);
	}
	pthread_mutex_unlock(&tcp_state.sender_info.tcp_retx_lock);
}

static void reset_packet_retransmission_timer(timer_t* timer_id,
		uint16_t timeInSecs)
{
	struct itimerspec timer_value = {0};
	timer_value.it_interval.tv_sec = timeInSecs;
	timer_value.it_value.tv_sec = timeInSecs;

	if (timer_settime(*timer_id, 0, &timer_value, NULL) < 0)
	{
		printf("Failed to set time!!");
		timer_delete(*timer_id);
		*timer_id = NULL;
	}
}

static void build_ip_header(struct iphdr* iph, uint16_t ip_payload_len)
{
	iph->daddr = *(uint32_t*) &tcp_state.session_info.dst_addr.sin_addr.s_addr;
	iph->saddr = *(uint32_t*) &tcp_state.session_info.src_addr.sin_addr.s_addr;
	iph->ihl = 5;
	iph->protocol = IPPROTO_TCP;
	iph->ttl = 255;
	iph->version = 4;
	iph->tot_len = sizeof(struct iphdr) + ip_payload_len;
	iph->check = csum((unsigned short*) iph, sizeof(struct iphdr));
}

static void build_tcp_header(struct tcphdr* tcph, tcp_flags_t* flags,
		uint16_t payload_len)
{
	tcph->dest = *(uint16_t*) &tcp_state.session_info.dst_addr.sin_port;
	tcph->source = *(uint16_t*) &tcp_state.session_info.src_addr.sin_port;
	tcph->window = htons(tcp_state.client_window_size);
	tcph->seq = htonl(tcp_state.client_next_seq_num);
	tcp_state.client_next_seq_num +=
			(flags->syn || flags->fin) ? 1 : payload_len;
	tcph->doff = (flags->syn) ? 6 : 5;
	tcph->syn = flags->syn;
	tcph->ack = flags->ack;
	tcph->fin = flags->fin;
	tcph->psh = flags->psh;
	tcph->ack_seq = htonl(tcp_state.server_next_seq_num);

	if (flags->syn)
	{
		char* tcp_options = ((char *) tcph) + sizeof(struct tcphdr);
		tcp_options_t mss = {0};
		mss.option_type = 2;
		mss.option_len = 4;
		mss.option_value = htons(1460);
		memcpy(tcp_options++, &mss.option_type, sizeof(char));
		memcpy(tcp_options++, &mss.option_len, sizeof(char));
		memcpy(tcp_options, &mss.option_value, sizeof(uint16_t));
	}
}

static void build_packet_headers(packet_t* packet, int payload_len,
		tcp_flags_t* flags)
{
	struct tcphdr* tcph = (struct tcphdr*) packet->offset[TCP_OFFSET];
	struct iphdr* iph = (struct iphdr*) packet->offset[IP_OFFSET];

	build_tcp_header(tcph, flags, payload_len);
	calculate_tcp_checksum(tcph, payload_len,
			*(uint32_t *) &tcp_state.session_info.src_addr.sin_addr.s_addr,
			*(uint32_t *) &tcp_state.session_info.dst_addr.sin_addr.s_addr);
	build_ip_header(iph, ((tcph->doff * WORD_LENGTH) + payload_len));
}

static int send_packet(void *buffer, int total_packet_len)
{
	int ret = -1;

	pthread_mutex_lock(&tcp_state.session_info.send_fd_lock);
	while (total_packet_len > 0)
	{
		//Send the packet
		if ((ret = sendto(tcp_state.session_info.send_fd, buffer,
				total_packet_len, 0,
				(struct sockaddr *) &tcp_state.session_info.dst_addr,
				sizeof(struct sockaddr_in))) < 0)
		{
			if (errno == EINTR)
			{
				printf("Sendto() Interrupted!!");
				continue;
			}
			else
			{
				perror("sendto failed");
				goto EXIT;
			}
		}
		if (ret == total_packet_len)
			break;

		total_packet_len -= ret;
		buffer += ret;
	}

	EXIT: pthread_mutex_unlock(&tcp_state.session_info.send_fd_lock);
	return ret;
}

static void handle_packet_retransmission()
{
	packet_t* packet = NULL;
	pthread_mutex_lock(&tcp_state.sender_info.tcp_retx_lock);
	int index = tcp_state.sender_info.retx_buffer_head;
	while (index != tcp_state.sender_info.retx_buffer_tail)
	{
		packet = tcp_state.sender_info.retx_buffer[index].packet;
		// 重启重传定时器
		reset_packet_retransmission_timer(&packet->retransmit_timer_id, 0);
		if (send_packet(packet->payload, packet->payload_len) < 0)
			printf("Failed to retransmit packet!!");
		reset_packet_retransmission_timer(&packet->retransmit_timer_id, 60);
		index++;
	}
	pthread_mutex_unlock(&tcp_state.sender_info.tcp_retx_lock);
}

static int send_ack_segment(uint8_t fin)
{
	int ret = -1;
	packet_t* packet = create_packet();
	tcp_flags_t flags =
	{ 0 };

	flags.ack = 1;
	flags.fin = fin;
	build_packet_headers(packet, 0, &flags);

	if ((ret = send_packet(&packet->payload,
			((struct iphdr*) packet->offset[IP_OFFSET])->tot_len)) < 0)
	{
		printf("Send error!! Exiting.. ");
	}

	EXIT: destroy_packet(packet);
	return ret;
}

static int receive_packet(packet_t *packet)
{
	int ret = -1;
	while (1)
	{
		if ((ret = recvfrom(tcp_state.session_info.recv_fd, &packet->payload,
				sizeof(packet->payload), 0,
				NULL, NULL)) < 0)
		{
			if (errno == EINTR)
				continue;
			else
			{
				perror("recv failed");
				return ret;
			}

		}
		//Data received successfully
		struct iphdr *iph = (struct iphdr *) &packet->payload;
		// printf("packet->payload:%sn", packet->payload);
		if (validate_ip_checksum(iph) < 0)
		{
			printf("IP Checksum validation failed!! Packet dropped!!n");
			continue;
		}

		uint16_t iphdr_len = iph->ihl * WORD_LENGTH;
		struct tcphdr *tcph = (struct tcphdr *) ((char*) iph + iphdr_len);
		uint16_t tcphdr_len = tcph->doff * WORD_LENGTH;

		if (iph->saddr != tcp_state.session_info.dst_addr.sin_addr.s_addr
				&& tcph->dest != tcp_state.session_info.src_port
				&& tcph->source != tcp_state.session_info.dst_port)
			continue;

		if (validate_tcp_checksum(tcph,
				(ntohs(iph->tot_len) - iphdr_len - tcphdr_len)) < 0)
		{
			printf("TCP Checksum validation failed!! Packet dropped!!n");
			continue;
		}

		if ( IS_DUPLICATE_ACK(tcph))
		{
			handle_packet_retransmission();
			continue;
		}
		else if ( IS_DUPLICATE_TCP_SEGMENT(tcph))
		{
			send_ack_segment(0);
			continue;
		}

		adjust_layer_offset(packet);
		packet->payload_len = (ntohs(iph->tot_len) - iphdr_len - tcphdr_len);
		// printf("packet->payload_len:%dn", packet->payload_len);
		break;
	}
	return ret;
}

static void process_ack(struct tcphdr *tcph, uint16_t payload_len)
{
	tcp_state.server_next_seq_num = (ntohl(tcph->seq) + payload_len);  // 当前收到的包的序号是seq,长度是payload_len,那么下一个数据包的seq就是ntohl(tcph->seq) + payload_len
	tcp_state.last_acked_seq_num = (ntohl(tcph->ack_seq));  // 下一个发包的seq

	pthread_mutex_lock(&tcp_state.tcp_state_lock);
	tcp_state.server_window_size = ntohs(tcph->window);    // 更新对端接收窗口值
	tcp_state.cwindow_size =
			(++tcp_state.cwindow_size > MAX_CONGESTION_WINDOW_SIZE) ?
					MAX_CONGESTION_WINDOW_SIZE : tcp_state.cwindow_size;
	pthread_cond_signal(&tcp_state.send_window_low_thresh);
	pthread_mutex_unlock(&tcp_state.tcp_state_lock);

	remove_acked_entries(ntohl(tcph->ack_seq));    // 删除已经收到回应的数据包
	// 更新tcp_state.max_segment_size
	if (HAS_TCP_OPTIONS(tcph))
	{
		char* tcp_options_offset = (char*) TCP_OPTION_OFFSET(tcph);
		uint16_t total_options_len = TCP_OPTIONS_LEN(tcph);

		while (!END_OF_TCP_OPTION_CHECK(tcp_options_offset)
				&& total_options_len > 0)
		{
			if ( IS_NO_OPERATION(tcp_options_offset))
			{
				tcp_options_offset++;
				total_options_len--;
			}
			else if ( IS_MSS(tcp_options_offset))
			{
				tcp_state.max_segment_size =
						min(tcp_state.max_segment_size,
								*((uint16_t*)(tcp_options_offset+TCP_OPTION_DATA_OFFSET)));
				tcp_options_offset += OPTION_LENGTH(tcp_options_offset);
				total_options_len -= OPTION_LENGTH(tcp_options_offset);
			}
			else
			{
				tcp_options_offset += OPTION_LENGTH(tcp_options_offset);
				total_options_len -= OPTION_LENGTH(tcp_options_offset);
			}
		}
	}
}

static void retransmission_timer_handler(union sigval value)
{
	int buffer_index = value.sival_int;
	packet_t* packet = NULL;

	pthread_mutex_lock(&tcp_state.tcp_state_lock);
	tcp_state.cwindow_size = 1;
	pthread_mutex_unlock(&tcp_state.tcp_state_lock);

	pthread_mutex_lock(&tcp_state.sender_info.tcp_retx_lock);

	if (tcp_state.sender_info.retx_buffer[buffer_index].packet == NULL
			|| buffer_index < tcp_state.sender_info.retx_buffer_head)
		goto EXIT;

	packet = tcp_state.sender_info.retx_buffer[buffer_index].packet;
	if (send_packet(&packet->payload,
			((struct iphdr*) packet->offset[IP_OFFSET])->tot_len) < 0)
	{
		printf("Failed to retransmit packet!!n");
	}

	EXIT: pthread_mutex_unlock(&tcp_state.sender_info.tcp_retx_lock);
}

void create_retransmission_timer(timer_t* timer, int send_buffer_index)
{
	union sigval val;
	struct sigevent sev;
	struct itimerspec timer_value = {0};

	memset(&val, 0, sizeof(val));
	memset(&sev, 0, sizeof(sev));
	val.sival_int = send_buffer_index;

	// SIGEV_THREAD:当定时器到期,内核会(在此进程内)以sigev_notification_attributes为线程属性创建一个线程,
	// 并且让它执行sigev_notify_function,传入sigev_value作为为一个参数。
	sev.sigev_notify = SIGEV_THREAD;
	sev.sigev_value = val;
	sev.sigev_notify_function = retransmission_timer_handler;    // 定时器到期,重传数据包(即超时重传)

	// 创建定时器
	// CLOCK_MONOTONIC:从系统启动这一刻起开始计时,不受系统时间被用户改变的影响
	if (timer_create(CLOCK_MONOTONIC, &sev, timer) < 0)
	{
		printf("Failed to create the retransmission timer!!");
		*timer = NULL;
		goto EXIT;
	}

	timer_value.it_interval.tv_sec = 60;  // it_interval:定时时间 60s
	timer_value.it_value.tv_sec = 60;     // it_value:单次启动时间 60s

	// 设置定时器
	if (timer_settime(*timer, 0, &timer_value, NULL) < 0)
	{
		printf("Failed to set time!!");
		timer_delete(*timer);
		*timer = NULL;
	}

	EXIT: return;
}

static int send_tcp_segment(packet_t* packet)
{
	int ret = 0;

	if ((ret = send_packet(&packet->payload,
			((struct iphdr*) packet->offset[IP_OFFSET])->tot_len)) < 0)
	{
		printf("Send error!! Exiting.. ");
		goto EXIT;
	}
	// 创建重传定时器,超时重传数据包 NULL 0
	create_retransmission_timer(&packet->retransmit_timer_id,
			tcp_state.sender_info.retx_buffer_tail);

	pthread_mutex_lock(&tcp_state.sender_info.tcp_retx_lock);

	// 数据包写入发送循环队列
	tcp_state.sender_info.retx_buffer[tcp_state.sender_info.retx_buffer_tail].packet_seq =
			((struct tcphdr*) &packet->offset[TCP_OFFSET])->seq;
	tcp_state.sender_info.retx_buffer[tcp_state.sender_info.retx_buffer_tail].packet =
			packet;
	// 发送尾指针加一,指向下一个空队列空间
	tcp_state.sender_info.retx_buffer_tail =
	WRAP_ROUND_BUFFER_SIZE(tcp_state.sender_info.retx_buffer_tail);

	pthread_mutex_unlock(&tcp_state.sender_info.tcp_retx_lock);

	EXIT: return ret;
}

static int send_syn()
{
	int ret = -1;
	packet_t* packet = create_packet();
	tcp_flags_t flags = {0};

	flags.syn = 1;
	build_packet_headers(packet, 0, &flags);
	tcp_state.tcp_current_state = SYN_SENT;

	return send_tcp_segment(packet);
}

static int receive_syn_ack_segment(tcp_flags_t* flags)
{
	int ret = -1;
	packet_t* packet = create_packet();
	struct tcphdr *tcph;

	while (1)
	{
		if ((ret = receive_packet(packet)) < 0)
		{
			printf("Receive error!! Exiting.. ");
			goto EXIT;
		}

		tcph = (struct tcphdr *) packet->offset[TCP_OFFSET];

		if (tcph->ack == flags->ack && tcph->syn == flags->syn)
			break;

		if (tcph->rst || !tcp_state.syn_retries)
		{
			ret = -1;
			goto EXIT;
		}
	}

	process_ack(tcph, 1);

	EXIT: destroy_packet(packet);
	return ret;
}

static int initialize_mutex(pthread_mutex_t* mutex)
{
	int ret = -1;
	pthread_mutexattr_t mutex_attr;

	if ((ret = pthread_mutexattr_init(&mutex_attr)) != 0)
	{
		printf("Failed to initialize mutex attributen");
		ret = -1;
		goto EXIT;
	}

	if ((ret = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE))
			!= 0)
	{
		printf("Failed to set mutex attributen");
		ret = -1;
		goto EXIT;
	}

	if ((ret = pthread_mutex_init(mutex, &mutex_attr)) != 0)
	{
		printf("Failed to initialize mutex!!n");
		ret = -1;
	}

	EXIT: return ret;
}

static void get_wait_time(struct timespec* timeToWait, uint16_t timeInSeconds)
{
	struct timeval now;
	int rt;

	gettimeofday(&now, NULL);

	timeToWait->tv_sec = now.tv_sec + timeInSeconds;
	timeToWait->tv_nsec = 0;
}

//Blocking call
int connect_tcp(int send_fd, int recv_fd, struct sockaddr_in* dst_addr,
		struct sockaddr_in* src_addr)
{
	int ret = 0;

// Initialize the TCP Session State with the given details
	bzero(&tcp_state, sizeof(tcp_state__t));
	tcp_state.max_segment_size = MAX_CLIENT_SEGMENT_SIZE;    // 初始化MSS
	tcp_state.client_window_size = CLIENT_WINDOW_SIZE;       // 初始化拥塞窗口
	tcp_state.client_next_seq_num = STARTING_SEQUENCE;       // 客户端下个包的seq
	tcp_state.session_info.dst_addr = *dst_addr;             // 目的地址
	tcp_state.session_info.src_addr = *src_addr;             // 源地址
	tcp_state.session_info.recv_fd = recv_fd;                // 接收句柄
	tcp_state.session_info.send_fd = send_fd;                // 发送句柄
	tcp_state.syn_retries = 5;                               // 重传次数
	tcp_state.cwindow_size = 1;    // 拥塞窗口值
	initialize_mutex(&tcp_state.tcp_state_lock);
	initialize_mutex(&tcp_state.session_info.send_fd_lock);

	tcp_flags_t flags = {0};
	flags.ack = 1;
	flags.syn = 1;
	if (((ret = send_syn()) < 0) || ((ret = receive_syn_ack_segment(&flags)) < 0)
	                             || ((ret = send_ack_segment(0)) < 0))
	{
		printf("Failed to set up TCP Connection!!");
		ret = -1;
		goto EXIT;
	}
	tcp_state.tcp_current_state = ESTABLISHED;

	EXIT: return ret;
}

static int send_fin()
{
	int ret = -1;
	packet_t* packet = create_packet();
	tcp_flags_t flags = {0};

	flags.fin = 1;
	flags.ack = 1;
	build_packet_headers(packet, 0, &flags);

	return send_tcp_segment(packet);
}

int close_tcp()
{
	int ret = -1;
	pthread_mutex_lock(&tcp_state.tcp_state_lock);
	if (!((tcp_state.tcp_current_state & ESTABLISHED)
			|| (tcp_state.tcp_current_state & CLOSE_WAIT)))
	{
		pthread_mutex_unlock(&tcp_state.tcp_state_lock);
		goto EXIT;
	}
	pthread_mutex_unlock(&tcp_state.tcp_state_lock);

	if ((ret = send_fin()) < 0)
		goto EXIT;

	struct timespec timeToWait;
	get_wait_time(&timeToWait, 10);

	pthread_mutex_lock(&tcp_state.tcp_state_lock);

	if (tcp_state.tcp_current_state & ESTABLISHED)
		tcp_state.tcp_current_state = FIN_WAIT_1;
	else
		tcp_state.tcp_current_state = LAST_ACK;

	tcp_state.tcp_write_end_closed = 1;
	pthread_cond_timedwait(&tcp_state.tcp_session_closed_notify,
			&tcp_state.tcp_state_lock, &timeToWait);

	pthread_mutex_unlock(&tcp_state.tcp_state_lock);

	EXIT: return ret;
}

static void release_and_update_recv_buffer(packet_t* packet)
{
	pthread_mutex_lock(&tcp_state.recv_info.tcp_recv_lock);

	tcp_state.recv_info.recv_buffer[tcp_state.recv_info.recv_buffer_head].packet =
	NULL;
	tcp_state.recv_info.recv_buffer_head =
	WRAP_ROUND_BUFFER_SIZE(tcp_state.recv_info.recv_buffer_head);
	destroy_packet(packet);
	pthread_cond_signal(&tcp_state.recv_info.recv_buffer_full);

	pthread_mutex_unlock(&tcp_state.recv_info.tcp_recv_lock);

}

int receive_data(char* buffer, int buffer_len)
{
	int total_bytes_read = 0, ret = -1;
	packet_t* packet = NULL;
	struct timespec timeToWait;

	while (buffer_len > 0)
	{
		get_wait_time(&timeToWait, 5);

		pthread_mutex_lock(&tcp_state.recv_info.tcp_recv_lock);
		if (tcp_state.recv_info.recv_buffer_head
				== tcp_state.recv_info.recv_buffer_tail)
		{
			if (total_bytes_read > 0)
			{
				pthread_mutex_unlock(&tcp_state.recv_info.tcp_recv_lock);
				break;
			}
			else
			{
				if ((ret = pthread_cond_timedwait(
						&tcp_state.recv_info.recv_buffer_empty,
						&tcp_state.recv_info.tcp_recv_lock, &timeToWait)) != 0)
				{
					pthread_mutex_unlock(&tcp_state.recv_info.tcp_recv_lock);
					if (ret == ETIMEDOUT)
					{
						pthread_mutex_lock(&tcp_state.tcp_state_lock);
						if (tcp_state.tcp_read_end_closed)
						{
							printf("TCP Server Closed!!n");
							total_bytes_read = -1;
							pthread_mutex_unlock(&tcp_state.tcp_state_lock);
							break;
						}
						pthread_mutex_unlock(&tcp_state.tcp_state_lock);
						continue;
					}
					else
						break;
				}
			}
		}

		packet =
				tcp_state.recv_info.recv_buffer[tcp_state.recv_info.recv_buffer_head].packet;
		pthread_mutex_unlock(&tcp_state.recv_info.tcp_recv_lock);

		int copied_bytes = 0;
		if (packet->payload_len > buffer_len)
		{
			printf("CHUNKED TRANSFER: %d:%dn", packet->payload_len,
					buffer_len);
			memcpy((buffer + total_bytes_read), packet->offset[DATA_OFFSET],
					buffer_len);
			packet->offset[DATA_OFFSET] += buffer_len;
			packet->payload_len -= buffer_len;
			total_bytes_read += buffer_len;
			copied_bytes = buffer_len;
			buffer_len = 0;
		}
		else
		{
			memcpy((buffer + total_bytes_read), packet->offset[DATA_OFFSET],
					packet->payload_len);
			buffer_len -= packet->payload_len;
			total_bytes_read += packet->payload_len;
			copied_bytes = packet->payload_len;
			release_and_update_recv_buffer(packet);
		}

		pthread_mutex_lock(&tcp_state.tcp_state_lock);
		tcp_state.client_window_size += copied_bytes;
		tcp_state.client_window_size =
				(tcp_state.client_window_size > CLIENT_WINDOW_SIZE) ?
						CLIENT_WINDOW_SIZE : tcp_state.client_window_size;
		pthread_mutex_unlock(&tcp_state.tcp_state_lock);
	}

	return total_bytes_read;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492
  • 493
  • 494
  • 495
  • 496
  • 497
  • 498
  • 499
  • 500
  • 501
  • 502
  • 503
  • 504
  • 505
  • 506
  • 507
  • 508
  • 509
  • 510
  • 511
  • 512
  • 513
  • 514
  • 515
  • 516
  • 517
  • 518
  • 519
  • 520
  • 521
  • 522
  • 523
  • 524
  • 525
  • 526
  • 527
  • 528
  • 529
  • 530
  • 531
  • 532
  • 533
  • 534
  • 535
  • 536
  • 537
  • 538
  • 539
  • 540
  • 541
  • 542
  • 543
  • 544
  • 545
  • 546
  • 547
  • 548
  • 549
  • 550
  • 551
  • 552
  • 553
  • 554
  • 555
  • 556
  • 557
  • 558
  • 559
  • 560
  • 561
  • 562
  • 563
  • 564
  • 565
  • 566
  • 567
  • 568
  • 569
  • 570
  • 571
  • 572
  • 573
  • 574
  • 575
  • 576
  • 577
  • 578
  • 579
  • 580
  • 581
  • 582
  • 583
  • 584
  • 585
  • 586
  • 587
  • 588
  • 589
  • 590
  • 591
  • 592
  • 593
  • 594
  • 595
  • 596
  • 597
  • 598
  • 599
  • 600
  • 601
  • 602
  • 603
  • 604
  • 605
  • 606
  • 607
  • 608
  • 609
  • 610
  • 611
  • 612
  • 613
  • 614
  • 615
  • 616
  • 617
  • 618
  • 619
  • 620
  • 621
  • 622
  • 623
  • 624
  • 625
  • 626
  • 627
  • 628
  • 629
  • 630
  • 631
  • 632
  • 633
  • 634
  • 635
  • 636
  • 637
  • 638
  • 639
  • 640
  • 641
  • 642
  • 643
  • 644
  • 645
  • 646
  • 647
  • 648
  • 649
  • 650
  • 651
  • 652
  • 653
  • 654
  • 655
  • 656
  • 657
  • 658
  • 659
  • 660
  • 661
  • 662
  • 663
  • 664
  • 665
  • 666
  • 667
  • 668
  • 669
  • 670
  • 671
  • 672
  • 673
  • 674
  • 675
  • 676
  • 677
  • 678
  • 679
  • 680
  • 681
  • 682
  • 683
  • 684
  • 685
  • 686
  • 687
  • 688
  • 689
  • 690
  • 691
  • 692
  • 693
  • 694
  • 695
  • 696
  • 697
  • 698
  • 699
  • 700
  • 701
  • 702
  • 703
  • 704
  • 705
  • 706
  • 707
  • 708
  • 709
  • 710
  • 711
  • 712
  • 713
  • 714
  • 715
  • 716
  • 717
  • 718
  • 719
  • 720
  • 721
  • 722
  • 723
  • 724
  • 725
  • 726
  • 727
  • 728
  • 729
  • 730
  • 731
  • 732
  • 733
  • 734
  • 735
  • 736
  • 737
  • 738
  • 739
  • 740
  • 741
  • 742
  • 743
  • 744
  • 745
  • 746
  • 747
  • 748
  • 749
  • 750
  • 751
  • 752
  • 753
  • 754
  • 755
  • 756
  • 757
  • 758
  • 759
  • 760
  • 761
  • 762
  • 763
  • 764
  • 765
  • 766
  • 767
  • 768
  • 769
  • 770
  • 771
  • 772
  • 773
  • 774
  • 775

tcp_handler.h

#ifndef TCP_HANDLER_H_
#define TCP_HANDLER_H_

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <string.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>

#define TOTAL_LAYERS  2
#define IP_LAYER_OFFSET  0
#define TCP_LAYER_OFFSET 1
#define PAYLOAD_OFFSET 2
#define CLIENT_PORT 35555
#define HTTP_PORT 80
#define RTAX_MAX 8
#define IP_OFFSET 0
#define TCP_OFFSET 1
#define DATA_OFFSET 2
#define MAX_BUFFER_SIZE 400
#define MAX_CLIENT_SEGMENT_SIZE 1460
// #define CLIENT_WINDOW_SIZE 16384
#define CLIENT_WINDOW_SIZE 12000
#define WORD_LENGTH 4
// #define PACKET_MAX_SIZE 16384
#define PACKET_MAX_SIZE 12000
#define MAX_PAYLOAD_LEN (PACKET_MAX_SIZE - sizeof(struct iphdr) - sizeof(struct tcphdr))
#define MAX_CONGESTION_WINDOW_SIZE 1000

typedef enum
{
	SYN_SENT = 1,
	ESTABLISHED = 2,
	FIN_WAIT_1 = 4,
	FIN_WAIT_2 = 8,
	CLOSE_WAIT = 16,
	CLOSING = 32,
	LAST_ACK = 64,
	CLOSED = 128
} tcp_state_machine_t;

typedef struct
{
	uint8_t syn :1;
	uint8_t ack :1;
	uint8_t fin :1;
	uint8_t psh :1;
} tcp_flags_t;

typedef struct
{
	uint8_t option_type;
	uint8_t option_len;
	uint16_t option_value;
} tcp_options_t;

typedef struct
{
	char payload[PACKET_MAX_SIZE];
	char* offset[TOTAL_LAYERS + 1];
	timer_t retransmit_timer_id;
	uint16_t payload_len;
} packet_t;

typedef struct
{
	packet_t* packet;
	uint32_t packet_seq;
} buffered_packet_t;

// TCP 伪首部
typedef struct
{
	u_int32_t source_address;
	u_int32_t dest_address;
	u_int8_t placeholder;
	u_int8_t protocol;
	u_int16_t tcp_length;
} pseudo_header;

typedef struct
{
	struct sockaddr_in src_addr;
	struct sockaddr_in dst_addr;
	uint16_t src_port;
	uint16_t dst_port;
	int send_fd;
	int recv_fd;
	pthread_mutex_t send_fd_lock;
} session_info__t;

typedef struct
{
	buffered_packet_t send_buffer[MAX_BUFFER_SIZE];
	uint16_t send_buffer_head;
	uint16_t send_buffer_tail;
	buffered_packet_t retx_buffer[MAX_BUFFER_SIZE];
	uint16_t retx_buffer_head;
	uint16_t retx_buffer_tail;
	pthread_mutex_t tcp_send_lock;
	pthread_mutex_t tcp_retx_lock;
	pthread_cond_t send_buffer_empty;
	pthread_cond_t send_buffer_full;
} tcp_send_data_t;

typedef struct
{
	buffered_packet_t recv_buffer[MAX_BUFFER_SIZE];
	uint16_t recv_buffer_head;
	uint16_t recv_buffer_tail;
	pthread_mutex_t tcp_recv_lock;
	pthread_cond_t recv_buffer_empty;
	pthread_cond_t recv_buffer_full;
} tcp_recv_data_t;

typedef struct
{
	session_info__t session_info;
	uint32_t client_next_seq_num;    // 本端发送的下一个数据包的seq
	uint32_t last_acked_seq_num;     // (相对的)三次回应包的seq
	uint32_t server_next_seq_num;    // 对端下一个包的seq(即希望对方下一个包的数据是从第seq开始的)
	uint16_t server_window_size;
	uint16_t client_window_size;
	uint16_t max_segment_size;
	uint16_t cwindow_size;
	uint16_t ssthresh;
	pthread_cond_t send_window_low_thresh;
	uint8_t syn_retries;
	tcp_send_data_t sender_info;
	tcp_recv_data_t recv_info;
	pthread_mutex_t tcp_state_lock;
	pthread_cond_t tcp_session_closed_notify;
	uint8_t tcp_write_end_closed;
	uint8_t tcp_read_end_closed;
	pthread_t tcp_worker_threads[2];
	tcp_state_machine_t tcp_current_state;
} tcp_state__t;

int connect_tcp(int send_fd, int recv_fd, struct sockaddr_in* dst_addr,
		struct sockaddr_in* src_addr);

int send_data(char* buffer, int buffer_len);

int receive_data(char* buffer, int buffer_len);

int close_tcp();

#endif /* TCP_HANDLER_H_ */

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160

Αναφορά για αυτόν τον κωδικό: https://github.com/praveenkmurthy/Raw-Sockets