Subversion Repositories Kolibri OS

Rev

Rev 5584 | Rev 6011 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5584 Rev 5842
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved.    ;;
3
;; Copyright (C) KolibriOS team 2004-2015. 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: 5584 $
17
$Revision: 5842 $
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                     ;;;; i dont like this static use of edi
65
        push    edi                     ;;;; 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
81
        inc     edi
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
        mov     [socket + TCP_SOCKET.t_maxseg], TCP_mss_default
92
        mov     [socket + TCP_SOCKET.t_maxseg], TCP_mss_default
93
        mov     [socket + TCP_SOCKET.t_flags], TF_REQ_SCALE or TF_REQ_TSTMP
93
        mov     [socket + TCP_SOCKET.t_flags], TF_REQ_SCALE or TF_REQ_TSTMP
94
 
94
 
95
        mov     [socket + TCP_SOCKET.t_srtt], TCP_time_srtt_default
95
        mov     [socket + TCP_SOCKET.t_srtt], TCP_time_srtt_default
96
        mov     [socket + TCP_SOCKET.t_rttvar], TCP_time_rtt_default * 4
96
        mov     [socket + TCP_SOCKET.t_rttvar], TCP_time_rtt_default * 4
97
        mov     [socket + TCP_SOCKET.t_rttmin], TCP_time_re_min
97
        mov     [socket + TCP_SOCKET.t_rttmin], TCP_time_re_min
98
;;; TODO: TCP_time_rangeset
98
;;; TODO: TCP_time_rangeset
99
 
99
 
100
        mov     [socket + TCP_SOCKET.SND_CWND], TCP_max_win shl TCP_max_winshift
100
        mov     [socket + TCP_SOCKET.SND_CWND], TCP_max_win shl TCP_max_winshift
101
        mov     [socket + TCP_SOCKET.SND_SSTHRESH], TCP_max_win shl TCP_max_winshift
101
        mov     [socket + TCP_SOCKET.SND_SSTHRESH], TCP_max_win shl TCP_max_winshift
102
 
102
 
103
 
103
 
104
}
104
}
105
 
105
 
106
 
106
 
107
;---------------------------
107
;---------------------------
108
;
108
;
109
; TCP_pull_out_of_band
109
; TCP_pull_out_of_band
110
;
110
;
111
; IN:  eax =
111
; IN:  eax =
112
;      ebx = socket ptr
112
;      ebx = socket ptr
113
;      edx = tcp packet ptr
113
;      edx = tcp packet ptr
114
;
114
;
115
; OUT: /
115
; OUT: /
116
;
116
;
117
;---------------------------
117
;---------------------------
118
 
118
 
119
align 4
119
align 4
120
TCP_pull_out_of_band:
120
TCP_pull_out_of_band:
121
 
121
 
122
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_pull_out_of_band\n"
122
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_pull_out_of_band\n"
123
 
123
 
124
        ;;;; 1282-1305
124
        ;;;; 1282-1305
125
 
125
 
126
        ret
126
        ret
127
 
127
 
128
 
128
 
129
 
129
 
130
 
130
 
131
 
131
 
132
 
132
 
133
 
133
 
134
 
134
 
135
;-------------------------
135
;-------------------------
136
;
136
;
137
; TCP_drop
137
; TCP_drop
138
;
138
;
139
;  IN:  eax = socket ptr
139
;  IN:  eax = socket ptr
140
;       ebx = error number
140
;       ebx = error number
141
;
141
;
142
;  OUT: eax = socket ptr
142
;  OUT: eax = socket ptr
143
;
143
;
144
;-------------------------
144
;-------------------------
145
align 4
145
align 4
146
TCP_drop:    ; FIXME CHECKME TODO
146
TCP_drop:    ; FIXME CHECKME TODO
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
;;; TODO: update stats
159
;;; TODO: update stats
160
 
160
 
161
        jmp     TCP_close
161
        jmp     TCP_close
162
 
162
 
163
  .no_syn_received:
163
  .no_syn_received:
164
 
164
 
165
;;; TODO: update stats
165
;;; TODO: update stats
166
 
166
 
167
;;; TODO: check if error code is "Connection timed out' and handle accordingly
167
;;; TODO: check if error code is "Connection timed out' and handle accordingly
168
 
168
 
169
;        mov     [eax + SOCKET.errorcode], ebx
169
;        mov     [eax + SOCKET.errorcode], ebx
170
 
170
 
171
 
171
 
172
 
172
 
173
 
173
 
174
;-------------------------
174
;-------------------------
175
;
175
;
176
; TCP_disconnect
176
; TCP_disconnect
177
;
177
;
178
;  IN:  eax = socket ptr
178
;  IN:  eax = socket ptr
179
;  OUT: eax = socket ptr / 0
179
;  OUT: eax = socket ptr / 0
180
;
180
;
181
;-------------------------
181
;-------------------------
182
align 4
182
align 4
183
TCP_disconnect:
183
TCP_disconnect:
184
 
184
 
185
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_disconnect: %x\n", eax
185
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_disconnect: %x\n", eax
186
 
186
 
187
        cmp     [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
187
        cmp     [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
188
        jb      TCP_close       ; Connection not yet synchronised, just get rid of the socket
188
        jb      TCP_close       ; Connection not yet synchronised, just get rid of the socket
189
 
189
 
190
; TODO: implement LINGER
190
; TODO: implement LINGER
191
 
191
 
192
        call    SOCKET_is_disconnecting
192
        call    SOCKET_is_disconnecting
193
        call    TCP_usrclosed
193
        call    TCP_usrclosed
194
 
194
 
195
        test    eax, eax
195
        test    eax, eax
196
        jz      @f
196
        jz      @f
197
        push    eax
197
        push    eax
198
        call    TCP_output
198
        call    TCP_output
199
        pop     eax
199
        pop     eax
200
  @@:
200
  @@:
201
 
201
 
202
        ret
202
        ret
203
 
203
 
204
 
204
 
205
;-------------------------
205
;-------------------------
206
;
206
;
207
; TCP_close
207
; TCP_close
208
;
208
;
209
;  IN:  eax = socket ptr
209
;  IN:  eax = socket ptr
210
;  OUT: /
210
;  OUT: /
211
;
211
;
212
;-------------------------
212
;-------------------------
213
align 4
213
align 4
214
TCP_close:
214
TCP_close:
215
 
215
 
216
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_close: %x\n", eax
216
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_close: %x\n", eax
217
 
217
 
218
;;; TODO: update RTT and mean deviation
218
;;; TODO: update RTT and mean deviation
219
;;; TODO: update slow start threshold
219
;;; TODO: update slow start threshold
220
 
220
 
221
        call    SOCKET_is_disconnected
221
        call    SOCKET_is_disconnected
222
        call    SOCKET_free
222
        call    SOCKET_free
223
 
223
 
224
        xor     eax, eax
224
        xor     eax, eax
225
 
225
 
226
        ret
226
        ret
227
 
227
 
228
 
228
 
229
 
229
 
230
 
230
 
231
;-------------------------
231
;-------------------------
232
;
232
;
233
; TCP_outflags
233
; TCP_outflags
234
;
234
;
235
;  IN:  eax = socket ptr
235
;  IN:  eax = socket ptr
236
;
236
;
237
;  OUT: edx = flags
237
;  OUT: edx = flags
238
;
238
;
239
;-------------------------
239
;-------------------------
240
align 4
240
align 4
241
TCP_outflags:
241
TCP_outflags:
242
 
242
 
243
        mov     edx, [eax + TCP_SOCKET.t_state]
243
        mov     edx, [eax + TCP_SOCKET.t_state]
244
        movzx   edx, byte [edx + .flaglist]
244
        movzx   edx, byte [edx + .flaglist]
245
 
245
 
246
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_outflags: socket=%x flags=%x\n", eax, dl
246
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_outflags: socket=%x flags=%x\n", eax, dl
247
 
247
 
248
        ret
248
        ret
249
 
249
 
250
  .flaglist:
250
  .flaglist:
251
 
251
 
252
        db      TH_RST + TH_ACK         ; TCPS_CLOSED
252
        db      TH_RST + TH_ACK         ; TCPS_CLOSED
253
        db      0                       ; TCPS_LISTEN
253
        db      0                       ; TCPS_LISTEN
254
        db      TH_SYN                  ; TCPS_SYN_SENT
254
        db      TH_SYN                  ; TCPS_SYN_SENT
255
        db      TH_SYN + TH_ACK         ; TCPS_SYN_RECEIVED
255
        db      TH_SYN + TH_ACK         ; TCPS_SYN_RECEIVED
256
        db               TH_ACK         ; TCPS_ESTABLISHED
256
        db               TH_ACK         ; TCPS_ESTABLISHED
257
        db               TH_ACK         ; TCPS_CLOSE_WAIT
257
        db               TH_ACK         ; TCPS_CLOSE_WAIT
258
        db      TH_FIN + TH_ACK         ; TCPS_FIN_WAIT_1
258
        db      TH_FIN + TH_ACK         ; TCPS_FIN_WAIT_1
259
        db      TH_FIN + TH_ACK         ; TCPS_CLOSING
259
        db      TH_FIN + TH_ACK         ; TCPS_CLOSING
260
        db      TH_FIN + TH_ACK         ; TCPS_LAST_ACK
260
        db      TH_FIN + TH_ACK         ; TCPS_LAST_ACK
261
        db               TH_ACK         ; TCPS_FIN_WAIT_2
261
        db               TH_ACK         ; TCPS_FIN_WAIT_2
262
        db               TH_ACK         ; TCPS_TIMED_WAIT
262
        db               TH_ACK         ; TCPS_TIMED_WAIT
263
 
263
 
264
 
264
 
265
 
265
 
266
 
266
 
267
 
267
 
268
 
268
 
269
;---------------------------------------
269
;-----------------------------------------------------------------
270
;
270
;
271
; The fast way to send an ACK/RST/keepalive segment
271
; The fast way to send an ACK/RST/keepalive segment
272
;
272
;
273
; TCP_respond
273
; TCP_respond
274
;
274
;
275
;  IN:  ebx = socket ptr
275
;  IN:  ebx = socket ptr
276
;        cl = flags
276
;        cl = flags
277
;
277
;
-
 
278
; OUT:  /
-
 
279
;
278
;--------------------------------------
280
;-----------------------------------------------------------------
-
 
281
 
279
align 4
282
align 4
280
TCP_respond:
283
TCP_respond:
281
 
284
 
282
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: socket=%x flags=%x\n", ebx, cl
285
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: socket=%x flags=%x\n", ebx, cl
283
 
286
 
284
;---------------------
287
;---------------------
285
; Create the IP packet
288
; Create the IP packet
286
 
289
 
287
        push    cx ebx
290
        push    cx ebx
288
        mov     eax, [ebx + IP_SOCKET.RemoteIP]
-
 
289
        mov     edx, [ebx + IP_SOCKET.LocalIP]
291
        mov     edx, [ebx + IP_SOCKET.LocalIP]
290
        mov     ebx, [ebx + IP_SOCKET.device]
292
        mov     edi, [ebx + IP_SOCKET.RemoteIP]
-
 
293
        mov     al, [ebx + IP_SOCKET.ttl]
-
 
294
        mov     ah, IP_PROTO_TCP
291
        mov     ecx, sizeof.TCP_header
295
        mov     ecx, sizeof.TCP_header
292
        mov     di, IP_PROTO_TCP shl 8 + 128
296
        mov     ebx, [ebx + IP_SOCKET.device]
293
        call    IPv4_output
297
        call    IPv4_output
294
        jz      .error
298
        jz      .error
295
        pop     esi cx
299
        pop     esi cx
296
        push    eax
300
        push    eax
297
 
301
 
298
;-----------------------------------------------
302
;-----------------------------------------------
299
; Fill in the TCP header by using the socket ptr
303
; Fill in the TCP header by using the socket ptr
300
 
304
 
301
        mov     ax, [esi + TCP_SOCKET.LocalPort]
305
        mov     ax, [esi + TCP_SOCKET.LocalPort]
302
        stosw
306
        stosw
303
        mov     ax, [esi + TCP_SOCKET.RemotePort]
307
        mov     ax, [esi + TCP_SOCKET.RemotePort]
304
        stosw
308
        stosw
305
        mov     eax, [esi + TCP_SOCKET.SND_NXT]
309
        mov     eax, [esi + TCP_SOCKET.SND_NXT]
306
        bswap   eax
310
        bswap   eax
307
        stosd
311
        stosd
308
        mov     eax, [esi + TCP_SOCKET.RCV_NXT]
312
        mov     eax, [esi + TCP_SOCKET.RCV_NXT]
309
        bswap   eax
313
        bswap   eax
310
        stosd
314
        stosd
311
        mov     al, 0x50        ; Dataoffset: 20 bytes (TCP_header.DataOffset)
315
        mov     al, 0x50        ; Dataoffset: 20 bytes (TCP_header.DataOffset)
312
        stosb
316
        stosb
313
        mov     al, cl
317
        mov     al, cl
314
        stosb
318
        stosb
315
;        mov     ax, [esi + TCP_SOCKET.RCV_WND]
319
;        mov     ax, [esi + TCP_SOCKET.RCV_WND]
316
;        rol     ax, 8
320
;        rol     ax, 8
317
        mov     ax, 0x00a0      ;;;;;;; FIXME
321
        mov     ax, 0x00a0      ;;;;;;; FIXME
318
        stosw                   ; window
322
        stosw                   ; window
319
        xor     eax, eax
323
        xor     eax, eax
320
        stosd                   ; checksum + urgentpointer
324
        stosd                   ; checksum + urgentpointer
321
 
325
 
322
;---------------------
326
;---------------------
323
; Fill in the checksum
327
; Fill in the checksum
324
 
328
 
325
  .checksum:
329
  .checksum:
326
        sub     edi, sizeof.TCP_header
330
        sub     edi, sizeof.TCP_header
327
        mov     ecx, sizeof.TCP_header
331
        mov     ecx, sizeof.TCP_header
328
        xchg    esi, edi
332
        xchg    esi, edi
329
        TCP_checksum (edi + IP_SOCKET.LocalIP), (edi + IP_SOCKET.RemoteIP)
333
        TCP_checksum (edi + IP_SOCKET.LocalIP), (edi + IP_SOCKET.RemoteIP)
330
        mov     [esi+TCP_header.Checksum], dx
334
        mov     [esi+TCP_header.Checksum], dx
331
 
335
 
332
;--------------------
336
;--------------------
333
; And send the segment
337
; And send the segment
334
 
338
 
335
        call    [ebx + NET_DEVICE.transmit]
339
        call    [ebx + NET_DEVICE.transmit]
336
        test    eax, eax
340
        test    eax, eax
337
        jnz     @f
341
        jnz     @f
338
        call    NET_ptr_to_num4
342
        call    NET_ptr_to_num4
339
        inc     [TCP_segments_tx + edi]
343
        inc     [TCP_segments_tx + edi]
340
       @@:
344
       @@:
341
        ret
345
        ret
342
 
346
 
343
  .error:
347
  .error:
344
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: failed\n"
348
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: failed\n"
345
        add     esp, 2 + 4
349
        add     esp, 2 + 4
346
 
350
 
347
        ret
351
        ret
348
 
352
 
349
 
-
 
350
 
-
 
351
 
-
 
-
 
353
 
352
 
354
;-----------------------------------------------------------------
353
 
-
 
354
 
-
 
355
 
-
 
356
;-------------------------
355
;
357
; TCP_respond_segment:
356
; TCP_respond_segment:
-
 
357
;
358
;
358
;  IN:  ebx = device ptr
359
;  IN:  edx = segment ptr (a previously received segment)
359
;       edx = segment ptr (a previously received segment)
360
;       edi = ptr to dest and src IPv4 addresses
360
;       edi = ptr to IPv4 header
-
 
361
;        cl = flags
-
 
362
;
-
 
363
;  OUT: /
-
 
364
;
361
;        cl = flags
365
;-----------------------------------------------------------------
362
 
366
 
363
align 4
367
align 4
364
TCP_respond_segment:
368
TCP_respond_segment:
365
 
369
 
366
        DEBUGF  DEBUG_NETWORK_VERBOSE,"TCP_respond_segment: frame=%x flags=%x\n", edx, cl
370
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_respond_segment: frame=%x flags=%x\n", edx, cl
367
 
371
 
368
;---------------------
372
;---------------------
369
; Create the IP packet
373
; Create the IP packet
370
 
374
 
371
        push    cx edx
375
        push    cx edx
372
        mov     edx, [edi + 4]
376
        mov     edx, [edi + IPv4_header.DestinationAddress]
373
        mov     eax, [edi]
377
        mov     edi, [edi + IPv4_header.SourceAddress]
374
        mov     ecx, sizeof.TCP_header
378
        mov     ecx, sizeof.TCP_header
375
        mov     di, IP_PROTO_TCP shl 8 + 128
379
        mov     ax, IP_PROTO_TCP shl 8 + 128
376
        xor     ebx, ebx                        ;;; fixme
-
 
377
        call    IPv4_output
380
        call    IPv4_output
378
        jz      .error
381
        jz      .error
379
        pop     esi cx
382
        pop     esi cx
380
 
383
 
381
        push    eax
384
        push    eax
382
 
385
 
383
;---------------------------------------------------
386
;---------------------------------------------------
384
; Fill in the TCP header by using a received segment
387
; Fill in the TCP header by using a received segment
385
 
388
 
386
        mov     ax, [esi + TCP_header.DestinationPort]
389
        mov     ax, [esi + TCP_header.DestinationPort]
387
        stosw
390
        stosw
388
        mov     ax, [esi + TCP_header.SourcePort]
391
        mov     ax, [esi + TCP_header.SourcePort]
389
        stosw
392
        stosw
390
        mov     eax, [esi + TCP_header.AckNumber]
393
        mov     eax, [esi + TCP_header.AckNumber]
391
        bswap   eax
394
        bswap   eax
392
        stosd
395
        stosd
393
        xor     eax, eax
396
        xor     eax, eax
394
        stosd
397
        stosd
395
        mov     al, 0x50        ; Dataoffset: 20 bytes (sizeof.TCP_header/4 shl 4)
398
        mov     al, 0x50        ; Dataoffset: 20 bytes (sizeof.TCP_header/4 shl 4)
396
        stosb
399
        stosb
397
        mov     al, cl
400
        mov     al, cl
398
        stosb
401
        stosb
399
        mov     ax, 1280
402
        mov     ax, 1280
400
        rol     ax, 8
403
        rol     ax, 8
401
        stosw                   ; window
404
        stosw                   ; window
402
        xor     eax, eax
405
        xor     eax, eax
403
        stosd                   ; checksum + urgentpointer
406
        stosd                   ; checksum + urgentpointer
404
 
407
 
405
;---------------------
408
;---------------------
406
; Fill in the checksum
409
; Fill in the checksum
407
 
410
 
408
        lea     esi, [edi - sizeof.TCP_header]
411
        lea     esi, [edi - sizeof.TCP_header]
409
        mov     ecx, sizeof.TCP_header
412
        mov     ecx, sizeof.TCP_header
410
        TCP_checksum (esi - sizeof.IPv4_header + IPv4_header.DestinationAddress),\      ; FIXME
413
        TCP_checksum (esi - sizeof.IPv4_header + IPv4_header.DestinationAddress),\      ; FIXME
411
                     (esi - sizeof.IPv4_header + IPv4_header.SourceAddress)
414
                     (esi - sizeof.IPv4_header + IPv4_header.SourceAddress)
412
        mov     [esi + TCP_header.Checksum], dx
415
        mov     [esi + TCP_header.Checksum], dx
413
 
416
 
414
;--------------------
417
;--------------------
415
; And send the segment
418
; And send the segment
416
 
419
 
417
        call    [ebx + NET_DEVICE.transmit]
420
        call    [ebx + NET_DEVICE.transmit]
418
        test    eax, eax
421
        test    eax, eax
419
        jnz     @f
422
        jnz     @f
420
        call    NET_ptr_to_num4
423
        call    NET_ptr_to_num4
421
        inc     [TCP_segments_tx + edi]
424
        inc     [TCP_segments_tx + edi]
422
       @@:
425
       @@:
423
        ret
426
        ret
424
 
427
 
425
  .error:
428
  .error:
426
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_respond_segment: failed\n"
429
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_respond_segment: failed\n"
427
        add     esp, 2+4
430
        add     esp, 2+4
428
 
431
 
429
        ret
432
        ret
430
 
433
 
431
 
434
 
432
macro   TCPT_RANGESET   timer, value, min, max {
435
macro   TCPT_RANGESET   timer, value, min, max {
433
 
436
 
434
local   .min
437
local   .min
435
local   .max
438
local   .max
436
local   .done
439
local   .done
437
 
440
 
438
        cmp     value, min
441
        cmp     value, min
439
        jb      .min
442
        jb      .min
440
        cmp     value, max
443
        cmp     value, max
441
        ja      .max
444
        ja      .max
442
 
445
 
443
        mov     timer, value
446
        mov     timer, value
444
        jmp     .done
447
        jmp     .done
445
 
448
 
446
  .min:
449
  .min:
447
        mov     timer, value
450
        mov     timer, value
448
        jmp     .done
451
        jmp     .done
449
 
452
 
450
  .max:
453
  .max:
451
        mov     timer, value
454
        mov     timer, value
452
        jmp     .done
455
        jmp     .done
453
 
456
 
454
  .done:
457
  .done:
455
}
458
}
456
 
459
 
457
 
460
 
458
align 4
461
align 4
459
TCP_set_persist:
462
TCP_set_persist:
460
 
463
 
461
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_set_persist\n"
464
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_set_persist\n"
462
 
465
 
463
; First, check if retransmit timer is not set, retransmit and persist are mutually exclusive
466
; First, check if retransmit timer is not set, retransmit and persist are mutually exclusive
464
 
467
 
465
        test    [eax + TCP_SOCKET.timer_flags], timer_flag_retransmission
468
        test    [eax + TCP_SOCKET.timer_flags], timer_flag_retransmission
466
        jnz     .exit
469
        jnz     .exit
467
 
470
 
468
; calculate RTO
471
; calculate RTO
469
        push    ebx
472
        push    ebx
470
        mov     ebx, [eax + TCP_SOCKET.t_srtt]
473
        mov     ebx, [eax + TCP_SOCKET.t_srtt]
471
        shr     ebx, 2
474
        shr     ebx, 2
472
        add     ebx, [eax + TCP_SOCKET.t_rttvar]
475
        add     ebx, [eax + TCP_SOCKET.t_rttvar]
473
        shr     ebx, 1
476
        shr     ebx, 1
474
 
477
 
475
        mov     cl, [eax + TCP_SOCKET.t_rxtshift]
478
        mov     cl, [eax + TCP_SOCKET.t_rxtshift]
476
        shl     ebx, cl
479
        shl     ebx, cl
477
 
480
 
478
; Start/restart persistance timer.
481
; Start/restart persistance timer.
479
 
482
 
480
        TCPT_RANGESET   [eax + TCP_SOCKET.timer_persist], ebx, TCP_time_pers_min, TCP_time_pers_max
483
        TCPT_RANGESET   [eax + TCP_SOCKET.timer_persist], ebx, TCP_time_pers_min, TCP_time_pers_max
481
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
484
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
482
        pop     ebx
485
        pop     ebx
483
 
486
 
484
        cmp     [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift
487
        cmp     [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift
485
        jae     @f
488
        jae     @f
486
        inc     [eax + TCP_SOCKET.t_rxtshift]
489
        inc     [eax + TCP_SOCKET.t_rxtshift]
487
      @@:
490
      @@:
488
  .exit:
491
  .exit:
489
 
492
 
490
        ret
493
        ret
491
 
494
 
492
 
495
 
493
 
496
 
494
; eax = rtt
497
; eax = rtt
495
; ebx = socket ptr
498
; ebx = socket ptr
496
 
499
 
497
align 4
500
align 4
498
TCP_xmit_timer:
501
TCP_xmit_timer:
499
 
502
 
500
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_xmit_timer: socket=%x rtt=%d0ms\n", ebx, eax
503
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_xmit_timer: socket=%x rtt=%d0ms\n", ebx, eax
501
 
504
 
502
;TODO: update stats
505
;TODO: update stats
503
 
506
 
504
        cmp     [ebx + TCP_SOCKET.t_rtt], 0
507
        cmp     [ebx + TCP_SOCKET.t_rtt], 0
505
        je      .no_rtt_yet
508
        je      .no_rtt_yet
506
 
509
 
507
; srtt is stored as a fixed point with 3 bits after the binary point.
510
; srtt is stored as a fixed point with 3 bits after the binary point.
508
; The following magic is equivalent of the smoothing algorithm in rfc793 with an alpha of .875
511
; The following magic is equivalent of the smoothing algorithm in rfc793 with an alpha of .875
509
; (srtt = rtt/8 + srtt*7/8 in fixed point)
512
; (srtt = rtt/8 + srtt*7/8 in fixed point)
510
; Adjust rtt to origin 0.
513
; Adjust rtt to origin 0.
511
 
514
 
512
        push    ecx
515
        push    ecx
513
        mov     ecx, [ebx + TCP_SOCKET.t_srtt]
516
        mov     ecx, [ebx + TCP_SOCKET.t_srtt]
514
        shr     ecx, TCP_RTT_SHIFT
517
        shr     ecx, TCP_RTT_SHIFT
515
        sub     eax, ecx
518
        sub     eax, ecx
516
        dec     eax
519
        dec     eax
517
        pop     ecx
520
        pop     ecx
518
 
521
 
519
        add     [ebx + TCP_SOCKET.t_srtt], eax
522
        add     [ebx + TCP_SOCKET.t_srtt], eax
520
        ja      @f
523
        ja      @f
521
        mov     [ebx + TCP_SOCKET.t_srtt], 1
524
        mov     [ebx + TCP_SOCKET.t_srtt], 1
522
  @@:
525
  @@:
523
 
526
 
524
; We accumulate a smoothed rtt variance (actually, a smoothed mean difference),
527
; We accumulate a smoothed rtt variance (actually, a smoothed mean difference),
525
; then set the retransmit timer to smoothed rtt + 4 times the smoothed variance.
528
; then set the retransmit timer to smoothed rtt + 4 times the smoothed variance.
526
; rttvar is stored as fixed point with 2 bits after the binary point.
529
; rttvar is stored as fixed point with 2 bits after the binary point.
527
; The following is equivalent to rfc793 smoothing with an alpha of .75
530
; The following is equivalent to rfc793 smoothing with an alpha of .75
528
; (rttvar = rttvar*3/4 + delta/4) (delta = eax)
531
; (rttvar = rttvar*3/4 + delta/4) (delta = eax)
529
 
532
 
530
; get abs(eax)
533
; get abs(eax)
531
        push    edx
534
        push    edx
532
        cdq
535
        cdq
533
        xor     eax, edx
536
        xor     eax, edx
534
        sub     eax, edx
537
        sub     eax, edx
535
 
538
 
536
        mov     edx, [ebx + TCP_SOCKET.t_rttvar]
539
        mov     edx, [ebx + TCP_SOCKET.t_rttvar]
537
        shr     edx, TCP_RTTVAR_SHIFT
540
        shr     edx, TCP_RTTVAR_SHIFT
538
        sub     eax, edx
541
        sub     eax, edx
539
        pop     edx
542
        pop     edx
540
 
543
 
541
        add     [ebx + TCP_SOCKET.t_rttvar], eax
544
        add     [ebx + TCP_SOCKET.t_rttvar], eax
542
        ja      @f
545
        ja      @f
543
        mov     [ebx + TCP_SOCKET.t_rttvar], 1
546
        mov     [ebx + TCP_SOCKET.t_rttvar], 1
544
  @@:
547
  @@:
545
        ret
548
        ret
546
 
549
 
547
 
550
 
548
  .no_rtt_yet:
551
  .no_rtt_yet:
549
 
552
 
550
        push    ecx
553
        push    ecx
551
        mov     ecx, eax
554
        mov     ecx, eax
552
        shl     ecx, TCP_RTT_SHIFT
555
        shl     ecx, TCP_RTT_SHIFT
553
        mov     [ebx + TCP_SOCKET.t_srtt], ecx
556
        mov     [ebx + TCP_SOCKET.t_srtt], ecx
554
 
557
 
555
        shl     eax, TCP_RTTVAR_SHIFT - 1
558
        shl     eax, TCP_RTTVAR_SHIFT - 1
556
        mov     [ebx + TCP_SOCKET.t_rttvar], eax
559
        mov     [ebx + TCP_SOCKET.t_rttvar], eax
557
        pop     ecx
560
        pop     ecx
558
 
561
 
559
        ret
562
        ret
560
 
563
 
561
 
564
 
562
 
565
 
563
 
566
 
564
; eax = max segment size
567
; eax = max segment size
565
; ebx = socket ptr
568
; ebx = socket ptr
566
align 4
569
align 4
567
TCP_mss:
570
TCP_mss:
568
 
571
 
569
        cmp     eax, 1420                               ; FIXME
572
        cmp     eax, 1420                               ; FIXME
570
        jbe     @f
573
        jbe     @f
571
        mov     eax, 1420
574
        mov     eax, 1420
572
  @@:
575
  @@:
573
        mov     [ebx + TCP_SOCKET.t_maxseg], eax
576
        mov     [ebx + TCP_SOCKET.t_maxseg], eax
574
 
577
 
575
 
578
 
576
        ret
579
        ret
577
 
580
 
578
 
581
 
579
 
582
 
580
 
583
 
581
; ebx = socket ptr
584
; ebx = socket ptr
582
; edx = segment ptr
585
; edx = segment ptr
583
align 4
586
align 4
584
TCP_reassemble:
587
TCP_reassemble:
585
 
588
 
586
 
589
 
587
 
590
 
588
        ret
591
        ret