Subversion Repositories Kolibri OS

Rev

Rev 3589 | Rev 3725 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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