Browse Source

Split TCP code out into proto/tcp.c

tags/v0.9.3
Michael Brown 19 years ago
parent
commit
a918abc036
4 changed files with 295 additions and 301 deletions
  1. 1
    297
      src/core/nic.c
  2. 2
    0
      src/include/ip.h
  3. 6
    4
      src/include/tcp.h
  4. 286
    0
      src/proto/tcp.c

+ 1
- 297
src/core/nic.c View File

@@ -219,7 +219,6 @@ static int rarp(void);
219 219
 #else
220 220
 static int bootp(void);
221 221
 #endif
222
-static unsigned short tcpudpchksum(struct iphdr *ip);
223 222
 
224 223
 
225 224
 /*
@@ -320,9 +319,6 @@ static int nic_load ( struct type_dev *type_dev,
320 319
 	char	*kernel;
321 320
 
322 321
 	/* Now use TFTP to load file */
323
-#ifdef	DOWNLOAD_PROTO_NFS
324
-	rpc_init();
325
-#endif
326 322
 	kernel = KERNEL_BUF[0] == '\0' ? 
327 323
 #ifdef	DEFAULT_BOOTFILE
328 324
 		DEFAULT_BOOTFILE
@@ -529,29 +525,6 @@ void build_udp_hdr(unsigned long destip,
529 525
 		udp->chksum = 0xffff;
530 526
 }
531 527
 
532
-#ifdef DOWNLOAD_PROTO_HTTP
533
-void build_tcp_hdr(unsigned long destip, unsigned int srcsock,
534
-		  unsigned int destsock, long send_seq, long recv_seq,
535
-		  int window, int flags, int ttl, int len, const void *buf)
536
-{
537
-       struct iphdr *ip;
538
-       struct tcphdr *tcp;
539
-       ip = (struct iphdr *)buf;
540
-       build_ip_hdr(destip, ttl, IP_TCP, 0, len, buf);
541
-       tcp = (struct tcphdr *)(ip + 1);
542
-       tcp->src = htons(srcsock);
543
-       tcp->dst = htons(destsock);
544
-       tcp->seq = htonl(send_seq);
545
-       tcp->ack = htonl(recv_seq);
546
-       tcp->ctrl = htons(flags + (5 << 12)); /* No TCP options */
547
-       tcp->window = htons(window);
548
-       tcp->chksum = 0;
549
-       if ((tcp->chksum = tcpudpchksum(ip)) == 0)
550
-	       tcp->chksum = 0xffff;
551
-}
552
-#endif
553
-
554
-
555 528
 /**************************************************************************
556 529
 UDP_TRANSMIT - Send an UDP datagram
557 530
 **************************************************************************/
@@ -562,37 +535,6 @@ int udp_transmit(unsigned long destip, unsigned int srcsock,
562 535
 	return ip_transmit(len, buf);
563 536
 }
564 537
 
565
-/**************************************************************************
566
-TCP_TRANSMIT - Send a TCP packet
567
-**************************************************************************/
568
-#ifdef DOWNLOAD_PROTO_HTTP
569
-int tcp_transmit(unsigned long destip, unsigned int srcsock,
570
-		unsigned int destsock, long send_seq, long recv_seq,
571
-		int window, int flags, int len, const void *buf)
572
-{
573
-       build_tcp_hdr(destip, srcsock, destsock, send_seq, recv_seq,
574
-		     window, flags, 60, len, buf);
575
-       return ip_transmit(len, buf);
576
-}
577
-
578
-int tcp_reset(struct iphdr *ip) {
579
-       struct tcphdr *tcp = (struct tcphdr *)(ip + 1);
580
-       char buf[sizeof(struct iphdr) + sizeof(struct tcphdr)];
581
-
582
-       if (!(tcp->ctrl & htons(RST))) {
583
-	      long seq = ntohl(tcp->seq) + ntohs(ip->len) -
584
-			 sizeof(struct iphdr) -
585
-			 ((ntohs(tcp->ctrl) >> 10) & 0x3C);
586
-	      if (tcp->ctrl & htons(SYN|FIN))
587
-		      seq++;
588
-	      return tcp_transmit(ntohl(ip->src.s_addr),
589
-				  ntohs(tcp->dst), ntohs(tcp->src),
590
-				  tcp->ctrl&htons(ACK) ? ntohl(tcp->ack) : 0,
591
-				  seq, TCP_MAX_WINDOW, RST, sizeof(buf), buf);
592
-       }
593
-       return (1);
594
-}
595
-#endif
596 538
 
597 539
 /**************************************************************************
598 540
 QDRAIN - clear the nic's receive queue
@@ -616,9 +558,6 @@ void rx_qdrain(void)
616 558
 	await_reply(await_qdrain, 0, NULL, 0);
617 559
 }
618 560
 
619
-#ifdef	DOWNLOAD_PROTO_TFTP
620
-#endif	/* DOWNLOAD_PROTO_TFTP */
621
-
622 561
 #ifdef	RARP_NOT_BOOTP
623 562
 /**************************************************************************
624 563
 RARP - Get my IP address and load information
@@ -876,7 +815,7 @@ static int bootp(void)
876 815
 }
877 816
 #endif	/* RARP_NOT_BOOTP */
878 817
 
879
-static uint16_t tcpudpchksum(struct iphdr *ip)
818
+uint16_t tcpudpchksum(struct iphdr *ip)
880 819
 {
881 820
 	struct udp_pseudo_hdr pseudo;
882 821
 	uint16_t checksum;
@@ -1034,239 +973,6 @@ void join_group(int slot, unsigned long group)
1034 973
 
1035 974
 #include "proto_eth_slow.c"
1036 975
 
1037
-/**************************************************************************
1038
-TCP - Simple-minded TCP stack. Can only send data once and then
1039
-      receive the response. The algorithm for computing window
1040
-      sizes and delaying ack's is currently broken, and thus
1041
-      disabled. Performance would probably improve a little, if
1042
-      this gets fixed. FIXME
1043
-**************************************************************************/
1044
-#ifdef DOWNLOAD_PROTO_HTTP
1045
-static int await_tcp(int ival, void *ptr, unsigned short ptype __unused,
1046
-		    struct iphdr *ip, struct udphdr *udp __unused,
1047
-		    struct tcphdr *tcp)
1048
-{
1049
-       if (!tcp) {
1050
-	       return 0;
1051
-       }
1052
-       if (arptable[ARP_CLIENT].ipaddr.s_addr != ip->dest.s_addr)
1053
-	       return 0;
1054
-       if (ntohs(tcp->dst) != ival) {
1055
-	       tcp_reset(ip);
1056
-	       return 0;
1057
-       }
1058
-       *(void **)ptr = tcp;
1059
-       return 1;
1060
-}
1061
-
1062
-int tcp_transaction(unsigned long destip, unsigned int destsock, void *ptr,
1063
-		   int (*send)(int len, void *buf, void *ptr),
1064
-		   int (*recv)(int len, const void *buf, void *ptr)) {
1065
-       static uint16_t srcsock = 0;
1066
-       int	       rc = 1;
1067
-       long	       send_seq = currticks();
1068
-       long	       recv_seq = 0;
1069
-       int	       can_send = 0;
1070
-       int	       sent_all = 0;
1071
-       struct iphdr   *ip;
1072
-       struct tcphdr  *tcp;
1073
-       int	       ctrl = SYN;
1074
-       char	       buf[128]; /* Small outgoing buffer */
1075
-       long	       payload;
1076
-       int	       header_size;
1077
-       int	       window = 3*TCP_MIN_WINDOW;
1078
-       long	       last_ack = 0;
1079
-       long	       last_sent = 0;
1080
-       long	       rtt = 0;
1081
-       long	       srtt = 0;
1082
-       long	       rto = TCP_INITIAL_TIMEOUT;
1083
-       int	       retry = TCP_MAX_TIMEOUT/TCP_INITIAL_TIMEOUT;
1084
-       enum { CLOSED, SYN_RCVD, ESTABLISHED,
1085
-	      FIN_WAIT_1, FIN_WAIT_2 } state = CLOSED;
1086
-
1087
-       if (!srcsock) {
1088
-	       srcsock = currticks();
1089
-       }
1090
-       if (++srcsock < 1024)
1091
-	       srcsock += 1024;
1092
-
1093
-       await_reply(await_qdrain, 0, NULL, 0);
1094
-
1095
- send_data:
1096
-       if (ctrl & ACK)
1097
-	       last_ack = recv_seq;
1098
-       if (!tcp_transmit(destip, srcsock, destsock, send_seq,
1099
-			 recv_seq, window, ctrl,
1100
-			 sizeof(struct iphdr) + sizeof(struct tcphdr)+
1101
-			 can_send, buf)) {
1102
-	       return (0);
1103
-       }
1104
-       last_sent = currticks();
1105
-
1106
- recv_data:
1107
-       if (!await_reply(await_tcp, srcsock, &tcp,
1108
-			(state == ESTABLISHED && !can_send)
1109
-			? TCP_MAX_TIMEOUT : rto)) {
1110
-	       if (state == ESTABLISHED) {
1111
- close:
1112
-		       ctrl = FIN|ACK;
1113
-		       state = FIN_WAIT_1;
1114
-		       rc = 0;
1115
-		       goto send_data;
1116
-	       }
1117
-
1118
-	       if (state == FIN_WAIT_1 || state == FIN_WAIT_2)
1119
-		       return (rc);
1120
-
1121
-	       if (--retry <= 0) {
1122
-		       /* time out */
1123
-		       if (state == SYN_RCVD) {
1124
-			       tcp_transmit(destip, srcsock, destsock,
1125
-					    send_seq, 0, window, RST,
1126
-					    sizeof(struct iphdr) +
1127
-					    sizeof(struct tcphdr), buf);
1128
-		       }
1129
-		       return (0);
1130
-	       }
1131
-	       /* retransmit */
1132
-	       goto send_data;
1133
-       }
1134
- got_data:
1135
-       retry = TCP_MAX_RETRY;
1136
-
1137
-       if (tcp->ctrl & htons(ACK) ) {
1138
-	       char *data;
1139
-	       int syn_ack, consumed;
1140
-
1141
-	       if (state == FIN_WAIT_1 || state == FIN_WAIT_2) {
1142
-		       state = FIN_WAIT_2;
1143
-		       ctrl = ACK;
1144
-		       goto consume_data;
1145
-	       }
1146
-	       syn_ack = state == CLOSED || state == SYN_RCVD;
1147
-	       consumed = ntohl(tcp->ack) - send_seq - syn_ack;
1148
-	       if (consumed < 0 || consumed > can_send) {
1149
-		       tcp_reset((struct iphdr *)&nic.packet[ETH_HLEN]);
1150
-		       goto recv_data;
1151
-	       }
1152
-
1153
-	       rtt = currticks() - last_sent;
1154
-	       srtt = !srtt ? rtt : (srtt*4 + rtt)/5;
1155
-	       rto = srtt + srtt/2;
1156
-	       if (rto < TCP_MIN_TIMEOUT)
1157
-		       rto = TCP_MIN_TIMEOUT;
1158
-	       else if (rto > TCP_MAX_TIMEOUT)
1159
-		       rto = TCP_MAX_TIMEOUT;
1160
-
1161
-	       can_send -= consumed;
1162
-	       send_seq += consumed + syn_ack;
1163
-	       data = buf + sizeof(struct iphdr) + sizeof(struct tcphdr);
1164
-	       if (can_send) {
1165
-		       memmove(data, data + consumed, can_send);
1166
-	       }
1167
-	       if (!sent_all) {
1168
-		       int more_data;
1169
-		       data += can_send;
1170
-		       more_data = buf + sizeof(buf) - data;
1171
-		       if (more_data > 0) {
1172
-			       more_data = send(more_data, data, ptr);
1173
-			       can_send += more_data;
1174
-		       }
1175
-		       sent_all = !more_data;
1176
-	       }
1177
-	       if (state == SYN_RCVD) {
1178
-		       state = ESTABLISHED;
1179
-		       ctrl = PSH|ACK;
1180
-		       goto consume_data;
1181
-	       }
1182
-	       if (tcp->ctrl & htons(RST))
1183
-		       return (0);
1184
-       } else if (tcp->ctrl & htons(RST)) {
1185
-	       if (state == CLOSED)
1186
-		       goto recv_data;
1187
-	       return (0);
1188
-       }
1189
-
1190
- consume_data:
1191
-       ip  = (struct iphdr *)&nic.packet[ETH_HLEN];
1192
-       header_size = sizeof(struct iphdr) + ((ntohs(tcp->ctrl)>>10)&0x3C);
1193
-       payload = ntohs(ip->len) - header_size;
1194
-       if (payload > 0 && state == ESTABLISHED) {
1195
-	       int old_bytes = recv_seq - (long)ntohl(tcp->seq);
1196
-	       if (old_bytes >= 0 && payload - old_bytes > 0) {
1197
-		       recv_seq += payload - old_bytes;
1198
-		       if (state != FIN_WAIT_1 && state != FIN_WAIT_2 &&
1199
-			   !recv(payload - old_bytes,
1200
-				 &nic.packet[ETH_HLEN+header_size+old_bytes],
1201
-				 ptr)) {
1202
-			       goto close;
1203
-		       }
1204
-		       if ((state == ESTABLISHED || state == SYN_RCVD) &&
1205
-			   !(tcp->ctrl & htons(FIN))) {
1206
-			       int in_window = window - 2*TCP_MIN_WINDOW >
1207
-						recv_seq - last_ack;
1208
-			       ctrl = can_send ? PSH|ACK : ACK;
1209
-			       if (!can_send && in_window) {
1210
-/* Window scaling is broken right now, just fall back to acknowledging every */
1211
-/* packet immediately and unconditionally. FIXME		       */ /***/
1212
-/*				       if (await_reply(await_tcp, srcsock,
1213
-						       &tcp, rto))
1214
-					       goto got_data;
1215
-				       else */
1216
-					       goto send_data;
1217
-			       }
1218
-			       if (!in_window) {
1219
-				       window += TCP_MIN_WINDOW;
1220
-				       if (window > TCP_MAX_WINDOW)
1221
-					       window = TCP_MAX_WINDOW;
1222
-			       }
1223
-			       goto send_data;
1224
-		       }
1225
-	       } else {
1226
-		       /* saw old data again, must have lost packets */
1227
-		       window /= 2;
1228
-		       if (window < 2*TCP_MIN_WINDOW)
1229
-			       window = 2*TCP_MIN_WINDOW;
1230
-	       }
1231
-       }
1232
-
1233
-       if (tcp->ctrl & htons(FIN)) {
1234
-	       if (state == ESTABLISHED) {
1235
-		       ctrl = FIN|ACK;
1236
-	       } else if (state == FIN_WAIT_1 || state == FIN_WAIT_2) {
1237
-		       ctrl = ACK;
1238
-	       } else {
1239
-		       ctrl = RST;
1240
-	       }
1241
-	       return (tcp_transmit(destip, srcsock, destsock,
1242
-				    send_seq, recv_seq + 1, window, ctrl,
1243
-				    sizeof(struct iphdr) +
1244
-				    sizeof(struct tcphdr), buf) &&
1245
-		       (state == ESTABLISHED ||
1246
-			state == FIN_WAIT_1 || state == FIN_WAIT_2) &&
1247
-		       !can_send);
1248
-       }
1249
-
1250
-       if (state == CLOSED) {
1251
-	       if (tcp->ctrl & htons(SYN)) {
1252
-		       recv_seq = ntohl(tcp->seq) + 1;
1253
-		       if (!(tcp->ctrl & htons(ACK))) {
1254
-			       state = SYN_RCVD;
1255
-			       ctrl = SYN|ACK|PSH;
1256
-			       goto send_data;
1257
-		       } else {
1258
-			       state = ESTABLISHED;
1259
-			       ctrl = PSH|ACK;
1260
-		       }
1261
-	       }
1262
-       }
1263
-
1264
-       if (can_send || payload) {
1265
-	       goto send_data;
1266
-       }
1267
-       goto recv_data;
1268
-}
1269
-#endif
1270 976
 
1271 977
 /**************************************************************************
1272 978
 AWAIT_REPLY - Wait until we get a response for our request
@@ -1361,7 +1067,6 @@ int await_reply(reply_t reply, int ival, void *ptr, long timeout)
1361 1067
 			}
1362 1068
 		}
1363 1069
 		tcp = 0;
1364
-#ifdef DOWNLOAD_PROTO_HTTP
1365 1070
 		if (ip && (ip->protocol == IP_TCP) &&
1366 1071
 		    (nic.packetlen >=
1367 1072
 		     ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr))){
@@ -1377,7 +1082,6 @@ int await_reply(reply_t reply, int ival, void *ptr, long timeout)
1377 1082
 			}
1378 1083
 
1379 1084
 		}
1380
-#endif
1381 1085
 		result = reply(ival, ptr, ptype, ip, udp, tcp);
1382 1086
 		if (result > 0) {
1383 1087
 			return result;

+ 2
- 0
src/include/ip.h View File

@@ -18,4 +18,6 @@ struct iphdr {
18 18
 	struct in_addr dest;
19 19
 } PACKED;
20 20
 
21
+extern uint16_t tcpudpchksum(struct iphdr *ip);
22
+
21 23
 #endif	/* _IP_H */

+ 6
- 4
src/include/tcp.h View File

@@ -9,10 +9,6 @@
9 9
 #define TCP_MIN_WINDOW          (1500-TCP_MAX_HEADER)
10 10
 #define TCP_MAX_WINDOW          (65535-TCP_MAX_HEADER)
11 11
 
12
-
13
-#define MAX_URL                 80
14
-
15
-
16 12
 #define FIN             1
17 13
 #define SYN             2
18 14
 #define RST             4
@@ -32,4 +28,10 @@ struct tcphdr {
32 28
        uint16_t urgent;
33 29
 };
34 30
 
31
+extern int tcp_transaction ( unsigned long destip, unsigned int destsock,
32
+			     void *ptr,
33
+			     int (*send)(int len, void *buf, void *ptr),
34
+			     int (*recv)(int len, const void *buf, void *ptr));
35
+
36
+
35 37
 #endif	/* _TCP_H */

+ 286
- 0
src/proto/tcp.c View File

@@ -0,0 +1,286 @@
1
+#include "etherboot.h"
2
+#include "ip.h"
3
+#include "tcp.h"
4
+
5
+
6
+void build_tcp_hdr(unsigned long destip, unsigned int srcsock,
7
+		  unsigned int destsock, long send_seq, long recv_seq,
8
+		  int window, int flags, int ttl, int len, const void *buf)
9
+{
10
+       struct iphdr *ip;
11
+       struct tcphdr *tcp;
12
+       ip = (struct iphdr *)buf;
13
+       build_ip_hdr(destip, ttl, IP_TCP, 0, len, buf);
14
+       tcp = (struct tcphdr *)(ip + 1);
15
+       tcp->src = htons(srcsock);
16
+       tcp->dst = htons(destsock);
17
+       tcp->seq = htonl(send_seq);
18
+       tcp->ack = htonl(recv_seq);
19
+       tcp->ctrl = htons(flags + (5 << 12)); /* No TCP options */
20
+       tcp->window = htons(window);
21
+       tcp->chksum = 0;
22
+       if ((tcp->chksum = tcpudpchksum(ip)) == 0)
23
+	       tcp->chksum = 0xffff;
24
+}
25
+
26
+/**************************************************************************
27
+TCP_TRANSMIT - Send a TCP packet
28
+**************************************************************************/
29
+int tcp_transmit(unsigned long destip, unsigned int srcsock,
30
+		unsigned int destsock, long send_seq, long recv_seq,
31
+		int window, int flags, int len, const void *buf)
32
+{
33
+       build_tcp_hdr(destip, srcsock, destsock, send_seq, recv_seq,
34
+		     window, flags, 60, len, buf);
35
+       return ip_transmit(len, buf);
36
+}
37
+
38
+int tcp_reset(struct iphdr *ip) {
39
+       struct tcphdr *tcp = (struct tcphdr *)(ip + 1);
40
+       char buf[sizeof(struct iphdr) + sizeof(struct tcphdr)];
41
+
42
+       if (!(tcp->ctrl & htons(RST))) {
43
+	      long seq = ntohl(tcp->seq) + ntohs(ip->len) -
44
+			 sizeof(struct iphdr) -
45
+			 ((ntohs(tcp->ctrl) >> 10) & 0x3C);
46
+	      if (tcp->ctrl & htons(SYN|FIN))
47
+		      seq++;
48
+	      return tcp_transmit(ntohl(ip->src.s_addr),
49
+				  ntohs(tcp->dst), ntohs(tcp->src),
50
+				  tcp->ctrl&htons(ACK) ? ntohl(tcp->ack) : 0,
51
+				  seq, TCP_MAX_WINDOW, RST, sizeof(buf), buf);
52
+       }
53
+       return (1);
54
+}
55
+
56
+/**************************************************************************
57
+TCP - Simple-minded TCP stack. Can only send data once and then
58
+      receive the response. The algorithm for computing window
59
+      sizes and delaying ack's is currently broken, and thus
60
+      disabled. Performance would probably improve a little, if
61
+      this gets fixed. FIXME
62
+**************************************************************************/
63
+static int await_tcp(int ival, void *ptr, unsigned short ptype __unused,
64
+		    struct iphdr *ip, struct udphdr *udp __unused,
65
+		    struct tcphdr *tcp)
66
+{
67
+       if (!tcp) {
68
+	       return 0;
69
+       }
70
+       if (arptable[ARP_CLIENT].ipaddr.s_addr != ip->dest.s_addr)
71
+	       return 0;
72
+       if (ntohs(tcp->dst) != ival) {
73
+	       tcp_reset(ip);
74
+	       return 0;
75
+       }
76
+       *(void **)ptr = tcp;
77
+       return 1;
78
+}
79
+
80
+int tcp_transaction(unsigned long destip, unsigned int destsock, void *ptr,
81
+		   int (*send)(int len, void *buf, void *ptr),
82
+		   int (*recv)(int len, const void *buf, void *ptr)) {
83
+       static uint16_t srcsock = 0;
84
+       int	       rc = 1;
85
+       long	       send_seq = currticks();
86
+       long	       recv_seq = 0;
87
+       int	       can_send = 0;
88
+       int	       sent_all = 0;
89
+       struct iphdr   *ip;
90
+       struct tcphdr  *tcp;
91
+       int	       ctrl = SYN;
92
+       char	       buf[128]; /* Small outgoing buffer */
93
+       long	       payload;
94
+       int	       header_size;
95
+       int	       window = 3*TCP_MIN_WINDOW;
96
+       long	       last_ack = 0;
97
+       long	       last_sent = 0;
98
+       long	       rtt = 0;
99
+       long	       srtt = 0;
100
+       long	       rto = TCP_INITIAL_TIMEOUT;
101
+       int	       retry = TCP_MAX_TIMEOUT/TCP_INITIAL_TIMEOUT;
102
+       enum { CLOSED, SYN_RCVD, ESTABLISHED,
103
+	      FIN_WAIT_1, FIN_WAIT_2 } state = CLOSED;
104
+
105
+       if (!srcsock) {
106
+	       srcsock = currticks();
107
+       }
108
+       if (++srcsock < 1024)
109
+	       srcsock += 1024;
110
+
111
+       rx_qdrain();
112
+
113
+ send_data:
114
+       if (ctrl & ACK)
115
+	       last_ack = recv_seq;
116
+       if (!tcp_transmit(destip, srcsock, destsock, send_seq,
117
+			 recv_seq, window, ctrl,
118
+			 sizeof(struct iphdr) + sizeof(struct tcphdr)+
119
+			 can_send, buf)) {
120
+	       return (0);
121
+       }
122
+       last_sent = currticks();
123
+
124
+ recv_data:
125
+       if (!await_reply(await_tcp, srcsock, &tcp,
126
+			(state == ESTABLISHED && !can_send)
127
+			? TCP_MAX_TIMEOUT : rto)) {
128
+	       if (state == ESTABLISHED) {
129
+ close:
130
+		       ctrl = FIN|ACK;
131
+		       state = FIN_WAIT_1;
132
+		       rc = 0;
133
+		       goto send_data;
134
+	       }
135
+
136
+	       if (state == FIN_WAIT_1 || state == FIN_WAIT_2)
137
+		       return (rc);
138
+
139
+	       if (--retry <= 0) {
140
+		       /* time out */
141
+		       if (state == SYN_RCVD) {
142
+			       tcp_transmit(destip, srcsock, destsock,
143
+					    send_seq, 0, window, RST,
144
+					    sizeof(struct iphdr) +
145
+					    sizeof(struct tcphdr), buf);
146
+		       }
147
+		       return (0);
148
+	       }
149
+	       /* retransmit */
150
+	       goto send_data;
151
+       }
152
+       /* got_data: */
153
+       retry = TCP_MAX_RETRY;
154
+
155
+       if (tcp->ctrl & htons(ACK) ) {
156
+	       char *data;
157
+	       int syn_ack, consumed;
158
+
159
+	       if (state == FIN_WAIT_1 || state == FIN_WAIT_2) {
160
+		       state = FIN_WAIT_2;
161
+		       ctrl = ACK;
162
+		       goto consume_data;
163
+	       }
164
+	       syn_ack = state == CLOSED || state == SYN_RCVD;
165
+	       consumed = ntohl(tcp->ack) - send_seq - syn_ack;
166
+	       if (consumed < 0 || consumed > can_send) {
167
+		       tcp_reset((struct iphdr *)&nic.packet[ETH_HLEN]);
168
+		       goto recv_data;
169
+	       }
170
+
171
+	       rtt = currticks() - last_sent;
172
+	       srtt = !srtt ? rtt : (srtt*4 + rtt)/5;
173
+	       rto = srtt + srtt/2;
174
+	       if (rto < TCP_MIN_TIMEOUT)
175
+		       rto = TCP_MIN_TIMEOUT;
176
+	       else if (rto > TCP_MAX_TIMEOUT)
177
+		       rto = TCP_MAX_TIMEOUT;
178
+
179
+	       can_send -= consumed;
180
+	       send_seq += consumed + syn_ack;
181
+	       data = buf + sizeof(struct iphdr) + sizeof(struct tcphdr);
182
+	       if (can_send) {
183
+		       memmove(data, data + consumed, can_send);
184
+	       }
185
+	       if (!sent_all) {
186
+		       int more_data;
187
+		       data += can_send;
188
+		       more_data = buf + sizeof(buf) - data;
189
+		       if (more_data > 0) {
190
+			       more_data = send(more_data, data, ptr);
191
+			       can_send += more_data;
192
+		       }
193
+		       sent_all = !more_data;
194
+	       }
195
+	       if (state == SYN_RCVD) {
196
+		       state = ESTABLISHED;
197
+		       ctrl = PSH|ACK;
198
+		       goto consume_data;
199
+	       }
200
+	       if (tcp->ctrl & htons(RST))
201
+		       return (0);
202
+       } else if (tcp->ctrl & htons(RST)) {
203
+	       if (state == CLOSED)
204
+		       goto recv_data;
205
+	       return (0);
206
+       }
207
+
208
+ consume_data:
209
+       ip  = (struct iphdr *)&nic.packet[ETH_HLEN];
210
+       header_size = sizeof(struct iphdr) + ((ntohs(tcp->ctrl)>>10)&0x3C);
211
+       payload = ntohs(ip->len) - header_size;
212
+       if (payload > 0 && state == ESTABLISHED) {
213
+	       int old_bytes = recv_seq - (long)ntohl(tcp->seq);
214
+	       if (old_bytes >= 0 && payload - old_bytes > 0) {
215
+		       recv_seq += payload - old_bytes;
216
+		       if (state != FIN_WAIT_1 && state != FIN_WAIT_2 &&
217
+			   !recv(payload - old_bytes,
218
+				 &nic.packet[ETH_HLEN+header_size+old_bytes],
219
+				 ptr)) {
220
+			       goto close;
221
+		       }
222
+		       if ((state == ESTABLISHED || state == SYN_RCVD) &&
223
+			   !(tcp->ctrl & htons(FIN))) {
224
+			       int in_window = window - 2*TCP_MIN_WINDOW >
225
+						recv_seq - last_ack;
226
+			       ctrl = can_send ? PSH|ACK : ACK;
227
+			       if (!can_send && in_window) {
228
+/* Window scaling is broken right now, just fall back to acknowledging every */
229
+/* packet immediately and unconditionally. FIXME		       */ /***/
230
+/*				       if (await_reply(await_tcp, srcsock,
231
+						       &tcp, rto))
232
+					       goto got_data;
233
+				       else */
234
+					       goto send_data;
235
+			       }
236
+			       if (!in_window) {
237
+				       window += TCP_MIN_WINDOW;
238
+				       if (window > TCP_MAX_WINDOW)
239
+					       window = TCP_MAX_WINDOW;
240
+			       }
241
+			       goto send_data;
242
+		       }
243
+	       } else {
244
+		       /* saw old data again, must have lost packets */
245
+		       window /= 2;
246
+		       if (window < 2*TCP_MIN_WINDOW)
247
+			       window = 2*TCP_MIN_WINDOW;
248
+	       }
249
+       }
250
+
251
+       if (tcp->ctrl & htons(FIN)) {
252
+	       if (state == ESTABLISHED) {
253
+		       ctrl = FIN|ACK;
254
+	       } else if (state == FIN_WAIT_1 || state == FIN_WAIT_2) {
255
+		       ctrl = ACK;
256
+	       } else {
257
+		       ctrl = RST;
258
+	       }
259
+	       return (tcp_transmit(destip, srcsock, destsock,
260
+				    send_seq, recv_seq + 1, window, ctrl,
261
+				    sizeof(struct iphdr) +
262
+				    sizeof(struct tcphdr), buf) &&
263
+		       (state == ESTABLISHED ||
264
+			state == FIN_WAIT_1 || state == FIN_WAIT_2) &&
265
+		       !can_send);
266
+       }
267
+
268
+       if (state == CLOSED) {
269
+	       if (tcp->ctrl & htons(SYN)) {
270
+		       recv_seq = ntohl(tcp->seq) + 1;
271
+		       if (!(tcp->ctrl & htons(ACK))) {
272
+			       state = SYN_RCVD;
273
+			       ctrl = SYN|ACK|PSH;
274
+			       goto send_data;
275
+		       } else {
276
+			       state = ESTABLISHED;
277
+			       ctrl = PSH|ACK;
278
+		       }
279
+	       }
280
+       }
281
+
282
+       if (can_send || payload) {
283
+	       goto send_data;
284
+       }
285
+       goto recv_data;
286
+}

Loading…
Cancel
Save