Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1763 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2362 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved.    ;;
1763 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
3143 hidnplayr 6
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
1763 hidnplayr 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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1733 hidnplayr 16
 
1763 hidnplayr 17
$Revision: 3514 $
1733 hidnplayr 18
 
2955 hidnplayr 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
 
2390 hidnplayr 24
macro   TCP_checksum IP1, IP2 {
1733 hidnplayr 25
 
26
;-------------
27
; Pseudoheader
28
 
2390 hidnplayr 29
        ; protocol type
30
        mov     edx, IP_PROTO_TCP
1733 hidnplayr 31
 
2390 hidnplayr 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]
1733 hidnplayr 37
 
2390 hidnplayr 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]
1733 hidnplayr 43
 
2390 hidnplayr 44
        ; size
45
        adc     dl, cl
46
        adc     dh, ch
1733 hidnplayr 47
 
2390 hidnplayr 48
        adc     edx, 0
49
 
1733 hidnplayr 50
;---------------------
51
; Real header and data
52
 
2390 hidnplayr 53
        push    esi
54
        call    checksum_1
55
        call    checksum_2
56
        pop     esi
1733 hidnplayr 57
 
2390 hidnplayr 58
}       ; returns in dx only
1733 hidnplayr 59
 
60
 
61
 
62
 
2390 hidnplayr 63
macro   TCP_sendseqinit ptr {
1733 hidnplayr 64
 
2390 hidnplayr 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
1733 hidnplayr 72
 
73
}
74
 
75
 
76
 
2390 hidnplayr 77
macro   TCP_rcvseqinit ptr {
1733 hidnplayr 78
 
2390 hidnplayr 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
1733 hidnplayr 85
 
86
}
87
 
88
 
89
 
2930 hidnplayr 90
macro   TCP_init_socket socket {
1733 hidnplayr 91
 
2612 hidnplayr 92
        mov     [socket + TCP_SOCKET.t_maxseg], TCP_mss_default
2953 hidnplayr 93
        mov     [socket + TCP_SOCKET.t_flags], TF_REQ_SCALE or TF_REQ_TSTMP
1733 hidnplayr 94
 
2612 hidnplayr 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
1733 hidnplayr 99
 
2612 hidnplayr 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
1733 hidnplayr 102
 
103
 
2612 hidnplayr 104
}
1733 hidnplayr 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
 
2390 hidnplayr 122
        DEBUGF  1,"TCP_pull_out_of_band\n"
1733 hidnplayr 123
 
2390 hidnplayr 124
        ;;;; 1282-1305
1733 hidnplayr 125
 
2390 hidnplayr 126
        ret
1733 hidnplayr 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
 
2891 hidnplayr 148
        DEBUGF  1,"TCP_drop: %x\n", eax
1733 hidnplayr 149
 
2390 hidnplayr 150
        cmp     [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
151
        jb      .no_syn_received
1733 hidnplayr 152
 
2390 hidnplayr 153
        mov     [eax + TCP_SOCKET.t_state], TCPS_CLOSED
1733 hidnplayr 154
 
2390 hidnplayr 155
        call    TCP_output
1733 hidnplayr 156
 
157
;;; TODO: update stats
158
 
2390 hidnplayr 159
        jmp     TCP_close
1733 hidnplayr 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
 
2390 hidnplayr 167
        mov     [eax + SOCKET.errorcode], ebx
1733 hidnplayr 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
 
2869 hidnplayr 187
        DEBUGF  1,"TCP_close: %x\n", eax
1733 hidnplayr 188
 
189
;;; TODO: update RTT and mean deviation
190
;;; TODO: update slow start threshold
191
 
2390 hidnplayr 192
        call    SOCKET_is_disconnected
3162 hidnplayr 193
        call    SOCKET_free
1733 hidnplayr 194
 
2390 hidnplayr 195
        ret
1733 hidnplayr 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
 
2390 hidnplayr 212
        mov     edx, [eax + TCP_SOCKET.t_state]
213
        movzx   edx, byte [edx + .flaglist]
1733 hidnplayr 214
 
2891 hidnplayr 215
        DEBUGF  1,"TCP_outflags: socket=%x flags=%x\n", eax, dl
1733 hidnplayr 216
 
2390 hidnplayr 217
        ret
1733 hidnplayr 218
 
219
  .flaglist:
220
 
2390 hidnplayr 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
2890 hidnplayr 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
2390 hidnplayr 230
        db               TH_ACK         ; TCPS_FIN_WAIT_2
231
        db               TH_ACK         ; TCPS_TIMED_WAIT
1733 hidnplayr 232
 
233
 
234
 
235
 
236
 
237
 
238
;---------------------------------------
239
;
1830 hidnplayr 240
; The fast way to send an ACK/RST/keepalive segment
1733 hidnplayr 241
;
3143 hidnplayr 242
; TCP_respond
1733 hidnplayr 243
;
244
;  IN:  ebx = socket ptr
245
;        cl = flags
246
;
247
;--------------------------------------
248
align 4
3143 hidnplayr 249
TCP_respond:
1733 hidnplayr 250
 
2891 hidnplayr 251
        DEBUGF  1,"TCP_respond_socket: socket=%x flags=%x\n", ebx, cl
1733 hidnplayr 252
 
253
;---------------------
254
; Create the IP packet
255
 
2390 hidnplayr 256
        push    cx ebx
257
        mov     eax, [ebx + IP_SOCKET.RemoteIP]
2877 hidnplayr 258
        mov     edx, [ebx + IP_SOCKET.LocalIP]
2390 hidnplayr 259
        mov     ecx, sizeof.TCP_header
2877 hidnplayr 260
        mov     di, IP_PROTO_TCP shl 8 + 128
2390 hidnplayr 261
        call    IPv4_output
262
        test    edi, edi
263
        jz      .error
264
        pop     esi cx
265
        push    edx eax
1733 hidnplayr 266
 
267
;-----------------------------------------------
268
; Fill in the TCP header by using the socket ptr
269
 
2390 hidnplayr 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
1830 hidnplayr 284
;        mov     ax, [esi + TCP_SOCKET.RCV_WND]
285
;        rol     ax, 8
2390 hidnplayr 286
        mov     ax, 0x00a0      ;;;;;;; FIXME
287
        stosw                   ; window
288
        xor     eax, eax
289
        stosd                   ; checksum + urgentpointer
1733 hidnplayr 290
 
291
;---------------------
292
; Fill in the checksum
293
 
294
  .checksum:
2390 hidnplayr 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
1733 hidnplayr 300
 
301
;--------------------
302
; And send the segment
303
 
2390 hidnplayr 304
        call    [ebx + NET_DEVICE.transmit]
305
        ret
1733 hidnplayr 306
 
307
  .error:
2891 hidnplayr 308
        DEBUGF  1,"TCP_respond_socket: failed\n"
309
        add     esp, 2 + 4
1733 hidnplayr 310
 
2390 hidnplayr 311
        ret
1733 hidnplayr 312
 
313
 
314
 
315
 
316
 
317
 
318
 
319
 
320
;-------------------------
3270 hidnplayr 321
; TCP_respond_segment:
1733 hidnplayr 322
;
2600 hidnplayr 323
;  IN:  edx = segment ptr (a previously received segment)
2308 hidnplayr 324
;       edi = ptr to dest and src IPv4 addresses
1733 hidnplayr 325
;        cl = flags
326
 
327
align 4
328
TCP_respond_segment:
329
 
3270 hidnplayr 330
        DEBUGF  1,"TCP_respond_segment: frame=%x flags=%x\n", edx, cl
1733 hidnplayr 331
 
332
;---------------------
333
; Create the IP packet
334
 
2600 hidnplayr 335
        push    cx edx
2390 hidnplayr 336
        mov     ebx, [edi + 4]
337
        mov     eax, [edi]
338
        mov     ecx, sizeof.TCP_header
3270 hidnplayr 339
        mov     di, IP_PROTO_TCP shl 8 + 128
2390 hidnplayr 340
        call    IPv4_output
341
        jz      .error
2600 hidnplayr 342
        pop     esi cx
1733 hidnplayr 343
 
2390 hidnplayr 344
        push    edx eax
1733 hidnplayr 345
 
346
;---------------------------------------------------
347
; Fill in the TCP header by using a received segment
348
 
2390 hidnplayr 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
3275 hidnplayr 358
        mov     al, 0x50        ; Dataoffset: 20 bytes (sizeof.TCP_header/4 shl 4)
2390 hidnplayr 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
1733 hidnplayr 367
 
368
;---------------------
369
; Fill in the checksum
370
 
2390 hidnplayr 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)
3270 hidnplayr 375
        mov     [esi + TCP_header.Checksum], dx
1733 hidnplayr 376
 
377
;--------------------
378
; And send the segment
379
 
2390 hidnplayr 380
        call    [ebx + NET_DEVICE.transmit]
381
        ret
1733 hidnplayr 382
 
383
  .error:
2891 hidnplayr 384
        DEBUGF  1,"TCP_respond_segment: failed\n"
2390 hidnplayr 385
        add     esp, 2+4
1733 hidnplayr 386
 
2390 hidnplayr 387
        ret
2362 hidnplayr 388
 
389
 
2955 hidnplayr 390
macro   TCPT_RANGESET   timer, value, min, max {
2362 hidnplayr 391
 
2955 hidnplayr 392
local   .min
393
local   .max
394
local   .done
2362 hidnplayr 395
 
2955 hidnplayr 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
 
3514 hidnplayr 419
        DEBUGF  1,"TCP_set_persist\n"
420
 
2937 hidnplayr 421
; First, check if retransmit timer is not set, retransmit and persist are mutually exclusive
422
 
2955 hidnplayr 423
        cmp     [eax + TCP_SOCKET.timer_retransmission], 0
3514 hidnplayr 424
        ja      @f
2937 hidnplayr 425
 
426
; calculate RTO
2955 hidnplayr 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
2937 hidnplayr 432
 
2955 hidnplayr 433
        mov     cl, [eax + TCP_SOCKET.t_rxtshift]
434
        shl     ebx, cl
2937 hidnplayr 435
 
436
; Start/restart persistance timer.
437
 
2955 hidnplayr 438
        TCPT_RANGESET   [eax + TCP_SOCKET.timer_persist], ebx, TCP_time_pers_min, TCP_time_pers_max
2362 hidnplayr 439
 
2955 hidnplayr 440
        pop     ebx
2937 hidnplayr 441
 
2955 hidnplayr 442
        cmp     [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift
443
        jae     @f
444
        inc     [eax + TCP_SOCKET.t_rxtshift]
445
      @@:
2930 hidnplayr 446
 
2955 hidnplayr 447
        ret
2937 hidnplayr 448
 
449
 
2955 hidnplayr 450
 
2930 hidnplayr 451
; eax = rtt
452
; ebx = socket ptr
453
 
454
align 4
455
TCP_xmit_timer:
456
 
2948 hidnplayr 457
        DEBUGF  1,"TCP_xmit_timer: socket=%x rtt=%d0ms\n", ebx, eax
458
 
2937 hidnplayr 459
;TODO: update stats
2930 hidnplayr 460
 
2937 hidnplayr 461
        cmp     [ebx + TCP_SOCKET.t_rtt], 0
462
        je      .no_rtt_yet
463
 
464
; srtt is stored as a fixed point with 3 bits after the binary point.
465
; The following magic is equivalent of the smoothing algorithm in rfc793 with an alpha of .875
466
; (srtt = rtt/8 + srtt*7/8 in fixed point)
467
; Adjust rtt to origin 0.
468
 
469
        push    ecx
470
        mov     ecx, [ebx + TCP_SOCKET.t_srtt]
471
        shr     ecx, TCP_RTT_SHIFT
472
        sub     eax, ecx
473
        dec     eax
474
        pop     ecx
475
 
476
        add     [ebx + TCP_SOCKET.t_srtt], eax
477
        ja      @f
478
        mov     [ebx + TCP_SOCKET.t_srtt], 1
479
  @@:
480
 
481
; We accumulate a smoothed rtt variance (actually, a smoothed mean difference),
482
; then set the retransmit timer to smoothed rtt + 4 times the smoothed variance.
483
; rttvar is stored as fixed point with 2 bits after the binary point.
484
; The following is equivalent to rfc793 smoothing with an alpha of .75
485
; (rttvar = rttvar*3/4 + delta/4) (delta = eax)
486
 
487
; get abs(eax)
488
        push    edx
489
        cdq
490
        xor     eax, edx
491
        sub     eax, edx
492
 
493
        mov     edx, [ebx + TCP_SOCKET.t_rttvar]
494
        shr     edx, TCP_RTTVAR_SHIFT
495
        sub     eax, edx
496
        pop     edx
497
 
498
        add     [ebx + TCP_SOCKET.t_rttvar], eax
499
        ja      @f
500
        mov     [ebx + TCP_SOCKET.t_rttvar], 1
501
  @@:
502
        ret
503
 
504
 
505
  .no_rtt_yet:
506
 
507
        push    ecx
508
        mov     ecx, eax
509
        shl     ecx, TCP_RTT_SHIFT
510
        mov     [ebx + TCP_SOCKET.t_srtt], ecx
511
 
512
        shl     eax, TCP_RTTVAR_SHIFT - 1
513
        mov     [ebx + TCP_SOCKET.t_rttvar], eax
514
        pop     ecx
515
 
516
        ret
3144 hidnplayr 517
 
518
 
519
 
520
 
521
; eax = max segment size
522
; ebx = socket ptr
523
align 4
524
TCP_mss:
525
 
526
        cmp     eax, 1420                               ; FIXME
527
        jbe     @f
528
        mov     eax, 1420
529
  @@:
530
        mov     [ebx + TCP_SOCKET.t_maxseg], eax
531
 
532
 
533
        ret
3406 hidnplayr 534
 
535
 
536
 
537
 
538
; ebx = socket ptr
539
; edx = segment ptr
540
align 4
541
TCP_reassemble:
542
 
543
 
544
 
545
        ret
546