Subversion Repositories Kolibri OS

Rev

Rev 3556 | Go to most recent revision | Details | 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
 
122
        DEBUGF  1,"TCP_pull_out_of_band\n"
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
 
148
        DEBUGF  1,"TCP_drop: %x\n", eax
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
 
187
        DEBUGF  1,"TCP_close: %x\n", eax
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
 
215
        DEBUGF  1,"TCP_outflags: socket=%x flags=%x\n", eax, dl
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
 
251
        DEBUGF  1,"TCP_respond_socket: socket=%x flags=%x\n", ebx, cl
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:
308
        DEBUGF  1,"TCP_respond_socket: failed\n"
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
 
330
        DEBUGF  1,"TCP_respond_segment: frame=%x flags=%x\n", edx, cl
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:
384
        DEBUGF  1,"TCP_respond_segment: failed\n"
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
 
419
        DEBUGF  1,"TCP_set_persist\n"
420
 
421
; First, check if retransmit timer is not set, retransmit and persist are mutually exclusive
422
 
423
        cmp     [eax + TCP_SOCKET.timer_retransmission], 0
424
        ja      @f
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
439
 
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
      @@:
446
 
447
        ret
448
 
449
 
450
 
451
; eax = rtt
452
; ebx = socket ptr
453
 
454
align 4
455
TCP_xmit_timer:
456
 
457
        DEBUGF  1,"TCP_xmit_timer: socket=%x rtt=%d0ms\n", ebx, eax
458
 
459
;TODO: update stats
460
 
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
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
534
 
535
 
536
 
537
 
538
; ebx = socket ptr
539
; edx = segment ptr
540
align 4
541
TCP_reassemble:
542
 
543
 
544
 
545
        ret
546