Rev 7974 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 7974 | Rev 8026 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2020. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2020. All rights reserved. ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; ;; |
5 | ;; ;; |
6 | ;; Part of the TCP/IP network stack for KolibriOS ;; |
6 | ;; Part of the TCP/IP network stack for KolibriOS ;; |
7 | ;; ;; |
7 | ;; ;; |
8 | ;; Written by hidnplayr@kolibrios.org ;; |
8 | ;; Written by hidnplayr@kolibrios.org ;; |
9 | ;; ;; |
9 | ;; ;; |
10 | ;; Based on the code of 4.4BSD ;; |
10 | ;; Based on the code of 4.4BSD ;; |
11 | ;; ;; |
11 | ;; ;; |
12 | ;; GNU GENERAL PUBLIC LICENSE ;; |
12 | ;; GNU GENERAL PUBLIC LICENSE ;; |
13 | ;; Version 2, June 1991 ;; |
13 | ;; Version 2, June 1991 ;; |
14 | ;; ;; |
14 | ;; ;; |
15 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
15 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
16 | 16 | ||
17 | $Revision: 7974 $ |
17 | $Revision: 8026 $ |
18 | 18 | ||
19 | align 4 |
19 | align 4 |
20 | iglobal |
20 | iglobal |
21 | TCP_backoff db 0,1,2,3,4,5,6,6,6,6,6,6,6 |
21 | TCP_backoff db 0,1,2,3,4,5,6,6,6,6,6,6,6 |
22 | endg |
22 | endg |
23 | 23 | ||
24 | macro tcp_checksum IP1, IP2 { |
24 | macro tcp_checksum IP1, IP2 { |
25 | 25 | ||
26 | ;------------- |
26 | ;------------- |
27 | ; Pseudoheader |
27 | ; Pseudoheader |
28 | 28 | ||
29 | ; protocol type |
29 | ; protocol type |
30 | mov edx, IP_PROTO_TCP |
30 | mov edx, IP_PROTO_TCP |
31 | 31 | ||
32 | ; source address |
32 | ; source address |
33 | add dl, byte [IP1+1] |
33 | add dl, byte [IP1+1] |
34 | adc dh, byte [IP1+0] |
34 | adc dh, byte [IP1+0] |
35 | adc dl, byte [IP1+3] |
35 | adc dl, byte [IP1+3] |
36 | adc dh, byte [IP1+2] |
36 | adc dh, byte [IP1+2] |
37 | 37 | ||
38 | ; destination address |
38 | ; destination address |
39 | adc dl, byte [IP2+1] |
39 | adc dl, byte [IP2+1] |
40 | adc dh, byte [IP2+0] |
40 | adc dh, byte [IP2+0] |
41 | adc dl, byte [IP2+3] |
41 | adc dl, byte [IP2+3] |
42 | adc dh, byte [IP2+2] |
42 | adc dh, byte [IP2+2] |
43 | 43 | ||
44 | ; size |
44 | ; size |
45 | adc dl, cl |
45 | adc dl, cl |
46 | adc dh, ch |
46 | adc dh, ch |
47 | 47 | ||
48 | adc edx, 0 |
48 | adc edx, 0 |
49 | 49 | ||
50 | ;--------------------- |
50 | ;--------------------- |
51 | ; Real header and data |
51 | ; Real header and data |
52 | 52 | ||
53 | push esi |
53 | push esi |
54 | call checksum_1 |
54 | call checksum_1 |
55 | call checksum_2 |
55 | call checksum_2 |
56 | pop esi |
56 | pop esi |
57 | 57 | ||
58 | } ; returns in dx only |
58 | } ; returns in dx only |
59 | 59 | ||
60 | 60 | ||
61 | 61 | ||
62 | 62 | ||
63 | macro tcp_sendseqinit ptr { |
63 | macro tcp_sendseqinit ptr { |
64 | 64 | ||
65 | push edi ;;;; FIXME: i dont like this static use of edi |
65 | push edi ;;;; FIXME: i dont like this static use of edi |
66 | mov edi, [ptr + TCP_SOCKET.ISS] |
66 | mov edi, [ptr + TCP_SOCKET.ISS] |
67 | mov [ptr + TCP_SOCKET.SND_UP], edi |
67 | mov [ptr + TCP_SOCKET.SND_UP], edi |
68 | mov [ptr + TCP_SOCKET.SND_MAX], edi |
68 | mov [ptr + TCP_SOCKET.SND_MAX], edi |
69 | mov [ptr + TCP_SOCKET.SND_NXT], edi |
69 | mov [ptr + TCP_SOCKET.SND_NXT], edi |
70 | mov [ptr + TCP_SOCKET.SND_UNA], edi |
70 | mov [ptr + TCP_SOCKET.SND_UNA], edi |
71 | pop edi |
71 | pop edi |
72 | 72 | ||
73 | } |
73 | } |
74 | 74 | ||
75 | 75 | ||
76 | 76 | ||
77 | macro tcp_rcvseqinit ptr { |
77 | macro tcp_rcvseqinit ptr { |
78 | 78 | ||
79 | push edi |
79 | push edi |
80 | mov edi, [ptr + TCP_SOCKET.IRS] |
80 | mov edi, [ptr + TCP_SOCKET.IRS] |
81 | inc edi ; SYN ocupies a sequence number |
81 | inc edi ; SYN ocupies a sequence number |
82 | mov [ptr + TCP_SOCKET.RCV_NXT], edi |
82 | mov [ptr + TCP_SOCKET.RCV_NXT], edi |
83 | mov [ptr + TCP_SOCKET.RCV_ADV], edi |
83 | mov [ptr + TCP_SOCKET.RCV_ADV], edi |
84 | pop edi |
84 | pop edi |
85 | 85 | ||
86 | } |
86 | } |
87 | 87 | ||
88 | 88 | ||
89 | 89 | ||
90 | macro tcp_init_socket socket { |
90 | macro tcp_init_socket socket { |
91 | 91 | ||
92 | ; new tcp control block |
92 | ; new tcp control block |
93 | 93 | ||
94 | mov [socket + TCP_SOCKET.t_maxseg], TCP_mss_default |
94 | mov [socket + TCP_SOCKET.t_maxseg], TCP_mss_default |
95 | mov [socket + TCP_SOCKET.t_flags], TF_REQ_SCALE or TF_REQ_TSTMP |
95 | mov [socket + TCP_SOCKET.t_flags], TF_REQ_SCALE or TF_REQ_TSTMP |
96 | 96 | ||
97 | mov [socket + TCP_SOCKET.t_srtt], TCP_time_srtt_default |
97 | mov [socket + TCP_SOCKET.t_srtt], TCP_time_srtt_default |
98 | mov [socket + TCP_SOCKET.t_rttvar], TCP_time_rtt_default * 4 |
98 | mov [socket + TCP_SOCKET.t_rttvar], TCP_time_rtt_default * 4 |
99 | mov [socket + TCP_SOCKET.t_rttmin], TCP_time_re_min |
99 | mov [socket + TCP_SOCKET.t_rttmin], TCP_time_re_min |
100 | ;;; TODO: TCP_time_rangeset |
100 | ;;; TODO: TCP_time_rangeset |
101 | 101 | ||
102 | mov [socket + TCP_SOCKET.SND_CWND], TCP_max_win shl TCP_max_winshift |
102 | mov [socket + TCP_SOCKET.SND_CWND], TCP_max_win shl TCP_max_winshift |
103 | mov [socket + TCP_SOCKET.SND_SSTHRESH], TCP_max_win shl TCP_max_winshift |
103 | mov [socket + TCP_SOCKET.SND_SSTHRESH], TCP_max_win shl TCP_max_winshift |
104 | 104 | ||
105 | mov [socket + TCP_SOCKET.RCV_SCALE], 0 |
105 | mov [socket + TCP_SOCKET.RCV_SCALE], 0 |
106 | mov [socket + TCP_SOCKET.SND_SCALE], 0 |
106 | mov [socket + TCP_SOCKET.SND_SCALE], 0 |
107 | 107 | ||
108 | } |
108 | } |
109 | 109 | ||
110 | 110 | ||
111 | ;-----------------------------------------------------------------; |
111 | ;-----------------------------------------------------------------; |
112 | ; ; |
112 | ; ; |
113 | ; tcp_pull_out_of_band ; |
113 | ; tcp_pull_out_of_band ; |
114 | ; ; |
114 | ; ; |
115 | ; IN: eax = ? ; |
115 | ; IN: eax = ? ; |
116 | ; ebx = socket ptr ; |
116 | ; ebx = socket ptr ; |
117 | ; edx = tcp packet ptr ; |
117 | ; edx = tcp packet ptr ; |
118 | ; ; |
118 | ; ; |
119 | ; OUT: / ; |
119 | ; OUT: / ; |
120 | ; ; |
120 | ; ; |
121 | ;-----------------------------------------------------------------; |
121 | ;-----------------------------------------------------------------; |
122 | align 4 |
122 | align 4 |
123 | tcp_pull_out_of_band: |
123 | tcp_pull_out_of_band: |
124 | 124 | ||
125 | DEBUGF DEBUG_NETWORK_VERBOSE, "tcp_pull_out_of_band\n" |
125 | DEBUGF DEBUG_NETWORK_VERBOSE, "tcp_pull_out_of_band\n" |
126 | 126 | ||
127 | ;;;; 1282-1305 |
127 | ;;;; 1282-1305 |
128 | 128 | ||
129 | ret |
129 | ret |
130 | 130 | ||
131 | 131 | ||
132 | 132 | ||
133 | ;-----------------------------------------------------------------; |
133 | ;-----------------------------------------------------------------; |
134 | ; ; |
134 | ; ; |
135 | ; tcp_drop ; |
135 | ; tcp_drop ; |
136 | ; ; |
136 | ; ; |
137 | ; IN: eax = socket ptr ; |
137 | ; IN: eax = socket ptr ; |
138 | ; ebx = error number ; |
138 | ; ebx = error number ; |
139 | ; ; |
139 | ; ; |
140 | ; OUT: eax = socket ptr ; |
140 | ; OUT: eax = socket ptr ; |
141 | ; ; |
141 | ; ; |
142 | ;-----------------------------------------------------------------; |
142 | ;-----------------------------------------------------------------; |
143 | align 4 |
143 | align 4 |
144 | tcp_drop: |
144 | tcp_drop: |
145 | 145 | ||
146 | ;;; TODO: check if error code is "Connection timed out' and handle accordingly |
146 | ;;; TODO: check if error code is "Connection timed out' and handle accordingly |
147 | 147 | ||
148 | DEBUGF DEBUG_NETWORK_VERBOSE, "tcp_drop: %x\n", eax |
148 | DEBUGF DEBUG_NETWORK_VERBOSE, "tcp_drop: %x\n", eax |
149 | 149 | ||
150 | cmp [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED |
150 | cmp [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED |
151 | jb .no_syn_received |
151 | jb .no_syn_received |
152 | 152 | ||
153 | mov [eax + TCP_SOCKET.t_state], TCPS_CLOSED |
153 | mov [eax + TCP_SOCKET.t_state], TCPS_CLOSED |
154 | 154 | ||
155 | push eax |
155 | push eax |
156 | call tcp_output |
156 | call tcp_output |
157 | pop eax |
157 | pop eax |
158 | 158 | ||
159 | inc [TCPS_drops] |
159 | inc [TCPS_drops] |
160 | 160 | ||
161 | mov [eax + SOCKET.errorcode], ebx |
161 | mov [eax + SOCKET.errorcode], ebx |
162 | jmp tcp_close |
162 | jmp tcp_close |
163 | 163 | ||
164 | .no_syn_received: |
164 | .no_syn_received: |
165 | inc [TCPS_conndrops] |
165 | inc [TCPS_conndrops] |
166 | 166 | ||
167 | mov [eax + SOCKET.errorcode], ebx |
167 | mov [eax + SOCKET.errorcode], ebx |
168 | jmp tcp_close |
168 | jmp tcp_close |
169 | 169 | ||
170 | 170 | ||
171 | ;-----------------------------------------------------------------; |
171 | ;-----------------------------------------------------------------; |
172 | ; ; |
172 | ; ; |
173 | ; tcp_disconnect ; |
173 | ; tcp_disconnect ; |
174 | ; ; |
174 | ; ; |
175 | ; IN: eax = socket ptr ; |
175 | ; IN: eax = socket ptr ; |
176 | ; ; |
176 | ; ; |
177 | ; OUT: eax = socket ptr / 0 ; |
177 | ; OUT: eax = socket ptr / 0 ; |
178 | ; ; |
178 | ; ; |
179 | ;-----------------------------------------------------------------; |
179 | ;-----------------------------------------------------------------; |
180 | align 4 |
180 | align 4 |
181 | tcp_disconnect: |
181 | tcp_disconnect: |
182 | 182 | ||
183 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_disconnect: %x\n", eax |
183 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_disconnect: %x\n", eax |
184 | 184 | ||
185 | cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED |
185 | cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED |
186 | jb tcp_close ; Connection not yet synchronised, just get rid of the socket |
186 | jb tcp_close ; Connection not yet synchronised, just get rid of the socket |
- | 187 | ||
- | 188 | test [eax + SOCKET.options], SO_LINGER |
|
- | 189 | jz .nolinger |
|
187 | 190 | ||
- | 191 | ; TODO: implement LINGER |
|
- | 192 | ; cmp [eax + SOCKET.so_linger], 0 |
|
- | 193 | ; je TCP_drop |
|
188 | ; TODO: implement LINGER |
194 | |
- | 195 | .nolinger: |
|
- | 196 | call socket_is_disconnecting |
|
- | 197 | ||
- | 198 | push eax |
|
- | 199 | add eax, STREAM_SOCKET.rcv |
|
- | 200 | mov ecx, [eax + RING_BUFFER.size] |
|
- | 201 | call socket_ring_free |
|
189 | 202 | pop eax |
|
190 | call socket_is_disconnecting |
203 | |
191 | call tcp_usrclosed |
204 | call tcp_usrclosed |
192 | 205 | ||
193 | test eax, eax |
206 | test eax, eax |
194 | jz @f |
207 | jz @f |
195 | push eax |
208 | push eax |
196 | call tcp_output |
209 | call tcp_output |
197 | pop eax |
210 | pop eax |
198 | @@: |
211 | @@: |
199 | ret |
212 | ret |
200 | 213 | ||
201 | 214 | ||
202 | ;-----------------------------------------------------------------; |
215 | ;-----------------------------------------------------------------; |
203 | ; ; |
216 | ; ; |
204 | ; tcp_close ; |
217 | ; tcp_close ; |
205 | ; ; |
218 | ; ; |
206 | ; IN: eax = socket ptr ; |
219 | ; IN: eax = socket ptr ; |
207 | ; ; |
220 | ; ; |
208 | ; OUT: / ; |
221 | ; OUT: / ; |
209 | ; ; |
222 | ; ; |
210 | ;-----------------------------------------------------------------; |
223 | ;-----------------------------------------------------------------; |
211 | align 4 |
224 | align 4 |
212 | tcp_close: |
225 | tcp_close: |
213 | 226 | ||
214 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_close: %x\n", eax |
227 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_close: %x\n", eax |
215 | 228 | ||
216 | ;;; TODO: update RTT and mean deviation |
229 | ;;; TODO: update RTT and mean deviation |
217 | ;;; TODO: update slow start threshold |
230 | ;;; TODO: update slow start threshold |
218 | 231 | ||
219 | call socket_is_disconnected |
232 | call socket_is_disconnected |
220 | call socket_free |
233 | call socket_free |
221 | 234 | ||
222 | inc [TCPS_closed] |
235 | inc [TCPS_closed] |
223 | 236 | ||
224 | xor eax, eax |
237 | xor eax, eax |
225 | ret |
238 | ret |
226 | 239 | ||
227 | 240 | ||
228 | 241 | ||
229 | ;-----------------------------------------------------------------; |
242 | ;-----------------------------------------------------------------; |
230 | ; ; |
243 | ; ; |
231 | ; tcp_outflags ; |
244 | ; tcp_outflags ; |
232 | ; ; |
245 | ; ; |
233 | ; IN: eax = socket ptr ; |
246 | ; IN: eax = socket ptr ; |
234 | ; ; |
247 | ; ; |
235 | ; OUT: edx = flags ; |
248 | ; OUT: edx = flags ; |
236 | ; ; |
249 | ; ; |
237 | ;-----------------------------------------------------------------; |
250 | ;-----------------------------------------------------------------; |
238 | align 4 |
251 | align 4 |
239 | tcp_outflags: |
252 | tcp_outflags: |
240 | 253 | ||
241 | mov edx, [eax + TCP_SOCKET.t_state] |
254 | mov edx, [eax + TCP_SOCKET.t_state] |
242 | movzx edx, byte[edx + .flaglist] |
255 | movzx edx, byte[edx + .flaglist] |
243 | 256 | ||
244 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_outflags: socket=%x flags=%x\n", eax, dl |
257 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_outflags: socket=%x flags=%x\n", eax, dl |
245 | 258 | ||
246 | ret |
259 | ret |
247 | 260 | ||
248 | .flaglist: |
261 | .flaglist: |
249 | db TH_RST + TH_ACK ; TCPS_CLOSED |
262 | db TH_RST + TH_ACK ; TCPS_CLOSED |
250 | db 0 ; TCPS_LISTEN |
263 | db 0 ; TCPS_LISTEN |
251 | db TH_SYN ; TCPS_SYN_SENT |
264 | db TH_SYN ; TCPS_SYN_SENT |
252 | db TH_SYN + TH_ACK ; TCPS_SYN_RECEIVED |
265 | db TH_SYN + TH_ACK ; TCPS_SYN_RECEIVED |
253 | db TH_ACK ; TCPS_ESTABLISHED |
266 | db TH_ACK ; TCPS_ESTABLISHED |
254 | db TH_ACK ; TCPS_CLOSE_WAIT |
267 | db TH_ACK ; TCPS_CLOSE_WAIT |
255 | db TH_FIN + TH_ACK ; TCPS_FIN_WAIT_1 |
268 | db TH_FIN + TH_ACK ; TCPS_FIN_WAIT_1 |
256 | db TH_FIN + TH_ACK ; TCPS_CLOSING |
269 | db TH_FIN + TH_ACK ; TCPS_CLOSING |
257 | db TH_FIN + TH_ACK ; TCPS_LAST_ACK |
270 | db TH_FIN + TH_ACK ; TCPS_LAST_ACK |
258 | db TH_ACK ; TCPS_FIN_WAIT_2 |
271 | db TH_ACK ; TCPS_FIN_WAIT_2 |
259 | db TH_ACK ; TCPS_TIME_WAIT |
272 | db TH_ACK ; TCPS_TIME_WAIT |
260 | 273 | ||
261 | 274 | ||
262 | ;-----------------------------------------------------------------; |
275 | ;-----------------------------------------------------------------; |
263 | ; ; |
276 | ; ; |
264 | ; TCP_respond: Fast way to send an ACK/RST/keepalive segment. ; |
277 | ; TCP_respond: Fast way to send an ACK/RST/keepalive segment. ; |
265 | ; ; |
278 | ; ; |
266 | ; IN: ebx = socket ptr ; |
279 | ; IN: ebx = socket ptr ; |
267 | ; cl = flags ; |
280 | ; cl = flags ; |
268 | ; ; |
281 | ; ; |
269 | ; OUT: / ; |
282 | ; OUT: / ; |
270 | ; ; |
283 | ; ; |
271 | ;-----------------------------------------------------------------; |
284 | ;-----------------------------------------------------------------; |
272 | align 4 |
285 | align 4 |
273 | tcp_respond: |
286 | tcp_respond: |
274 | 287 | ||
275 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: socket=%x flags=%x\n", ebx, cl |
288 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: socket=%x flags=%x\n", ebx, cl |
276 | 289 | ||
277 | ;--------------------- |
290 | ;--------------------- |
278 | ; Create the IP packet |
291 | ; Create the IP packet |
279 | 292 | ||
280 | push cx ebx |
293 | push cx ebx |
281 | mov edx, [ebx + IP_SOCKET.LocalIP] |
294 | mov edx, [ebx + IP_SOCKET.LocalIP] |
282 | mov edi, [ebx + IP_SOCKET.RemoteIP] |
295 | mov edi, [ebx + IP_SOCKET.RemoteIP] |
283 | mov al, [ebx + IP_SOCKET.ttl] |
296 | mov al, [ebx + IP_SOCKET.ttl] |
284 | mov ah, IP_PROTO_TCP |
297 | mov ah, IP_PROTO_TCP |
285 | mov ecx, sizeof.TCP_header |
298 | mov ecx, sizeof.TCP_header |
286 | mov ebx, [ebx + IP_SOCKET.device] |
299 | mov ebx, [ebx + IP_SOCKET.device] |
287 | call ipv4_output |
300 | call ipv4_output |
288 | jz .error |
301 | jz .error |
289 | pop esi cx |
302 | pop esi cx |
290 | push eax |
303 | push eax |
291 | 304 | ||
292 | ;----------------------------------------------- |
305 | ;----------------------------------------------- |
293 | ; Fill in the TCP header by using the socket ptr |
306 | ; Fill in the TCP header by using the socket ptr |
294 | 307 | ||
295 | mov ax, [esi + TCP_SOCKET.LocalPort] |
308 | mov ax, [esi + TCP_SOCKET.LocalPort] |
296 | stosw |
309 | stosw |
297 | mov ax, [esi + TCP_SOCKET.RemotePort] |
310 | mov ax, [esi + TCP_SOCKET.RemotePort] |
298 | stosw |
311 | stosw |
299 | mov eax, [esi + TCP_SOCKET.SND_NXT] |
312 | mov eax, [esi + TCP_SOCKET.SND_NXT] |
300 | bswap eax |
313 | bswap eax |
301 | stosd |
314 | stosd |
302 | mov eax, [esi + TCP_SOCKET.RCV_NXT] |
315 | mov eax, [esi + TCP_SOCKET.RCV_NXT] |
303 | bswap eax |
316 | bswap eax |
304 | stosd |
317 | stosd |
305 | mov al, 0x50 ; Dataoffset: 20 bytes (TCP_header.DataOffset) |
318 | mov al, 0x50 ; Dataoffset: 20 bytes (TCP_header.DataOffset) |
306 | stosb |
319 | stosb |
307 | mov al, cl |
320 | mov al, cl |
308 | stosb |
321 | stosb |
309 | mov eax, SOCKET_BUFFER_SIZE |
322 | mov eax, SOCKET_BUFFER_SIZE |
310 | sub eax, [esi + STREAM_SOCKET.rcv.size] |
323 | sub eax, [esi + STREAM_SOCKET.rcv.size] |
311 | cmp eax, TCP_max_win |
324 | cmp eax, TCP_max_win |
312 | jbe .lessthanmax |
325 | jbe .lessthanmax |
313 | mov eax, TCP_max_win |
326 | mov eax, TCP_max_win |
314 | .lessthanmax: |
327 | .lessthanmax: |
315 | mov cl, [esi + TCP_SOCKET.RCV_SCALE] |
328 | mov cl, [esi + TCP_SOCKET.RCV_SCALE] |
316 | shr eax, cl |
329 | shr eax, cl |
317 | 330 | ||
318 | xchg al, ah |
331 | xchg al, ah |
319 | stosw ; window |
332 | stosw ; window |
320 | xor eax, eax |
333 | xor eax, eax |
321 | stosd ; checksum + urgentpointer |
334 | stosd ; checksum + urgentpointer |
322 | 335 | ||
323 | ;--------------------- |
336 | ;--------------------- |
324 | ; Fill in the checksum |
337 | ; Fill in the checksum |
325 | 338 | ||
326 | .checksum: |
339 | .checksum: |
327 | sub edi, sizeof.TCP_header |
340 | sub edi, sizeof.TCP_header |
328 | mov ecx, sizeof.TCP_header |
341 | mov ecx, sizeof.TCP_header |
329 | xchg esi, edi |
342 | xchg esi, edi |
330 | tcp_checksum (edi + IP_SOCKET.LocalIP), (edi + IP_SOCKET.RemoteIP) |
343 | tcp_checksum (edi + IP_SOCKET.LocalIP), (edi + IP_SOCKET.RemoteIP) |
331 | mov [esi+TCP_header.Checksum], dx |
344 | mov [esi+TCP_header.Checksum], dx |
332 | 345 | ||
333 | ;-------------------- |
346 | ;-------------------- |
334 | ; And send the segment |
347 | ; And send the segment |
335 | 348 | ||
336 | call [ebx + NET_DEVICE.transmit] |
349 | call [ebx + NET_DEVICE.transmit] |
337 | test eax, eax |
350 | test eax, eax |
338 | jnz @f |
351 | jnz @f |
339 | call net_ptr_to_num4 |
352 | call net_ptr_to_num4 |
340 | inc [TCP_segments_tx + edi] |
353 | inc [TCP_segments_tx + edi] |
341 | @@: |
354 | @@: |
342 | ret |
355 | ret |
343 | 356 | ||
344 | .error: |
357 | .error: |
345 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: failed\n" |
358 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: failed\n" |
346 | add esp, 2 + 4 |
359 | add esp, 2 + 4 |
347 | 360 | ||
348 | ret |
361 | ret |
349 | 362 | ||
350 | 363 | ||
351 | ;-----------------------------------------------------------------; |
364 | ;-----------------------------------------------------------------; |
352 | ; ; |
365 | ; ; |
353 | ; tcp_respond_segment ; |
366 | ; tcp_respond_segment ; |
354 | ; ; |
367 | ; ; |
355 | ; IN: ebx = device ptr ; |
368 | ; IN: ebx = device ptr ; |
356 | ; edx = segment ptr (a previously received segment) ; |
369 | ; edx = segment ptr (a previously received segment) ; |
357 | ; edi = ptr to IPv4 header ; |
370 | ; edi = ptr to IPv4 header ; |
358 | ; cl = flags ; |
371 | ; cl = flags ; |
359 | ; ; |
372 | ; ; |
360 | ; OUT: / ; |
373 | ; OUT: / ; |
361 | ; ; |
374 | ; ; |
362 | ;-----------------------------------------------------------------; |
375 | ;-----------------------------------------------------------------; |
363 | align 4 |
376 | align 4 |
364 | tcp_respond_segment: |
377 | tcp_respond_segment: |
365 | 378 | ||
366 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_segment: frame=%x flags=%x\n", edx, cl |
379 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_segment: frame=%x flags=%x\n", edx, cl |
367 | 380 | ||
368 | ;--------------------- |
381 | ;--------------------- |
369 | ; Create the IP packet |
382 | ; Create the IP packet |
370 | 383 | ||
371 | push cx edx |
384 | push cx edx |
372 | mov edx, [edi + IPv4_header.DestinationAddress] |
385 | mov edx, [edi + IPv4_header.DestinationAddress] |
373 | mov edi, [edi + IPv4_header.SourceAddress] |
386 | mov edi, [edi + IPv4_header.SourceAddress] |
374 | mov ecx, sizeof.TCP_header |
387 | mov ecx, sizeof.TCP_header |
375 | mov ax, IP_PROTO_TCP shl 8 + 128 |
388 | mov ax, IP_PROTO_TCP shl 8 + 128 |
376 | call ipv4_output |
389 | call ipv4_output |
377 | jz .error |
390 | jz .error |
378 | pop esi cx |
391 | pop esi cx |
379 | 392 | ||
380 | push eax |
393 | push eax |
381 | 394 | ||
382 | ;--------------------------------------------------- |
395 | ;--------------------------------------------------- |
383 | ; Fill in the TCP header by using a received segment |
396 | ; Fill in the TCP header by using a received segment |
384 | 397 | ||
385 | mov ax, [esi + TCP_header.DestinationPort] |
398 | mov ax, [esi + TCP_header.DestinationPort] |
386 | stosw |
399 | stosw |
387 | mov ax, [esi + TCP_header.SourcePort] |
400 | mov ax, [esi + TCP_header.SourcePort] |
388 | stosw |
401 | stosw |
389 | mov eax, [esi + TCP_header.AckNumber] |
402 | mov eax, [esi + TCP_header.AckNumber] |
390 | bswap eax |
403 | bswap eax |
391 | stosd |
404 | stosd |
392 | xor eax, eax |
405 | xor eax, eax |
393 | stosd |
406 | stosd |
394 | mov al, 0x50 ; Dataoffset: 20 bytes (sizeof.TCP_header/4 shl 4) |
407 | mov al, 0x50 ; Dataoffset: 20 bytes (sizeof.TCP_header/4 shl 4) |
395 | stosb |
408 | stosb |
396 | mov al, cl |
409 | mov al, cl |
397 | stosb |
410 | stosb |
398 | mov ax, 1280 |
411 | mov ax, 1280 |
399 | rol ax, 8 |
412 | rol ax, 8 |
400 | stosw ; window |
413 | stosw ; window |
401 | xor eax, eax |
414 | xor eax, eax |
402 | stosd ; checksum + urgentpointer |
415 | stosd ; checksum + urgentpointer |
403 | 416 | ||
404 | ;--------------------- |
417 | ;--------------------- |
405 | ; Fill in the checksum |
418 | ; Fill in the checksum |
406 | 419 | ||
407 | lea esi, [edi - sizeof.TCP_header] |
420 | lea esi, [edi - sizeof.TCP_header] |
408 | mov ecx, sizeof.TCP_header |
421 | mov ecx, sizeof.TCP_header |
409 | tcp_checksum (esi - sizeof.IPv4_header + IPv4_header.DestinationAddress),\ ; FIXME |
422 | tcp_checksum (esi - sizeof.IPv4_header + IPv4_header.DestinationAddress),\ ; FIXME |
410 | (esi - sizeof.IPv4_header + IPv4_header.SourceAddress) |
423 | (esi - sizeof.IPv4_header + IPv4_header.SourceAddress) |
411 | mov [esi + TCP_header.Checksum], dx |
424 | mov [esi + TCP_header.Checksum], dx |
412 | 425 | ||
413 | ;-------------------- |
426 | ;-------------------- |
414 | ; And send the segment |
427 | ; And send the segment |
415 | 428 | ||
416 | call [ebx + NET_DEVICE.transmit] |
429 | call [ebx + NET_DEVICE.transmit] |
417 | test eax, eax |
430 | test eax, eax |
418 | jnz @f |
431 | jnz @f |
419 | call net_ptr_to_num4 |
432 | call net_ptr_to_num4 |
420 | inc [TCP_segments_tx + edi] |
433 | inc [TCP_segments_tx + edi] |
421 | @@: |
434 | @@: |
422 | ret |
435 | ret |
423 | 436 | ||
424 | .error: |
437 | .error: |
425 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_segment: failed\n" |
438 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_segment: failed\n" |
426 | add esp, 2+4 |
439 | add esp, 2+4 |
427 | 440 | ||
428 | ret |
441 | ret |
429 | 442 | ||
430 | 443 | ||
431 | macro tcpt_rangeset timer, value, min, max { |
444 | macro tcpt_rangeset timer, value, min, max { |
432 | 445 | ||
433 | local .min |
446 | local .min |
434 | local .max |
447 | local .max |
435 | local .done |
448 | local .done |
436 | 449 | ||
437 | cmp value, min |
450 | cmp value, min |
438 | jb .min |
451 | jb .min |
439 | cmp value, max |
452 | cmp value, max |
440 | ja .max |
453 | ja .max |
441 | mov timer, value |
454 | mov timer, value |
442 | jmp .done |
455 | jmp .done |
443 | .min: |
456 | .min: |
444 | mov timer, min |
457 | mov timer, min |
445 | jmp .done |
458 | jmp .done |
446 | .max: |
459 | .max: |
447 | mov timer, max |
460 | mov timer, max |
448 | .done: |
461 | .done: |
449 | } |
462 | } |
450 | 463 | ||
451 | ;-----------------------------------------------------------------; |
464 | ;-----------------------------------------------------------------; |
452 | ; ; |
465 | ; ; |
453 | ; tcp_set_persist ; |
466 | ; tcp_set_persist ; |
454 | ; ; |
467 | ; ; |
455 | ;-----------------------------------------------------------------; |
468 | ;-----------------------------------------------------------------; |
456 | align 4 |
469 | align 4 |
457 | tcp_set_persist: |
470 | tcp_set_persist: |
458 | 471 | ||
459 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_set_persist\n" |
472 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_set_persist\n" |
460 | 473 | ||
461 | ; First, check if retransmit timer is not set, retransmit and persist are mutually exclusive |
474 | ; First, check if retransmit timer is not set, retransmit and persist are mutually exclusive |
462 | 475 | ||
463 | test [eax + TCP_SOCKET.timer_flags], timer_flag_retransmission |
476 | test [eax + TCP_SOCKET.timer_flags], timer_flag_retransmission |
464 | jnz .exit |
477 | jnz .exit |
465 | 478 | ||
466 | ; calculate RTO |
479 | ; calculate RTO |
467 | push ebx |
480 | push ebx |
468 | mov ebx, [eax + TCP_SOCKET.t_srtt] |
481 | mov ebx, [eax + TCP_SOCKET.t_srtt] |
469 | shr ebx, 2 |
482 | shr ebx, 2 |
470 | add ebx, [eax + TCP_SOCKET.t_rttvar] |
483 | add ebx, [eax + TCP_SOCKET.t_rttvar] |
471 | shr ebx, 1 |
484 | shr ebx, 1 |
472 | 485 | ||
473 | mov cl, [eax + TCP_SOCKET.t_rxtshift] |
486 | mov cl, [eax + TCP_SOCKET.t_rxtshift] |
474 | shl ebx, cl |
487 | shl ebx, cl |
475 | 488 | ||
476 | ; Start/restart persistance timer. |
489 | ; Start/restart persistance timer. |
477 | 490 | ||
478 | tcpt_rangeset [eax + TCP_SOCKET.timer_persist], ebx, TCP_time_pers_min, TCP_time_pers_max |
491 | tcpt_rangeset [eax + TCP_SOCKET.timer_persist], ebx, TCP_time_pers_min, TCP_time_pers_max |
479 | or [ebx + TCP_SOCKET.timer_flags], timer_flag_persist |
492 | or [ebx + TCP_SOCKET.timer_flags], timer_flag_persist |
480 | pop ebx |
493 | pop ebx |
481 | 494 | ||
482 | cmp [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift |
495 | cmp [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift |
483 | jae @f |
496 | jae @f |
484 | inc [eax + TCP_SOCKET.t_rxtshift] |
497 | inc [eax + TCP_SOCKET.t_rxtshift] |
485 | @@: |
498 | @@: |
486 | .exit: |
499 | .exit: |
487 | 500 | ||
488 | ret |
501 | ret |
489 | 502 | ||
490 | 503 | ||
491 | 504 | ||
492 | ;-----------------------------------------------------------------; |
505 | ;-----------------------------------------------------------------; |
493 | ; ; |
506 | ; ; |
494 | ; tcp_xmit_timer: Calculate new smoothed RTT. ; |
507 | ; tcp_xmit_timer: Calculate new smoothed RTT. ; |
495 | ; ; |
508 | ; ; |
496 | ; IN: eax = rtt ; |
509 | ; IN: eax = rtt ; |
497 | ; ebx = socket ptr ; |
510 | ; ebx = socket ptr ; |
498 | ; ; |
511 | ; ; |
499 | ; OUT: / ; |
512 | ; OUT: / ; |
500 | ; ; |
513 | ; ; |
501 | ;-----------------------------------------------------------------; |
514 | ;-----------------------------------------------------------------; |
502 | align 4 |
515 | align 4 |
503 | tcp_xmit_timer: |
516 | tcp_xmit_timer: |
504 | 517 | ||
505 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_xmit_timer: socket=0x%x rtt=%d0ms\n", ebx, eax |
518 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_xmit_timer: socket=0x%x rtt=%d0ms\n", ebx, eax |
506 | 519 | ||
507 | inc [TCPS_rttupdated] |
520 | inc [TCPS_rttupdated] |
508 | 521 | ||
509 | cmp [ebx + TCP_SOCKET.t_rtt], 0 |
522 | cmp [ebx + TCP_SOCKET.t_rtt], 0 |
510 | je .no_rtt_yet |
523 | je .no_rtt_yet |
511 | 524 | ||
512 | ; srtt is stored as a fixed point with 3 bits after the binary point. |
525 | ; srtt is stored as a fixed point with 3 bits after the binary point. |
513 | ; The following magic is equivalent of the smoothing algorithm in rfc793 with an alpha of .875 |
526 | ; The following magic is equivalent of the smoothing algorithm in rfc793 with an alpha of .875 |
514 | ; (srtt = rtt/8 + srtt*7/8 in fixed point) |
527 | ; (srtt = rtt/8 + srtt*7/8 in fixed point) |
515 | ; Adjust rtt to origin 0. |
528 | ; Adjust rtt to origin 0. |
516 | 529 | ||
517 | push ecx |
530 | push ecx |
518 | mov ecx, [ebx + TCP_SOCKET.t_srtt] |
531 | mov ecx, [ebx + TCP_SOCKET.t_srtt] |
519 | shr ecx, TCP_RTT_SHIFT |
532 | shr ecx, TCP_RTT_SHIFT |
520 | sub eax, ecx |
533 | sub eax, ecx |
521 | dec eax |
534 | dec eax |
522 | pop ecx |
535 | pop ecx |
523 | 536 | ||
524 | add [ebx + TCP_SOCKET.t_srtt], eax |
537 | add [ebx + TCP_SOCKET.t_srtt], eax |
525 | ja @f |
538 | ja @f |
526 | mov [ebx + TCP_SOCKET.t_srtt], 1 |
539 | mov [ebx + TCP_SOCKET.t_srtt], 1 |
527 | @@: |
540 | @@: |
528 | 541 | ||
529 | ; We accumulate a smoothed rtt variance (actually, a smoothed mean difference), |
542 | ; We accumulate a smoothed rtt variance (actually, a smoothed mean difference), |
530 | ; then set the retransmit timer to smoothed rtt + 4 times the smoothed variance. |
543 | ; then set the retransmit timer to smoothed rtt + 4 times the smoothed variance. |
531 | ; rttvar is stored as fixed point with 2 bits after the binary point. |
544 | ; rttvar is stored as fixed point with 2 bits after the binary point. |
532 | ; The following is equivalent to rfc793 smoothing with an alpha of .75 |
545 | ; The following is equivalent to rfc793 smoothing with an alpha of .75 |
533 | ; (rttvar = rttvar*3/4 + delta/4) (delta = eax) |
546 | ; (rttvar = rttvar*3/4 + delta/4) (delta = eax) |
534 | 547 | ||
535 | ; get abs(eax) |
548 | ; get abs(eax) |
536 | push edx |
549 | push edx |
537 | cdq |
550 | cdq |
538 | xor eax, edx |
551 | xor eax, edx |
539 | sub eax, edx |
552 | sub eax, edx |
540 | 553 | ||
541 | mov edx, [ebx + TCP_SOCKET.t_rttvar] |
554 | mov edx, [ebx + TCP_SOCKET.t_rttvar] |
542 | shr edx, TCP_RTTVAR_SHIFT |
555 | shr edx, TCP_RTTVAR_SHIFT |
543 | sub eax, edx |
556 | sub eax, edx |
544 | pop edx |
557 | pop edx |
545 | 558 | ||
546 | add [ebx + TCP_SOCKET.t_rttvar], eax |
559 | add [ebx + TCP_SOCKET.t_rttvar], eax |
547 | ja @f |
560 | ja @f |
548 | mov [ebx + TCP_SOCKET.t_rttvar], 1 |
561 | mov [ebx + TCP_SOCKET.t_rttvar], 1 |
549 | @@: |
562 | @@: |
550 | ret |
563 | ret |
551 | 564 | ||
552 | 565 | ||
553 | .no_rtt_yet: |
566 | .no_rtt_yet: |
554 | push ecx |
567 | push ecx |
555 | mov ecx, eax |
568 | mov ecx, eax |
556 | shl ecx, TCP_RTT_SHIFT |
569 | shl ecx, TCP_RTT_SHIFT |
557 | mov [ebx + TCP_SOCKET.t_srtt], ecx |
570 | mov [ebx + TCP_SOCKET.t_srtt], ecx |
558 | 571 | ||
559 | shl eax, TCP_RTTVAR_SHIFT - 1 |
572 | shl eax, TCP_RTTVAR_SHIFT - 1 |
560 | mov [ebx + TCP_SOCKET.t_rttvar], eax |
573 | mov [ebx + TCP_SOCKET.t_rttvar], eax |
561 | pop ecx |
574 | pop ecx |
562 | 575 | ||
563 | ret |
576 | ret |
564 | 577 | ||
565 | 578 | ||
566 | ;-----------------------------------------------------------------; |
579 | ;-----------------------------------------------------------------; |
567 | ; ; |
580 | ; ; |
568 | ; tcp_mss: Update maximum segment size ; |
581 | ; tcp_mss: Update maximum segment size ; |
569 | ; ; |
582 | ; ; |
570 | ; IN: eax = max segment size ; |
583 | ; IN: eax = max segment size ; |
571 | ; ebx = socket ptr ; |
584 | ; ebx = socket ptr ; |
572 | ; ; |
585 | ; ; |
573 | ; OUT: / ; |
586 | ; OUT: / ; |
574 | ; ; |
587 | ; ; |
575 | ;-----------------------------------------------------------------; |
588 | ;-----------------------------------------------------------------; |
576 | align 4 |
589 | align 4 |
577 | tcp_mss: |
590 | tcp_mss: |
578 | 591 | ||
579 | cmp eax, 1420 ; FIXME |
592 | cmp eax, 1420 ; FIXME |
580 | jbe @f |
593 | jbe @f |
581 | mov eax, 1420 |
594 | mov eax, 1420 |
582 | @@: |
595 | @@: |
583 | mov [ebx + TCP_SOCKET.t_maxseg], eax |
596 | mov [ebx + TCP_SOCKET.t_maxseg], eax |
584 | 597 | ||
585 | 598 | ||
586 | ret |
599 | ret |
587 | 600 | ||
588 | 601 | ||
589 | 602 | ||
590 | ;-----------------------------------------------------------------; |
603 | ;-----------------------------------------------------------------; |
591 | ; ; |
604 | ; ; |
592 | ; tcp_reassemble ; |
605 | ; tcp_reassemble ; |
593 | ; ; |
606 | ; ; |
594 | ; IN: ebx = socket ptr ; |
607 | ; IN: ebx = socket ptr ; |
595 | ; edx = segment ptr ; |
608 | ; edx = segment ptr ; |
596 | ; ; |
609 | ; ; |
597 | ; OUT: / ; |
610 | ; OUT: / ; |
598 | ; ; |
611 | ; ; |
599 | ;-----------------------------------------------------------------; |
612 | ;-----------------------------------------------------------------; |
600 | align 4 |
613 | align 4 |
601 | tcp_reassemble: |
614 | tcp_reassemble: |
602 | 615 | ||
603 | ;;;;; TODO |
616 | ;;;;; TODO |
604 | 617 | ||
605 | ret |
618 | ret |