Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 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
 
3556 hidnplayr 122
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_pull_out_of_band\n"
3545 hidnplayr 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
 
3556 hidnplayr 148
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_drop: %x\n", eax
3545 hidnplayr 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
 
3674 hidnplayr 167
;        mov     [eax + SOCKET.errorcode], ebx
3545 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
 
3556 hidnplayr 187
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_close: %x\n", eax
3545 hidnplayr 188
 
189
;;; TODO: update RTT and mean deviation
190
;;; TODO: update slow start threshold
191
 
192
        call    SOCKET_is_disconnected
3737 hidnplayr 193
;;        call    SOCKET_free
3545 hidnplayr 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
 
3556 hidnplayr 215
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_outflags: socket=%x flags=%x\n", eax, dl
3545 hidnplayr 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
 
3556 hidnplayr 251
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: socket=%x flags=%x\n", ebx, cl
3545 hidnplayr 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]
3644 hidnplayr 305
        test    eax, eax
306
        jnz     @f
307
        call    NET_ptr_to_num4
308
        inc     [TCP_segments_tx + edi]
309
       @@:
3545 hidnplayr 310
        ret
311
 
312
  .error:
3556 hidnplayr 313
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: failed\n"
3545 hidnplayr 314
        add     esp, 2 + 4
315
 
316
        ret
317
 
318
 
319
 
320
 
321
 
322
 
323
 
324
 
325
;-------------------------
326
; TCP_respond_segment:
327
;
328
;  IN:  edx = segment ptr (a previously received segment)
329
;       edi = ptr to dest and src IPv4 addresses
330
;        cl = flags
331
 
332
align 4
333
TCP_respond_segment:
334
 
3556 hidnplayr 335
        DEBUGF  DEBUG_NETWORK_VERBOSE,"TCP_respond_segment: frame=%x flags=%x\n", edx, cl
3545 hidnplayr 336
 
337
;---------------------
338
; Create the IP packet
339
 
340
        push    cx edx
341
        mov     ebx, [edi + 4]
342
        mov     eax, [edi]
343
        mov     ecx, sizeof.TCP_header
344
        mov     di, IP_PROTO_TCP shl 8 + 128
345
        call    IPv4_output
346
        jz      .error
347
        pop     esi cx
348
 
349
        push    edx eax
350
 
351
;---------------------------------------------------
352
; Fill in the TCP header by using a received segment
353
 
354
        mov     ax, [esi + TCP_header.DestinationPort]
355
        stosw
356
        mov     ax, [esi + TCP_header.SourcePort]
357
        stosw
358
        mov     eax, [esi + TCP_header.AckNumber]
359
        bswap   eax
360
        stosd
361
        xor     eax, eax
362
        stosd
363
        mov     al, 0x50        ; Dataoffset: 20 bytes (sizeof.TCP_header/4 shl 4)
364
        stosb
365
        mov     al, cl
366
        stosb
367
        mov     ax, 1280
368
        rol     ax, 8
369
        stosw                   ; window
370
        xor     eax, eax
371
        stosd                   ; checksum + urgentpointer
372
 
373
;---------------------
374
; Fill in the checksum
375
 
376
        lea     esi, [edi - sizeof.TCP_header]
377
        mov     ecx, sizeof.TCP_header
378
        TCP_checksum (esi - sizeof.IPv4_header + IPv4_header.DestinationAddress),\      ; FIXME
379
                     (esi - sizeof.IPv4_header + IPv4_header.SourceAddress)
380
        mov     [esi + TCP_header.Checksum], dx
381
 
382
;--------------------
383
; And send the segment
384
 
385
        call    [ebx + NET_DEVICE.transmit]
3644 hidnplayr 386
        test    eax, eax
387
        jnz     @f
388
        call    NET_ptr_to_num4
389
        inc     [TCP_segments_tx + edi]
390
       @@:
3545 hidnplayr 391
        ret
392
 
393
  .error:
3556 hidnplayr 394
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_respond_segment: failed\n"
3545 hidnplayr 395
        add     esp, 2+4
396
 
397
        ret
398
 
399
 
400
macro   TCPT_RANGESET   timer, value, min, max {
401
 
402
local   .min
403
local   .max
404
local   .done
405
 
406
        cmp     value, min
407
        jb      .min
408
        cmp     value, max
409
        ja      .max
410
 
411
        mov     timer, value
412
        jmp     .done
413
 
414
  .min:
415
        mov     timer, value
416
        jmp     .done
417
 
418
  .max:
419
        mov     timer, value
420
        jmp     .done
421
 
422
  .done:
423
}
424
 
425
 
426
align 4
427
TCP_set_persist:
428
 
3556 hidnplayr 429
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_set_persist\n"
3545 hidnplayr 430
 
431
; First, check if retransmit timer is not set, retransmit and persist are mutually exclusive
432
 
3600 hidnplayr 433
        test    [eax + TCP_SOCKET.timer_flags], timer_flag_retransmission
434
        jnz     .exit
3545 hidnplayr 435
 
436
; calculate RTO
437
        push    ebx
438
        mov     ebx, [eax + TCP_SOCKET.t_srtt]
439
        shr     ebx, 2
440
        add     ebx, [eax + TCP_SOCKET.t_rttvar]
441
        shr     ebx, 1
442
 
443
        mov     cl, [eax + TCP_SOCKET.t_rxtshift]
444
        shl     ebx, cl
445
 
446
; Start/restart persistance timer.
447
 
448
        TCPT_RANGESET   [eax + TCP_SOCKET.timer_persist], ebx, TCP_time_pers_min, TCP_time_pers_max
3600 hidnplayr 449
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
3545 hidnplayr 450
        pop     ebx
451
 
452
        cmp     [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift
453
        jae     @f
454
        inc     [eax + TCP_SOCKET.t_rxtshift]
455
      @@:
3600 hidnplayr 456
  .exit:
3545 hidnplayr 457
 
458
        ret
459
 
460
 
461
 
462
; eax = rtt
463
; ebx = socket ptr
464
 
465
align 4
466
TCP_xmit_timer:
467
 
3556 hidnplayr 468
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_xmit_timer: socket=%x rtt=%d0ms\n", ebx, eax
3545 hidnplayr 469
 
470
;TODO: update stats
471
 
472
        cmp     [ebx + TCP_SOCKET.t_rtt], 0
473
        je      .no_rtt_yet
474
 
475
; srtt is stored as a fixed point with 3 bits after the binary point.
476
; The following magic is equivalent of the smoothing algorithm in rfc793 with an alpha of .875
477
; (srtt = rtt/8 + srtt*7/8 in fixed point)
478
; Adjust rtt to origin 0.
479
 
480
        push    ecx
481
        mov     ecx, [ebx + TCP_SOCKET.t_srtt]
482
        shr     ecx, TCP_RTT_SHIFT
483
        sub     eax, ecx
484
        dec     eax
485
        pop     ecx
486
 
487
        add     [ebx + TCP_SOCKET.t_srtt], eax
488
        ja      @f
489
        mov     [ebx + TCP_SOCKET.t_srtt], 1
490
  @@:
491
 
492
; We accumulate a smoothed rtt variance (actually, a smoothed mean difference),
493
; then set the retransmit timer to smoothed rtt + 4 times the smoothed variance.
494
; rttvar is stored as fixed point with 2 bits after the binary point.
495
; The following is equivalent to rfc793 smoothing with an alpha of .75
496
; (rttvar = rttvar*3/4 + delta/4) (delta = eax)
497
 
498
; get abs(eax)
499
        push    edx
500
        cdq
501
        xor     eax, edx
502
        sub     eax, edx
503
 
504
        mov     edx, [ebx + TCP_SOCKET.t_rttvar]
505
        shr     edx, TCP_RTTVAR_SHIFT
506
        sub     eax, edx
507
        pop     edx
508
 
509
        add     [ebx + TCP_SOCKET.t_rttvar], eax
510
        ja      @f
511
        mov     [ebx + TCP_SOCKET.t_rttvar], 1
512
  @@:
513
        ret
514
 
515
 
516
  .no_rtt_yet:
517
 
518
        push    ecx
519
        mov     ecx, eax
520
        shl     ecx, TCP_RTT_SHIFT
521
        mov     [ebx + TCP_SOCKET.t_srtt], ecx
522
 
523
        shl     eax, TCP_RTTVAR_SHIFT - 1
524
        mov     [ebx + TCP_SOCKET.t_rttvar], eax
525
        pop     ecx
526
 
527
        ret
528
 
529
 
530
 
531
 
532
; eax = max segment size
533
; ebx = socket ptr
534
align 4
535
TCP_mss:
536
 
537
        cmp     eax, 1420                               ; FIXME
538
        jbe     @f
539
        mov     eax, 1420
540
  @@:
541
        mov     [ebx + TCP_SOCKET.t_maxseg], eax
542
 
543
 
544
        ret
545
 
546
 
547
 
548
 
549
; ebx = socket ptr
550
; edx = segment ptr
551
align 4
552
TCP_reassemble:
553
 
554
 
555
 
556
        ret
557