1 | void handle_tcp(uint8_t* data) {
|
2 | EthernetFrame* eth = (EthernetFrame*)(data);
|
3 | TCPHeader* tcp = (TCPHeader*)(data + TCP_HEADER_POS);
|
4 | IPHeader* ip = (IPHeader*)(data + IP_HEADER_POS);
|
5 |
|
6 | // look if this port is registered
|
7 | uint8_t idx, i, len1;
|
8 | if((idx = tcpFindEntry(ntohs(tcp->dst_port))) < MAX_TCP_SOCKETS) {
|
9 |
|
10 | // syn from client
|
11 | if((tcp->flags & TCP_FLAG_MASK) == TCP_SYN && TCPSocket[idx].status == TCP_LISTENING) {
|
12 |
|
13 | TCPSocket[idx].status = TCP_SYN_RECV;
|
14 | TCPSocket[idx].ack_nr = ntohl(tcp->seq_nr) + 1;
|
15 | TCPSocket[idx].seq_nr = network_clock;
|
16 | TCPSocket[idx].src_port = ntohs(tcp->src_port);
|
17 | TCPSocket[idx].window = 384;
|
18 |
|
19 | generateEthernetFrame(send_buffer, eth->MAC_src, 0x0800); // ethernet: ip
|
20 | generateIPHeader(send_buffer + IP_HEADER_POS, ip->ip_src, 0x06, IP_HEADER_LEN + TCP_HEADER_LEN + 4 + 4);
|
21 | generateTCPPacket(send_buffer + TCP_HEADER_POS, idx, 0);
|
22 |
|
23 | // send syn | ack
|
24 | enc28j60PacketSend(MAX(60, ETHERNET_FRAME_LEN + IP_HEADER_LEN + TCP_HEADER_LEN + 4 + 4), send_buffer);
|
25 | return;
|
26 | }
|
27 |
|
28 | // send ack
|
29 | if((tcp->flags & TCP_ACK) && TCPSocket[idx].status == TCP_ESTABLISHED) {
|
30 | uint16_t len = ntohs(ip->ip_len) - IP_HEADER_LEN;
|
31 | len -= tcp->off / 4;
|
32 |
|
33 | TCPSocket[idx].seq_nr = ntohl(tcp->ack_nr);
|
34 | TCPSocket[idx].ack_nr = ntohl(tcp->seq_nr) + len;
|
35 |
|
36 | generateEthernetFrame(send_buffer, eth->MAC_src, 0x0800); // ethernet: ip
|
37 | generateIPHeader(send_buffer + IP_HEADER_POS, ip->ip_src, 0x06, IP_HEADER_LEN + TCP_HEADER_LEN + TSV_LEN);
|
38 | generateTCPPacket(send_buffer + TCP_HEADER_POS, idx, 0);
|
39 |
|
40 | // send ack
|
41 | enc28j60PacketSend(MAX(60, ETHERNET_FRAME_LEN + IP_HEADER_LEN + TCP_HEADER_LEN + TSV_LEN), send_buffer);
|
42 |
|
43 | return;
|
44 | }
|
45 |
|
46 | // ack from client
|
47 | if((tcp->flags & TCP_FLAG_MASK) == TCP_ACK && TCPSocket[idx].status == TCP_SYN_RECV) {
|
48 | TCPSocket[idx].status = TCP_ESTABLISHED;
|
49 | TCPSocket[idx].seq_nr = ntohl(tcp->seq_nr);
|
50 | return;
|
51 | }
|
52 |
|
53 | // end connection
|
54 | if((tcp->flags & TCP_FIN) || (tcp->flags & TCP_RST)) {
|
55 | TCPSocket[idx].status = TCP_LISTENING;
|
56 | return;
|
57 | }
|
58 | }
|
59 | }
|
60 |
|
61 | void generateTCPPacket(uint8_t* data, uint8_t idx, uint16_t length) {
|
62 | TCPHeader* tcp = (TCPHeader*)(data);
|
63 |
|
64 | tcp->src_port = htons(TCPSocket[idx].port);
|
65 | tcp->dst_port = htons(TCPSocket[idx].src_port);
|
66 | tcp->flags = 0;
|
67 | switch(TCPSocket[idx].status) {
|
68 | case TCP_SYN_RECV:
|
69 | tcp->flags = TCP_SYN | TCP_ACK;
|
70 | break;
|
71 |
|
72 | case TCP_ESTABLISHED:
|
73 | tcp->flags = TCP_ACK;
|
74 | break;
|
75 | }
|
76 |
|
77 | tcp->off = 80;
|
78 | tcp->window_size = htons(TCPSocket[idx].window);
|
79 | tcp->urgent_ptr = 0;
|
80 | tcp->checksum = 0;
|
81 | tcp->seq_nr = htonl(TCPSocket[idx].seq_nr);
|
82 | tcp->ack_nr = htonl(TCPSocket[idx].ack_nr);
|
83 |
|
84 | if((TCPSocket[idx].status == TCP_SYN_RECV) ) {
|
85 | data[TCP_HEADER_LEN] = 2;
|
86 | data[TCP_HEADER_LEN + 1] = 4;
|
87 | data[TCP_HEADER_LEN + 2] = (TCP_MSS >> 8) & 0xff;
|
88 | data[TCP_HEADER_LEN + 3] = TCP_MSS & 0xff;
|
89 |
|
90 | data[TCP_HEADER_LEN + 4] = 1; // nop
|
91 | data[TCP_HEADER_LEN + 5] = 3; // windows scale = 0
|
92 | data[TCP_HEADER_LEN + 6] = 3;
|
93 | data[TCP_HEADER_LEN + 7] = 0;
|
94 |
|
95 | tcp->off = 0x60 + 16;
|
96 | length += 4 + 4;
|
97 | }
|
98 |
|
99 | uint16_t data_len = TCP_HEADER_LEN + length + 8;
|
100 | uint32_t start_val = data_len - 2;
|
101 |
|
102 | tcp->checksum = htons(checksum((data - IP_HEADER_LEN + 12), start_val, data_len));
|
103 | }
|