Subversion Repositories Kolibri OS

Rev

Rev 2402 | 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
;;                                                                 ;;
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: 2555 $
18
 
1733 hidnplayr 19
;-----------------------------------------------------------------
20
;
21
; TCP_input:
22
;
23
;  IN:  [esp] = ptr to buffer
24
;       [esp+4] = buffer size
25
;       ebx = ptr to device struct
26
;       ecx = segment size
2310 hidnplayr 27
;       esi = ptr to TCP segment
2308 hidnplayr 28
;       edi = ptr to ipv4 source address, followed by ipv4 dest address
1733 hidnplayr 29
;
30
;  OUT: /
31
;
32
;-----------------------------------------------------------------
1830 hidnplayr 33
 
1733 hidnplayr 34
align 4
35
TCP_input:
36
 
2390 hidnplayr 37
        DEBUGF  1,"TCP_input size=%u\n", ecx
1733 hidnplayr 38
 
2390 hidnplayr 39
; First, re-calculate the checksum
1733 hidnplayr 40
 
2390 hidnplayr 41
        push    ecx esi
42
        pushw   [esi + TCP_header.Checksum]
43
        mov     [esi + TCP_header.Checksum], 0
44
        TCP_checksum (edi), (edi+4)
45
        pop     cx              ; previous checksum
46
        cmp     cx, dx
47
        pop     edx ecx
48
        jne     .drop_not_locked
1733 hidnplayr 49
 
2390 hidnplayr 50
        DEBUGF  1,"Checksum ok\n"
1733 hidnplayr 51
 
2390 hidnplayr 52
        and     [edx + TCP_header.DataOffset], 0xf0                     ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
53
        shr     [edx + TCP_header.DataOffset], 2
54
        cmp     [edx + TCP_header.DataOffset], sizeof.TCP_header        ; Now see if it's at least the size of a standard TCP header
55
        jb      .drop_not_locked                                        ; If not, drop the packet
1733 hidnplayr 56
 
2390 hidnplayr 57
        movzx   eax, [edx + TCP_header.DataOffset]
58
        sub     ecx, eax                                                ; substract TCP header size from total segment size
59
        jb      .drop_not_locked                                        ; If total segment size is less then the advertised header size, drop packet
60
        DEBUGF  1,"we got %u bytes of data\n", ecx
1733 hidnplayr 61
 
62
;-----------------------------------------------------------------------------------------
63
; Check if this packet has a timestamp option (We do it here so we can process it quickly)
64
 
2390 hidnplayr 65
        cmp     eax, sizeof.TCP_header + 12                             ; Timestamp option is 12 bytes
66
        jb      .no_timestamp
67
        je      .is_ok
1733 hidnplayr 68
 
2390 hidnplayr 69
        cmp     byte [edx + sizeof.TCP_header + 12], TCP_OPT_EOL                ; end of option list
70
        jne     .no_timestamp
1733 hidnplayr 71
 
72
  .is_ok:
2390 hidnplayr 73
        test    [edx + TCP_header.Flags], TH_SYN                                ; SYN flag must not be set
74
        jnz     .no_timestamp
1733 hidnplayr 75
 
2390 hidnplayr 76
        cmp     dword [edx + sizeof.TCP_header], 0x0101080a                     ; Timestamp header
77
        jne     .no_timestamp
1733 hidnplayr 78
 
2390 hidnplayr 79
        DEBUGF  1,"timestamp ok\n"
1733 hidnplayr 80
 
2390 hidnplayr 81
        ; TODO: Parse the option
82
        ; TODO: Set a Bit in the TCP to tell all options are parsed
1733 hidnplayr 83
 
84
  .no_timestamp:
85
 
86
;-------------------------------------------
87
; Convert Big-endian values to little endian
88
 
2390 hidnplayr 89
        ntohd   [edx + TCP_header.SequenceNumber]
90
        ntohd   [edx + TCP_header.AckNumber]
1733 hidnplayr 91
 
2390 hidnplayr 92
        ntohw   [edx + TCP_header.Window]
93
        ntohw   [edx + TCP_header.UrgentPointer]
94
        ntohw   [edx + TCP_header.SourcePort]
95
        ntohw   [edx + TCP_header.DestinationPort]
1733 hidnplayr 96
 
97
;------------------------------------------------------------
1831 hidnplayr 98
; Next thing to do is find the TCPS (thus, the socket pointer)
1733 hidnplayr 99
 
100
; IP Packet TCP Destination Port = local Port
101
; (IP Packet SenderAddress = Remote IP)  OR  (Remote IP = 0)
2309 hidnplayr 102
; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0)
1733 hidnplayr 103
 
2390 hidnplayr 104
        mov     ebx, net_sockets
105
        mov     si, [edx + TCP_header.DestinationPort]
1733 hidnplayr 106
 
107
  .socket_loop:
2390 hidnplayr 108
        mov     ebx, [ebx + SOCKET.NextPtr]
109
        or      ebx, ebx
110
        jz      .drop_with_reset_not_locked
1733 hidnplayr 111
 
2390 hidnplayr 112
        cmp     [ebx + SOCKET.Domain], AF_INET4
113
        jne     .socket_loop
1733 hidnplayr 114
 
2390 hidnplayr 115
        cmp     [ebx + SOCKET.Protocol], IP_PROTO_TCP
116
        jne     .socket_loop
1733 hidnplayr 117
 
2390 hidnplayr 118
        cmp     [ebx + TCP_SOCKET.LocalPort], si
119
        jne     .socket_loop
1733 hidnplayr 120
 
2390 hidnplayr 121
        mov     eax, [ebx + IP_SOCKET.RemoteIP]
122
        cmp     eax, [edi]                              ; Ipv4 source addres
123
        je      @f
124
        test    eax, eax
125
        jnz     .socket_loop
1733 hidnplayr 126
       @@:
127
 
2390 hidnplayr 128
        mov     ax, [ebx + TCP_SOCKET.RemotePort]
129
        cmp     [edx + TCP_header.SourcePort], ax
130
        je      .found_socket
131
        test    ax, ax
132
        jnz     .socket_loop
133
  .found_socket:                                        ; ebx now contains the socketpointer
134
        DEBUGF  1,"Socket ptr: %x\n", ebx
1733 hidnplayr 135
 
136
 
137
;----------------------------
138
; Check if socket isnt closed
139
 
2390 hidnplayr 140
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
141
        je      .drop_not_locked
1733 hidnplayr 142
 
143
;----------------
144
; Lock the socket
145
 
2402 hidnplayr 146
        pusha
147
        lea     ecx, [ebx + SOCKET.mutex]
148
        call    mutex_lock
149
        popa
1830 hidnplayr 150
 
2390 hidnplayr 151
        DEBUGF  1,"Socket locked\n"
1733 hidnplayr 152
 
153
;---------------------------------------
154
; unscale the window into a 32 bit value
155
 
2390 hidnplayr 156
        movzx   eax, [edx + TCP_header.Window]
157
        push    ecx
158
        mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
159
        shl     eax, cl
160
        mov     dword [edx + TCP_header.Window], eax    ; word after window is checksum, we dont need checksum anymore
161
        pop     ecx
1733 hidnplayr 162
 
163
;-----------------------------------
164
; Is this socket a listening socket?
165
 
2390 hidnplayr 166
        test    [ebx + SOCKET.options], SO_ACCEPTCON
167
        jz      .no_listening_socket
1733 hidnplayr 168
 
2390 hidnplayr 169
        DEBUGF  1,"Accepting new connection\n"
1838 hidnplayr 170
 
2402 hidnplayr 171
        pusha
172
        lea     ecx, [ebx + SOCKET.mutex]
173
        call    mutex_unlock
174
        popa
175
 
2390 hidnplayr 176
        push    ecx edx esi edi         ;;;
177
        call    SOCKET_fork
178
        pop     edi esi edx ecx
1838 hidnplayr 179
 
2390 hidnplayr 180
        test    eax, eax
181
        jz      .drop
1733 hidnplayr 182
 
2390 hidnplayr 183
        push    dword [edi + 4]                         ; Ipv4 destination addres
184
        pop     [eax + IP_SOCKET.LocalIP]
1733 hidnplayr 185
 
2390 hidnplayr 186
        push    [edx + TCP_header.DestinationPort]
187
        pop     [eax + TCP_SOCKET.LocalPort]
1733 hidnplayr 188
 
2390 hidnplayr 189
        mov     [eax + TCP_SOCKET.t_state], TCPS_LISTEN
190
        mov     ebx, eax
1733 hidnplayr 191
 
2390 hidnplayr 192
        jmp     .LISTEN
1838 hidnplayr 193
 
1733 hidnplayr 194
  .no_listening_socket:
195
 
196
;-------------------------------------
197
; Reset idle timer and keepalive timer
198
 
2390 hidnplayr 199
        mov     [ebx + TCP_SOCKET.t_idle], 0
200
        mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
1733 hidnplayr 201
 
202
;--------------------
203
; Process TCP options
204
 
2390 hidnplayr 205
        movzx   eax, [edx + TCP_header.DataOffset]
206
        cmp     eax, sizeof.TCP_header                  ; Does header contain any options?
207
        je      .no_options
1733 hidnplayr 208
 
2390 hidnplayr 209
        DEBUGF  1,"Segment has options\n"
1733 hidnplayr 210
 
2390 hidnplayr 211
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
212
        jz      .not_uni_xfer                           ; also no header prediction
1733 hidnplayr 213
 
2390 hidnplayr 214
        add     eax, edx
215
        lea     esi, [edx + sizeof.TCP_header]
1733 hidnplayr 216
 
217
  .opt_loop:
2390 hidnplayr 218
        cmp     esi, eax                        ; are we scanning outside of header?
219
        jae     .no_options
1733 hidnplayr 220
 
2390 hidnplayr 221
        cmp     byte [esi], TCP_OPT_EOL         ; end of option list?
222
        jz      .no_options
1733 hidnplayr 223
 
2390 hidnplayr 224
        cmp     byte [esi], TCP_OPT_NOP         ; nop ?
225
        jz      .opt_nop
1733 hidnplayr 226
 
2390 hidnplayr 227
        cmp     byte [esi], TCP_OPT_MAXSEG
228
        je      .opt_maxseg
1733 hidnplayr 229
 
2390 hidnplayr 230
        cmp     byte [esi], TCP_OPT_WINDOW
231
        je      .opt_window
1733 hidnplayr 232
 
2390 hidnplayr 233
        cmp     byte [esi], TCP_OPT_TIMESTAMP
234
        je      .opt_timestamp
1733 hidnplayr 235
 
2390 hidnplayr 236
        jmp     .no_options     ; If we reach here, some unknown options were received, skip them all!
1733 hidnplayr 237
 
238
  .opt_nop:
2390 hidnplayr 239
        inc     edi
240
        jmp     .opt_loop
1733 hidnplayr 241
 
242
  .opt_maxseg:
2390 hidnplayr 243
        cmp     byte [esi+1], 4
244
        jne     .no_options             ; error occured, ignore all options!
1733 hidnplayr 245
 
2390 hidnplayr 246
        test    [edx + TCP_header.Flags], TH_SYN
247
        jz      @f
1733 hidnplayr 248
 
2390 hidnplayr 249
        movzx   eax, word[esi+2]
250
        rol     ax, 8
251
        DEBUGF  1,"Maxseg: %u\n", ax
1733 hidnplayr 252
 
2390 hidnplayr 253
        mov     [ebx + TCP_SOCKET.t_maxseg], eax
1733 hidnplayr 254
 
255
       @@:
2390 hidnplayr 256
        add     edi, 4
257
        jmp     .opt_loop
1733 hidnplayr 258
 
259
 
260
  .opt_window:
2390 hidnplayr 261
        cmp     byte [esi+1], 3
262
        jne     .no_options
1733 hidnplayr 263
 
2390 hidnplayr 264
        test    [edx + TCP_header.Flags], TH_SYN
265
        jz      @f
1733 hidnplayr 266
 
2390 hidnplayr 267
        DEBUGF  1,"Got window option\n"
1733 hidnplayr 268
 
2390 hidnplayr 269
        ;;;;;
1733 hidnplayr 270
       @@:
2390 hidnplayr 271
        add     edi, 3
272
        jmp     .opt_loop
1733 hidnplayr 273
 
274
 
275
  .opt_timestamp:
2390 hidnplayr 276
        cmp     byte [esi+1], 10
277
        jne     .no_options
1733 hidnplayr 278
 
2390 hidnplayr 279
        DEBUGF  1,"Got timestamp option\n"
1733 hidnplayr 280
 
2390 hidnplayr 281
        ;;;;;
1733 hidnplayr 282
 
2390 hidnplayr 283
        add     esi, 10
284
        jmp     .opt_loop
1733 hidnplayr 285
 
286
  .no_options:
287
 
288
 
289
 
290
 
291
 
292
 
293
;-----------------------------------------------------------------------
294
; Time to do some header prediction (Original Principle by Van Jacobson)
295
 
296
; There are two common cases for an uni-directional data transfer.
297
;
298
; General rule: the packets has no control flags, is in-sequence,
299
;   window width didnt change and we're not retransmitting.
300
;
301
; Second rules:
302
;  -  If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
303
;      In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
304
;
305
;  -  If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
306
;      If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
307
 
2390 hidnplayr 308
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
309
        jnz     .not_uni_xfer
1733 hidnplayr 310
 
2390 hidnplayr 311
        test    [edx + TCP_header.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
312
        jnz     .not_uni_xfer
1733 hidnplayr 313
 
2390 hidnplayr 314
        test    [edx + TCP_header.Flags], TH_ACK
315
        jz      .not_uni_xfer
1733 hidnplayr 316
 
2390 hidnplayr 317
        mov     eax, [edx + TCP_header.SequenceNumber]
318
        cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
319
        jne     .not_uni_xfer
1733 hidnplayr 320
 
2390 hidnplayr 321
        mov     eax, dword [edx + TCP_header.Window]
322
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
323
        jne     .not_uni_xfer
1733 hidnplayr 324
 
2390 hidnplayr 325
        mov     eax, [ebx + TCP_SOCKET.SND_NXT]
326
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
327
        jne     .not_uni_xfer
1733 hidnplayr 328
 
329
;---------------------------------------
330
; check if we are sender in the uni-xfer
331
 
332
; If the following 4 conditions are all true, this segment is a pure ACK.
333
;
334
; - The segment contains no data.
2390 hidnplayr 335
        test    ecx, ecx
336
        jnz     .not_sender
1733 hidnplayr 337
 
338
; - The congestion window is greater than or equal to the current send window.
339
;     This test is true only if the window is fully open, that is, the connection is not in the middle of slow start or congestion avoidance.
2390 hidnplayr 340
        mov     eax, [ebx + TCP_SOCKET.SND_CWND]
341
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
342
        jb      .not_uni_xfer
1733 hidnplayr 343
 
344
; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
2390 hidnplayr 345
        mov     eax, [edx + TCP_header.AckNumber]
346
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
347
        ja      .not_uni_xfer
1733 hidnplayr 348
 
349
; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
2390 hidnplayr 350
        sub     eax, [ebx + TCP_SOCKET.SND_UNA]
351
        jbe     .not_uni_xfer
1733 hidnplayr 352
 
2390 hidnplayr 353
        DEBUGF  1,"Header prediction: we are sender\n"
1733 hidnplayr 354
 
355
;---------------------------------
356
; Packet is a pure ACK, process it
357
 
358
; Update RTT estimators
359
 
1763 hidnplayr 360
;;; TODO
361
 
1733 hidnplayr 362
; Delete acknowledged bytes from send buffer
2390 hidnplayr 363
        pusha
364
        mov     ecx, eax
365
        lea     eax, [ebx + STREAM_SOCKET.snd]
366
        call    SOCKET_ring_free
367
        popa
1733 hidnplayr 368
 
369
; update window pointers
2390 hidnplayr 370
        mov     eax, [edx + TCP_header.AckNumber]
371
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1733 hidnplayr 372
 
373
; Stop retransmit timer
2390 hidnplayr 374
        mov     [ebx + TCP_SOCKET.timer_retransmission], 0
1733 hidnplayr 375
 
376
; Awaken waiting processes
2402 hidnplayr 377
        pusha
378
        lea     ecx, [ebx + SOCKET.mutex]
379
        call    mutex_unlock
380
        popa
381
 
2390 hidnplayr 382
        mov     eax, ebx
383
        call    SOCKET_notify_owner
1733 hidnplayr 384
 
1763 hidnplayr 385
; Generate more output
2390 hidnplayr 386
        call    TCP_output
1733 hidnplayr 387
 
2390 hidnplayr 388
        jmp     .drop_not_locked
1763 hidnplayr 389
 
1733 hidnplayr 390
;-------------------------------------------------
391
; maybe we are the receiver in the uni-xfer then..
392
 
393
  .not_sender:
394
; - The amount of data in the segment is greater than 0 (data count is in ecx)
395
 
396
; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
2390 hidnplayr 397
        mov     eax, [edx + TCP_header.AckNumber]
398
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
399
        jne     .not_uni_xfer
1733 hidnplayr 400
 
401
; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp).
402
 
403
;;; TODO
404
 
2390 hidnplayr 405
        jnz     .not_uni_xfer
1733 hidnplayr 406
 
407
; Complete processing of received data
408
 
2390 hidnplayr 409
        DEBUGF  1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx
1733 hidnplayr 410
 
2390 hidnplayr 411
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
1763 hidnplayr 412
 
2390 hidnplayr 413
        movzx   esi, [edx + TCP_header.DataOffset]
414
        add     esi, edx
415
        lea     eax, [ebx + STREAM_SOCKET.rcv]
416
        call    SOCKET_ring_write                       ; Add the data to the socket buffer
1733 hidnplayr 417
 
2390 hidnplayr 418
        mov     eax, ebx
419
        call    SOCKET_notify_owner
1733 hidnplayr 420
 
2390 hidnplayr 421
        or      [ebx + TCP_SOCKET.t_flags], TF_DELACK   ; Set delayed ack flag
1733 hidnplayr 422
 
2390 hidnplayr 423
        jmp     .drop
1733 hidnplayr 424
 
425
 
426
 
427
 
428
 
429
 
430
;--------------------------------------------------
431
; Header prediction failed, do it the slow way
432
 
433
  .not_uni_xfer:
434
 
2390 hidnplayr 435
        DEBUGF  1,"Header prediction failed\n"
1733 hidnplayr 436
 
437
; Calculate receive window size
438
 
2362 hidnplayr 439
;        mov     eax, [ebx + STREAM_SOCKET.rcv.size]
2305 hidnplayr 440
;        neg     eax
441
;        add     eax, SOCKETBUFFSIZE
442
;        mov     edx, [ebx + TCP_SOCKET.RCV_ADV]
443
;        sub     edx, [ebx + TCP_SOCKET.RCV_NXT]
444
;        cmp     eax, edx
445
;        jae     @f
446
;        mov     eax, edx
447
;       @@:
1733 hidnplayr 448
 
2390 hidnplayr 449
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
450
        je      .LISTEN
1733 hidnplayr 451
 
2390 hidnplayr 452
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT
453
        je      .SYN_SENT
1733 hidnplayr 454
 
2390 hidnplayr 455
        jmp     .NOT_LISTEN_OR_SYN_SENT
1733 hidnplayr 456
 
457
 
458
 
459
;-------------
460
; Passive Open
461
 
462
align 4
2555 hidnplayr 463
  .LISTEN:
1733 hidnplayr 464
 
2390 hidnplayr 465
        DEBUGF  1,"TCP state: listen\n"
1733 hidnplayr 466
 
2390 hidnplayr 467
        test    [edx + TCP_header.Flags], TH_RST        ;;; TODO: kill new socket on error
468
        jnz     .drop
1733 hidnplayr 469
 
2390 hidnplayr 470
        test    [edx + TCP_header.Flags], TH_ACK
471
        jnz     .drop_with_reset
1733 hidnplayr 472
 
2390 hidnplayr 473
        test    [edx + TCP_header.Flags], TH_SYN
474
        jz      .drop
1733 hidnplayr 475
 
476
;;; TODO: check if it's a broadcast or multicast, and drop if so
477
 
2555 hidnplayr 478
        push    dword [edi]                             ; Ipv4 source addres
2390 hidnplayr 479
        pop     [ebx + IP_SOCKET.RemoteIP]
1733 hidnplayr 480
 
2390 hidnplayr 481
        push    [edx + TCP_header.SourcePort]
482
        pop     [ebx + TCP_SOCKET.RemotePort]
1733 hidnplayr 483
 
2390 hidnplayr 484
        push    [edx + TCP_header.SequenceNumber]
485
        pop     [ebx + TCP_SOCKET.IRS]
1733 hidnplayr 486
 
2390 hidnplayr 487
        push    [TCP_sequence_num]                      ;;;;;
488
        add     [TCP_sequence_num], 64000 / 2
489
        pop     [ebx + TCP_SOCKET.ISS]
1733 hidnplayr 490
 
2390 hidnplayr 491
        push    [ebx + TCP_SOCKET.ISS]
492
        pop     [ebx + TCP_SOCKET.SND_NXT]
1733 hidnplayr 493
 
2390 hidnplayr 494
        TCP_sendseqinit ebx
495
        TCP_rcvseqinit ebx
1733 hidnplayr 496
 
2390 hidnplayr 497
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
498
        mov     [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
499
        mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval  ;;;; macro
1838 hidnplayr 500
 
2390 hidnplayr 501
        lea     eax, [ebx + STREAM_SOCKET.snd]
502
        call    SOCKET_ring_create
1733 hidnplayr 503
 
2390 hidnplayr 504
        lea     eax, [ebx + STREAM_SOCKET.rcv]
505
        call    SOCKET_ring_create
1733 hidnplayr 506
 
1838 hidnplayr 507
;;;        call    SOCKET_notify_owner
1733 hidnplayr 508
 
2390 hidnplayr 509
        jmp     .trim_then_step6
510
 
1733 hidnplayr 511
 
512
 
513
 
514
 
515
 
516
 
517
 
518
 
1838 hidnplayr 519
 
1733 hidnplayr 520
;------------
521
; Active Open
522
 
523
align 4
524
.SYN_SENT:
525
 
2390 hidnplayr 526
        DEBUGF  1,"TCP state: syn_sent\n"
1733 hidnplayr 527
 
2390 hidnplayr 528
        test    [edx + TCP_header.Flags], TH_ACK
529
        jz      @f
1733 hidnplayr 530
 
2390 hidnplayr 531
        mov     eax, [edx + TCP_header.AckNumber]
532
        cmp     eax, [ebx + TCP_SOCKET.ISS]
533
        jbe     .drop_with_reset
1733 hidnplayr 534
 
2390 hidnplayr 535
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
536
        ja      .drop_with_reset
1733 hidnplayr 537
       @@:
538
 
2390 hidnplayr 539
        test    [edx + TCP_header.Flags], TH_RST
540
        jz      @f
1733 hidnplayr 541
 
2390 hidnplayr 542
        test    [edx + TCP_header.Flags], TH_ACK
543
        jz      .drop
1733 hidnplayr 544
 
2390 hidnplayr 545
        mov     eax, ebx
546
        mov     ebx, ECONNREFUSED
547
        call    TCP_drop
1733 hidnplayr 548
 
2390 hidnplayr 549
        jmp     .drop
1733 hidnplayr 550
       @@:
551
 
2390 hidnplayr 552
        test    [edx + TCP_header.Flags], TH_SYN
553
        jz      .drop
1733 hidnplayr 554
 
555
; at this point, segment seems to be valid
556
 
2390 hidnplayr 557
        test    [edx + TCP_header.Flags], TH_ACK
558
        jz      .no_syn_ack
1733 hidnplayr 559
 
560
; now, process received SYN in response to an active open
561
 
2390 hidnplayr 562
        mov     eax, [edx + TCP_header.AckNumber]
563
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
564
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
565
        jbe     @f
566
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1733 hidnplayr 567
       @@:
568
 
569
  .no_syn_ack:
570
 
2390 hidnplayr 571
        mov     [ebx + TCP_SOCKET.timer_retransmission], 0      ; disable retransmission
1733 hidnplayr 572
 
2390 hidnplayr 573
        push    [edx + TCP_header.SequenceNumber]
574
        pop     [ebx + TCP_SOCKET.IRS]
1733 hidnplayr 575
 
2390 hidnplayr 576
        TCP_rcvseqinit ebx
1733 hidnplayr 577
 
2390 hidnplayr 578
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1733 hidnplayr 579
 
2390 hidnplayr 580
        mov     eax, [ebx + TCP_SOCKET.SND_UNA]
581
        cmp     eax, [ebx + TCP_SOCKET.ISS]
582
        jbe     .simultaneous_open
1733 hidnplayr 583
 
2390 hidnplayr 584
        test    [edx + TCP_header.Flags], TH_ACK
585
        jz      .simultaneous_open
1733 hidnplayr 586
 
2390 hidnplayr 587
        DEBUGF  1,"TCP: active open\n"
1733 hidnplayr 588
 
589
;;; TODO: update stats
590
 
591
; set socket state to connected
592
 
2390 hidnplayr 593
        mov     [ebx + SOCKET.state],1  ;;;; FIXME
1733 hidnplayr 594
 
2390 hidnplayr 595
        mov     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1733 hidnplayr 596
 
597
;;; TODO: check if we should scale the connection (567-572)
598
;;; TODO: update RTT estimators
599
 
2390 hidnplayr 600
        jmp     .trim_then_step6
1733 hidnplayr 601
 
602
  .simultaneous_open:
603
 
2390 hidnplayr 604
        DEBUGF  1,"TCP: simultaneous open\n"
1733 hidnplayr 605
; We have received a syn but no ACK, so we are having a simultaneous open..
2390 hidnplayr 606
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1733 hidnplayr 607
 
608
 
609
 
610
 
611
 
612
 
613
 
614
;-------------------------------------
615
; Common processing for receipt of SYN
616
 
617
  .trim_then_step6:
618
 
2390 hidnplayr 619
        inc     [edx + TCP_header.SequenceNumber]
1733 hidnplayr 620
 
621
;;; TODO: Drop any received data that follows receive window (590)
622
 
2390 hidnplayr 623
        mov     eax, [edx + TCP_header.SequenceNumber]
624
        mov     [ebx + TCP_SOCKET.RCV_UP], eax
625
        dec     eax
626
        mov     [ebx + TCP_SOCKET.SND_WL1], eax
1733 hidnplayr 627
 
2390 hidnplayr 628
        jmp     .ack_processed
1733 hidnplayr 629
 
630
 
631
 
632
 
633
 
634
 
635
 
636
 
637
  .NOT_LISTEN_OR_SYN_SENT:
638
 
2390 hidnplayr 639
        DEBUGF  1,"Slow TCP input: not listen or syn_sent state\n"
1733 hidnplayr 640
 
641
;--------------------------------------------
642
; Protection Against Wrapped Sequence Numbers
643
 
644
; First, check if timestamp is present
645
 
1763 hidnplayr 646
;;;; TODO 602
1733 hidnplayr 647
 
648
; Then, check if at least some bytes of data are within window
649
 
650
;;;; TODO
651
 
652
 
653
 
654
 
655
 
656
 
657
 
658
 
659
;----------------------------
660
; trim any data not in window
661
 
662
; check for duplicate data at beginning of segment
663
 
2390 hidnplayr 664
        mov     eax, [ebx + TCP_SOCKET.RCV_NXT]
665
        sub     eax, [edx + TCP_header.SequenceNumber]
666
        jbe     .no_duplicate
1733 hidnplayr 667
 
2390 hidnplayr 668
        DEBUGF  1,"Uh oh.. %u bytes of duplicate data!\n", eax
1763 hidnplayr 669
 
2390 hidnplayr 670
        test    [edx + TCP_header.Flags], TH_SYN
671
        jz      .no_dup_syn
1733 hidnplayr 672
 
673
; remove duplicate syn
674
 
2390 hidnplayr 675
        and     [edx + TCP_header.Flags], not (TH_SYN)
676
        inc     [edx + TCP_header.SequenceNumber]
1733 hidnplayr 677
 
2390 hidnplayr 678
        cmp     [edx + TCP_header.UrgentPointer], 1
679
        jbe     @f
680
        dec     [edx + TCP_header.UrgentPointer]
681
        jmp     .dup_syn
1733 hidnplayr 682
       @@:
2390 hidnplayr 683
        and     [edx + TCP_header.Flags], not (TH_URG)
1838 hidnplayr 684
  .dup_syn:
2390 hidnplayr 685
        dec     eax
1763 hidnplayr 686
  .no_dup_syn:
1733 hidnplayr 687
 
688
; eax holds number of bytes to drop
689
 
690
; Check for entire duplicate packet
691
 
2390 hidnplayr 692
        cmp     eax, ecx
693
        jae     .duplicate
1733 hidnplayr 694
 
2390 hidnplayr 695
        DEBUGF  1,"Going to drop %u out of %u bytes\n", eax, ecx
1830 hidnplayr 696
 
1733 hidnplayr 697
;;; TODO: apply figure 28.30
698
 
699
; Check for duplicate FIN
700
 
2390 hidnplayr 701
        test    [edx + TCP_header.Flags], TH_FIN
702
        jz      @f
703
        inc     ecx
704
        cmp     eax, ecx
705
        dec     ecx
706
        jne     @f
1733 hidnplayr 707
 
2390 hidnplayr 708
        mov     eax, ecx
709
        and     [edx + TCP_header.Flags], not TH_FIN
710
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
711
        jmp     .no_duplicate
1733 hidnplayr 712
       @@:
713
 
714
; Handle the case when a bound socket connects to itself
715
; Allow packets with a SYN and an ACKto continue with the processing
716
 
717
;-------------------------------------
718
; Generate duplicate ACK if nescessary
719
 
720
; This code also handles simultaneous half-open or self-connects
721
 
2390 hidnplayr 722
        test    eax, eax
723
        jnz     .drop_after_ack
1733 hidnplayr 724
 
2390 hidnplayr 725
        cmp     [edx + TCP_header.Flags], TH_ACK
726
        jz      .drop_after_ack
1733 hidnplayr 727
 
728
  .duplicate:
729
 
2390 hidnplayr 730
        DEBUGF  1,"Duplicate received\n"
1733 hidnplayr 731
 
732
;----------------------------------------
733
; Update statistics for duplicate packets
734
 
735
;;; TODO
736
 
2390 hidnplayr 737
        jmp     .drop_after_ack
1733 hidnplayr 738
 
739
  .no_duplicate:
740
 
741
;-----------------------------------------------
742
; Remove duplicate data and update urgent offset
743
 
2390 hidnplayr 744
        add     [edx + TCP_header.SequenceNumber], eax
1733 hidnplayr 745
 
746
;;; TODO
747
 
2390 hidnplayr 748
        sub     [edx + TCP_header.UrgentPointer], ax
749
        ja      @f
1733 hidnplayr 750
 
2390 hidnplayr 751
        and     [edx + TCP_header.Flags], not (TH_URG)
752
        mov     [edx + TCP_header.UrgentPointer], 0
1733 hidnplayr 753
       @@:
754
 
755
;--------------------------------------------------
756
; Handle data that arrives after process terminates
757
 
2390 hidnplayr 758
        cmp     [ebx + SOCKET.PID], 0
759
        ja      @f
1733 hidnplayr 760
 
2390 hidnplayr 761
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
762
        jbe     @f
1733 hidnplayr 763
 
2390 hidnplayr 764
        test    ecx, ecx
765
        jz      @f
1733 hidnplayr 766
 
767
;;; Close the socket
768
;;; update stats
769
 
2390 hidnplayr 770
        jmp     .drop_with_reset
1733 hidnplayr 771
       @@:
772
 
773
;----------------------------------------
774
; Remove data beyond right edge of window
775
 
2390 hidnplayr 776
        mov     eax, [edx + TCP_header.SequenceNumber]
777
        add     eax, ecx
778
        sub     eax, [ebx + TCP_SOCKET.RCV_NXT]
779
        sub     ax, [ebx + TCP_SOCKET.RCV_WND]
1733 hidnplayr 780
 
781
; eax now holds the number of bytes to drop
782
 
2390 hidnplayr 783
        jbe     .no_excess_data
1733 hidnplayr 784
 
785
;;; TODO: update stats
786
 
2390 hidnplayr 787
        cmp     eax, ecx
788
        jb      .dont_drop_all
1733 hidnplayr 789
 
790
;;; TODO 700-736
791
 
792
  .dont_drop_all:
793
 
794
  .no_excess_data:
795
 
796
 
797
 
798
 
799
 
800
 
801
 
802
 
803
;-----------------
804
; Record timestamp
805
 
806
;;; TODO 737-746
807
 
808
 
809
 
810
 
811
 
812
;------------------
813
; Process RST flags
814
 
2390 hidnplayr 815
        test    [edx + TCP_header.Flags], TH_RST
816
        jz      .rst_skip
1733 hidnplayr 817
 
2390 hidnplayr 818
        DEBUGF  1,"Got an RST flag"
1733 hidnplayr 819
 
2390 hidnplayr 820
        mov     eax, [ebx + TCP_SOCKET.t_state]
821
        shl     eax, 2
822
        jmp     dword [eax + .rst_sw_list]
1733 hidnplayr 823
 
824
  .rst_sw_list:
2390 hidnplayr 825
        dd      .rst_skip       ;TCPS_CLOSED
826
        dd      .rst_skip       ;TCPS_LISTEN
827
        dd      .rst_skip       ;TCPS_SYN_SENT
828
        dd      .econnrefused   ;TCPS_SYN_RECEIVED
829
        dd      .econnreset     ;TCPS_ESTABLISHED
830
        dd      .econnreset     ;TCPS_CLOSE_WAIT
831
        dd      .econnreset     ;TCPS_FIN_WAIT_1
832
        dd      .rst_close      ;TCPS_CLOSING
833
        dd      .rst_close      ;TCPS_LAST_ACK
834
        dd      .econnreset     ;TCPS_FIN_WAIT_2
835
        dd      .rst_close      ;TCPS_TIMED_WAIT
1733 hidnplayr 836
 
837
  .econnrefused:
2390 hidnplayr 838
        DEBUGF  1,"Connection refused"
1733 hidnplayr 839
 
2390 hidnplayr 840
        mov     [ebx + SOCKET.errorcode], ECONNREFUSED
841
        jmp     .close
1733 hidnplayr 842
 
843
  .econnreset:
2390 hidnplayr 844
        DEBUGF  1,"Connection reset"
1733 hidnplayr 845
 
2390 hidnplayr 846
        mov     [ebx + SOCKET.errorcode], ECONNRESET
1733 hidnplayr 847
 
1831 hidnplayr 848
    .close:
2390 hidnplayr 849
        DEBUGF  1,"Closing connection"
1733 hidnplayr 850
 
2390 hidnplayr 851
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
852
        ;;; TODO: update stats
853
        mov     eax, ebx
854
        call    TCP_close
855
        jmp     .drop
1733 hidnplayr 856
 
857
  .rst_close:
2390 hidnplayr 858
        DEBUGF  1,"Closing with reset\n"
1733 hidnplayr 859
 
2390 hidnplayr 860
        mov     eax, ebx
861
        call    TCP_close
862
        jmp     .drop
1733 hidnplayr 863
 
864
 
865
 
866
 
867
 
868
 
869
 
1763 hidnplayr 870
  .rst_skip:
1733 hidnplayr 871
 
1763 hidnplayr 872
 
1733 hidnplayr 873
;--------------------------------------
874
; handle SYN-full and ACK-less segments
875
 
2390 hidnplayr 876
        test    [edx + TCP_header.Flags], TH_SYN
877
        jz      @f
1733 hidnplayr 878
 
2390 hidnplayr 879
        mov     eax, ebx
880
        mov     ebx, ECONNRESET
881
        call    TCP_drop
882
        jmp     .drop_with_reset
1733 hidnplayr 883
 
2390 hidnplayr 884
        test    [edx + TCP_header.Flags], TH_ACK
885
        jz      .drop
1733 hidnplayr 886
      @@:
887
 
888
 
889
 
890
 
891
 
892
 
893
 
894
;---------------
895
; ACK processing
896
 
2390 hidnplayr 897
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
898
        jnz     .no_syn_rcv
1733 hidnplayr 899
 
2390 hidnplayr 900
        DEBUGF  1,"TCP state = syn received\n"
1733 hidnplayr 901
 
2390 hidnplayr 902
        mov     eax, [edx + TCP_header.AckNumber]
903
        cmp     [ebx + TCP_SOCKET.SND_UNA], eax
904
        ja      .drop_with_reset
905
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
906
        ja      .drop_with_reset
1733 hidnplayr 907
 
2309 hidnplayr 908
;;; TODO: update stats
909
 
2390 hidnplayr 910
        mov     eax, ebx
911
        call    SOCKET_is_connected
912
        mov     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1831 hidnplayr 913
 
914
; Do window scaling?
915
 
2390 hidnplayr 916
        test    [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
917
        jz      @f
918
        test    [ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE
919
        jz      @f
1831 hidnplayr 920
 
2390 hidnplayr 921
        push    word [ebx + TCP_SOCKET.requested_s_scale]       ; Set send and receive scale factors to the received values
922
        pop     word [ebx + TCP_SOCKET.SND_SCALE]
1831 hidnplayr 923
       @@:
924
 
2309 hidnplayr 925
;;; TODO: copy the data (if any) into the socket
1831 hidnplayr 926
 
2390 hidnplayr 927
        mov     eax, [edx + TCP_header.SequenceNumber]
928
        dec     eax
929
        mov     [ebx + TCP_SOCKET.SND_WL1], eax
930
        jmp     .not_dup_ack
1831 hidnplayr 931
 
1733 hidnplayr 932
  .no_syn_rcv:
933
 
934
; check for duplicate ACK
935
 
2390 hidnplayr 936
        mov     eax, [edx + TCP_header.AckNumber]
937
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
938
        ja      .not_dup_ack
1733 hidnplayr 939
 
2390 hidnplayr 940
        test    ecx, ecx
941
        jnz     .reset_dupacks
1733 hidnplayr 942
 
2390 hidnplayr 943
        mov     eax, dword [edx + TCP_header.Window]
944
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
945
        jne     .reset_dupacks
1733 hidnplayr 946
 
2390 hidnplayr 947
        DEBUGF  1,"Processing a duplicate ACK..\n"
1733 hidnplayr 948
 
2390 hidnplayr 949
        cmp     [ebx + TCP_SOCKET.timer_retransmission], 10000 ;;;;  FIXME
950
        ja      @f
1733 hidnplayr 951
 
2390 hidnplayr 952
        mov     eax, [edx + TCP_header.AckNumber]
953
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
954
        je      .dup_ack
1763 hidnplayr 955
 
956
       @@:
2390 hidnplayr 957
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
958
        jmp     .not_dup_ack
1763 hidnplayr 959
 
960
  .dup_ack:
2390 hidnplayr 961
        inc     [ebx + TCP_SOCKET.t_dupacks]
962
        cmp     [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
963
        jne     .no_re_xmit
1763 hidnplayr 964
 
2390 hidnplayr 965
        push    [ebx + TCP_SOCKET.SND_NXT]              ; >>>>
1763 hidnplayr 966
 
2390 hidnplayr 967
        mov     eax, [ebx + TCP_SOCKET.SND_WND]
968
        cmp     eax, [ebx + TCP_SOCKET.SND_CWND]
969
        cmovg   eax, [ebx + TCP_SOCKET.SND_CWND]
970
        shr     eax, 1
971
        push    edx
972
        xor     edx, edx
973
        div     [ebx + TCP_SOCKET.t_maxseg]
974
        cmp     eax, 2
975
        jae     @f
976
        mov     ax, 2
1763 hidnplayr 977
       @@:
2390 hidnplayr 978
        mul     [ebx + TCP_SOCKET.t_maxseg]
979
        pop     edx
980
        mov     [ebx + TCP_SOCKET.SND_SSTHRESH], eax
1763 hidnplayr 981
 
2390 hidnplayr 982
        mov     [ebx + TCP_SOCKET.timer_retransmission], 0      ; turn off retransmission timer
983
        mov     [ebx + TCP_SOCKET.t_rtt], 0
984
        mov     eax, [edx + TCP_header.AckNumber]
985
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
986
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
987
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
1763 hidnplayr 988
 
2390 hidnplayr 989
        mov     eax, ebx
990
        call    TCP_output                                      ; retransmit missing segment
1763 hidnplayr 991
 
2390 hidnplayr 992
        push    edx
993
        xor     edx, edx
994
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
995
        mul     [ebx + TCP_SOCKET.t_dupacks]
996
        pop     edx
997
        add     eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
998
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
1763 hidnplayr 999
 
2390 hidnplayr 1000
        pop     eax                                     ; <<<<
1001
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1002
        jb      @f
1003
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1763 hidnplayr 1004
       @@:
1005
 
2390 hidnplayr 1006
        jmp     .drop
1733 hidnplayr 1007
 
1008
 
1763 hidnplayr 1009
  .no_re_xmit:
2390 hidnplayr 1010
        jbe     .not_dup_ack
1733 hidnplayr 1011
 
2390 hidnplayr 1012
        DEBUGF  1,"Increasing congestion window\n"
1733 hidnplayr 1013
 
2390 hidnplayr 1014
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
1015
        add     [ebx + TCP_SOCKET.SND_CWND], eax
1733 hidnplayr 1016
 
2390 hidnplayr 1017
        mov     eax, ebx
1018
        call    TCP_output
1733 hidnplayr 1019
 
2390 hidnplayr 1020
        jmp     .drop
1733 hidnplayr 1021
 
1022
 
1023
 
1763 hidnplayr 1024
 
1025
 
1026
 
1027
  .not_dup_ack:
1028
 
1733 hidnplayr 1029
;-------------------------------------------------
1030
; If the congestion window was inflated to account
1031
; for the other side's cached packets, retract it
1032
 
2390 hidnplayr 1033
        mov     eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
1034
        cmp     eax, [ebx + TCP_SOCKET.SND_CWND]
1035
        ja      @f
1036
        cmp     [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
1037
        jbe     @f
1038
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
1763 hidnplayr 1039
       @@:
1733 hidnplayr 1040
 
2390 hidnplayr 1041
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
1733 hidnplayr 1042
 
2390 hidnplayr 1043
        mov     eax, [edx + TCP_header.AckNumber]
1044
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
1045
        jbe     @f
1733 hidnplayr 1046
 
2390 hidnplayr 1047
        ;;; TODO: update stats
1048
        jmp     .drop_after_ack
1733 hidnplayr 1049
 
1763 hidnplayr 1050
       @@:
1733 hidnplayr 1051
 
2390 hidnplayr 1052
        mov     edi, [edx + TCP_header.AckNumber]
1053
        sub     edi, [ebx + TCP_SOCKET.SND_UNA]         ; now we got the number of acked bytes in edi
1733 hidnplayr 1054
 
2390 hidnplayr 1055
        ;;; TODO: update stats
1733 hidnplayr 1056
 
1057
 
2390 hidnplayr 1058
        DEBUGF  1,"We have an acceptable ACK of %x bytes\n", esi
1763 hidnplayr 1059
 
1060
 
1061
 
1062
 
1063
 
1064
 
1733 hidnplayr 1065
;------------------------------------------
1066
; RTT measurements and retransmission timer
1067
 
2390 hidnplayr 1068
        ;;;;; 912 - 926
1733 hidnplayr 1069
 
2390 hidnplayr 1070
        mov     [ebx + TCP_SOCKET.timer_retransmission], 0
1733 hidnplayr 1071
 
2390 hidnplayr 1072
        mov     eax, [ebx + TCP_SOCKET.SND_MAX]
1073
        cmp     eax, [edx + TCP_header.AckNumber]
1074
        je      .all_outstanding
1075
        mov     [ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value (use a macro for it)
1733 hidnplayr 1076
  .all_outstanding:
1077
 
1078
 
1079
 
1080
 
1081
 
1082
 
1083
 
1084
;-------------------------------------------
1085
; Open congestion window in response to ACKs
1086
 
2390 hidnplayr 1087
        mov     esi, [ebx + TCP_SOCKET.SND_CWND]
1088
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
1733 hidnplayr 1089
 
2390 hidnplayr 1090
        cmp     esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
1091
        jbe     @f
1092
        push    edx
1093
        push    eax
1094
        mul     eax
1095
        div     esi
1096
        pop     edx
1097
        shr     edx, 3
1098
        add     eax, edx
1099
        pop     edx
1763 hidnplayr 1100
       @@:
1733 hidnplayr 1101
 
2390 hidnplayr 1102
        add     esi, eax
1733 hidnplayr 1103
 
2390 hidnplayr 1104
        push    ecx
1105
        mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
1106
        mov     eax, TCP_max_win
1107
        shl     eax, cl
1108
        pop     ecx
1733 hidnplayr 1109
 
2390 hidnplayr 1110
        cmp     esi, eax
1111
        cmovg   esi, eax
1112
        mov     [ebx + TCP_SOCKET.SND_CWND], esi
1733 hidnplayr 1113
 
1114
 
1115
 
1116
 
1763 hidnplayr 1117
 
1118
 
1119
 
1733 hidnplayr 1120
;------------------------------------------
1121
; Remove acknowledged data from send buffer
1122
 
2390 hidnplayr 1123
        push    ecx edx ebx
1124
        mov     ecx, edi
1125
        lea     eax, [ebx + STREAM_SOCKET.snd]
1126
        call    SOCKET_ring_free
1127
        pop     ebx
1128
        sub     [ebx + TCP_SOCKET.SND_WND], ecx
1129
        pop     edx ecx
1733 hidnplayr 1130
 
1131
; Wake up process waiting on send buffer
1132
 
2390 hidnplayr 1133
        mov     eax, ebx
1134
        call    SOCKET_notify_owner
1733 hidnplayr 1135
 
1831 hidnplayr 1136
; Update TCPS
1733 hidnplayr 1137
 
2390 hidnplayr 1138
        mov     eax, [edx + TCP_header.AckNumber]
1139
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1733 hidnplayr 1140
 
2390 hidnplayr 1141
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1142
        jb      @f
1143
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1733 hidnplayr 1144
       @@:
1145
 
1146
 
2390 hidnplayr 1147
        ;; TODO: use zero flag as 'ourfinisacked'
1733 hidnplayr 1148
 
1149
 
1150
 
1151
 
1152
; General ACK handling complete
1153
; Now do the state-specific ones
1154
 
2390 hidnplayr 1155
        mov     eax, [ebx + TCP_SOCKET.t_state]
1156
        jmp     dword [eax*4 + .ACK_sw_list]
1733 hidnplayr 1157
 
1158
  .ACK_sw_list:
2390 hidnplayr 1159
        dd      .ack_processed  ;TCPS_CLOSED
1160
        dd      .ack_processed  ;TCPS_LISTEN
1161
        dd      .ack_processed  ;TCPS_SYN_SENT
1162
        dd      .ack_processed  ;TCPS_SYN_RECEIVED
1163
        dd      .ack_processed  ;TCPS_ESTABLISHED
1164
        dd      .ack_processed  ;TCPS_CLOSE_WAIT
1165
        dd      .ack_fw1        ;TCPS_FIN_WAIT_1
1166
        dd      .ack_c          ;TCPS_CLOSING
1167
        dd      .ack_la         ;TCPS_LAST_ACK
1168
        dd      .ack_processed  ;TCPS_FIN_WAIT_2
1169
        dd      .ack_tw         ;TCPS_TIMED_WAIT
1733 hidnplayr 1170
 
1171
 
1772 hidnplayr 1172
  .ack_fw1:
2390 hidnplayr 1173
        jz      .ack_processed
1733 hidnplayr 1174
 
2390 hidnplayr 1175
        test    [ebx + SOCKET.state], SS_CANTRCVMORE
1176
        jnz     @f
1177
        mov     eax, ebx
1178
        call    SOCKET_is_disconnected
1773 hidnplayr 1179
;;;        mov     [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle
1772 hidnplayr 1180
       @@:
1733 hidnplayr 1181
 
2390 hidnplayr 1182
        mov     [ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
1183
        jmp     .ack_processed
1733 hidnplayr 1184
 
1185
 
1772 hidnplayr 1186
  .ack_c:
2390 hidnplayr 1187
        jz      .ack_processed
1772 hidnplayr 1188
 
2390 hidnplayr 1189
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1190
        mov     eax, ebx
1191
        call    TCP_cancel_timers
1192
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1193
        mov     eax, ebx
1194
        call    SOCKET_is_disconnected
1195
        jmp     .ack_processed
1733 hidnplayr 1196
 
1197
 
1772 hidnplayr 1198
  .ack_la:
2390 hidnplayr 1199
        jz      .ack_processed
1733 hidnplayr 1200
 
1773 hidnplayr 1201
 
2390 hidnplayr 1202
        mov     eax, ebx
1203
        call    TCP_close
1204
        jmp     .drop
1733 hidnplayr 1205
 
1206
 
1772 hidnplayr 1207
  .ack_tw:
2390 hidnplayr 1208
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1209
        jmp     .drop_after_ack
1733 hidnplayr 1210
 
1211
 
1772 hidnplayr 1212
 
1213
 
1214
 
1215
 
1216
 
2390 hidnplayr 1217
  .reset_dupacks:               ; We got a new ACK, reset duplicate ACK counter
1733 hidnplayr 1218
 
2390 hidnplayr 1219
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
1733 hidnplayr 1220
 
2390 hidnplayr 1221
  .ack_processed:       ; (step 6)
1733 hidnplayr 1222
 
2390 hidnplayr 1223
        DEBUGF  1,"ACK processed\n"
1733 hidnplayr 1224
 
1225
;----------------------------------------------
1226
; check if we need to update window information
1227
 
2390 hidnplayr 1228
        test    [edx + TCP_header.Flags], TH_ACK
1229
        jz      .no_window_update
1733 hidnplayr 1230
 
2390 hidnplayr 1231
        mov     eax, [ebx + TCP_SOCKET.SND_WL1]
1232
        cmp     eax, [edx + TCP_header.SequenceNumber]
1233
        jb      .update_window
1234
        ja      @f
1733 hidnplayr 1235
 
2390 hidnplayr 1236
        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
1237
        cmp     eax, [edx + TCP_header.AckNumber]
1238
        jb      .update_window
1239
        ja      .no_window_update
1733 hidnplayr 1240
       @@:
1241
 
2390 hidnplayr 1242
        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
1243
        cmp     eax, [edx + TCP_header.AckNumber]
1244
        jne     .no_window_update
1733 hidnplayr 1245
 
2390 hidnplayr 1246
        mov     eax, dword [edx + TCP_header.Window]
1247
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
1248
        jbe     .no_window_update
1733 hidnplayr 1249
 
1250
  .update_window:
1251
 
2390 hidnplayr 1252
        DEBUGF  1,"Updating window\n"
1733 hidnplayr 1253
 
1254
; Keep track of pure window updates
1255
 
1256
;        test    ecx, ecx
1257
;        jz      @f
1258
;
1259
;        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
2305 hidnplayr 1260
;        cmp     eax, [edx + TCP_header.AckNumber]
1733 hidnplayr 1261
;        jne     @f
1262
;
1263
;        ;; mov eax, tiwin
1264
;        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
2300 hidnplayr 1265
;        jbe     @f
1733 hidnplayr 1266
;
1267
;        ;;; update stats
1268
;
1269
;       @@:
1270
 
2390 hidnplayr 1271
        mov     eax, dword [edx + TCP_header.Window]
1272
        cmp     eax, [ebx + TCP_SOCKET.max_sndwnd]
1273
        jbe     @f
1274
        mov     [ebx + TCP_SOCKET.max_sndwnd], eax
1733 hidnplayr 1275
       @@:
2390 hidnplayr 1276
        mov     [ebx + TCP_SOCKET.SND_WND], eax
1733 hidnplayr 1277
 
2390 hidnplayr 1278
        push    [edx + TCP_header.SequenceNumber]
1279
        pop     [ebx + TCP_SOCKET.SND_WL1]
1733 hidnplayr 1280
 
2390 hidnplayr 1281
        push    [edx + TCP_header.AckNumber]
1282
        pop     [ebx + TCP_SOCKET.SND_WL2]
1733 hidnplayr 1283
 
2390 hidnplayr 1284
        ;;; needoutput = 1
1733 hidnplayr 1285
 
1286
  .no_window_update:
1287
 
1288
 
1289
 
1290
 
1291
 
1292
 
1293
 
1294
;-----------------
1295
; process URG flag
1296
 
2390 hidnplayr 1297
        test    [edx + TCP_header.Flags], TH_URG
1298
        jz      .not_urgent
1733 hidnplayr 1299
 
2390 hidnplayr 1300
        cmp     [edx + TCP_header.UrgentPointer], 0
1301
        jz      .not_urgent
1733 hidnplayr 1302
 
2390 hidnplayr 1303
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1304
        je      .not_urgent
1733 hidnplayr 1305
 
1306
; Ignore bogus urgent offsets
1307
 
2390 hidnplayr 1308
        ;;; 1040-1050
1733 hidnplayr 1309
 
2390 hidnplayr 1310
        movzx   eax, [edx + TCP_header.UrgentPointer]
1311
        add     eax, [ebx + STREAM_SOCKET.rcv.size]
1312
        cmp     eax, SOCKET_MAXDATA
1313
        jbe     .not_urgent
1733 hidnplayr 1314
 
2390 hidnplayr 1315
        mov     [edx + TCP_header.UrgentPointer], 0
1316
        and     [edx + TCP_header.Flags], not (TH_URG)
1317
        jmp     .do_data
1733 hidnplayr 1318
 
1319
  .not_urgent:
1320
 
1321
; processing of received urgent pointer
1322
 
2390 hidnplayr 1323
        ;;; TODO (1051-1093)
1733 hidnplayr 1324
 
1325
 
1326
 
1327
 
1328
 
1329
 
1330
 
1331
 
1332
;--------------------------------
1333
; process the data in the segment
1334
 
1335
  .do_data:
1336
 
2390 hidnplayr 1337
        DEBUGF  1,"TCP: do data (%u)\n", ecx
1733 hidnplayr 1338
 
2390 hidnplayr 1339
        test    [edx + TCP_header.Flags], TH_FIN
1340
        jnz     .process_fin
1733 hidnplayr 1341
 
2390 hidnplayr 1342
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_1
1343
        jae     .dont_do_data
1733 hidnplayr 1344
 
2390 hidnplayr 1345
        test    ecx, ecx
1346
        jz      .final_processing
1733 hidnplayr 1347
 
2390 hidnplayr 1348
        DEBUGF  1,"Processing data in segment\n"
1733 hidnplayr 1349
 
1350
;; TODO: check if data is in sequence !
1351
 
2390 hidnplayr 1352
        movzx   esi, [edx + TCP_header.DataOffset]
1353
        add     esi, edx
1733 hidnplayr 1354
 
2390 hidnplayr 1355
        or      [ebx + TCP_SOCKET.t_flags], TF_DELACK
1356
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx
1733 hidnplayr 1357
 
2390 hidnplayr 1358
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1359
        call    SOCKET_ring_write
1733 hidnplayr 1360
 
2390 hidnplayr 1361
        mov     eax, ebx
1362
        call    SOCKET_notify_owner
1733 hidnplayr 1363
 
2390 hidnplayr 1364
        jmp     .final_processing
1733 hidnplayr 1365
 
1366
 
1367
  .dont_do_data:
1368
 
1369
 
1370
 
1371
 
1372
 
1373
 
1374
 
1375
;---------------
1376
; FIN processing
1377
 
1378
  .process_fin:
1379
 
2390 hidnplayr 1380
        DEBUGF  1,"Processing FIN\n"
1733 hidnplayr 1381
 
2390 hidnplayr 1382
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
1383
        je      .not_first_fin
1384
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSING
1385
        je      .not_first_fin
1386
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
1387
        je      .not_first_fin
1774 hidnplayr 1388
 
2390 hidnplayr 1389
        DEBUGF  1,"First FIN for this connection\n"
1774 hidnplayr 1390
 
2390 hidnplayr 1391
        mov     eax, ebx
1392
        call    SOCKET_cant_recv_more
1774 hidnplayr 1393
 
2390 hidnplayr 1394
        mov     [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1395
        inc     [ebx + TCP_SOCKET.RCV_NXT]
1774 hidnplayr 1396
 
1397
  .not_first_fin:
2390 hidnplayr 1398
        mov     eax, [ebx + TCP_SOCKET.t_state]
1399
        shl     eax, 2
1400
        jmp     dword [eax + .FIN_sw_list]
1733 hidnplayr 1401
 
1402
  .FIN_sw_list:
2390 hidnplayr 1403
        dd      .no_fin         ;TCPS_CLOSED
1404
        dd      .no_fin         ;TCPS_LISTEN
1405
        dd      .no_fin         ;TCPS_SYN_SENT
1406
        dd      .fin_syn_est    ;TCPS_SYN_RECEIVED
1407
        dd      .fin_syn_est    ;TCPS_ESTABLISHED
1408
        dd      .no_fin         ;TCPS_CLOSE_WAIT
1409
        dd      .fin_wait1      ;TCPS_FIN_WAIT_1
1410
        dd      .no_fin         ;TCPS_CLOSING
1411
        dd      .no_fin         ;TCPS_LAST_ACK
1412
        dd      .fin_wait2      ;TCPS_FIN_WAIT_2
1413
        dd      .fin_timed      ;TCPS_TIMED_WAIT
1733 hidnplayr 1414
 
1415
  .fin_syn_est:
1416
 
2390 hidnplayr 1417
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
1418
        jmp     .no_fin
1733 hidnplayr 1419
 
1420
  .fin_wait1:
1421
 
2390 hidnplayr 1422
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSING
1423
        jmp     .no_fin
1733 hidnplayr 1424
 
1425
  .fin_wait2:
1426
 
2390 hidnplayr 1427
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1428
        mov     eax, ebx
1429
        call    TCP_cancel_timers
1430
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1431
        call    SOCKET_is_disconnected
1432
        jmp     .no_fin
1733 hidnplayr 1433
 
1434
  .fin_timed:
2390 hidnplayr 1435
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1436
        jmp     .no_fin
1733 hidnplayr 1437
 
1438
  .no_fin:
1439
 
1440
 
1441
 
1442
 
1443
 
1444
 
1445
 
1446
 
1447
;-----------------
1448
; Final processing
1449
 
1450
  .final_processing:
1451
 
2390 hidnplayr 1452
        DEBUGF  1,"Final processing\n"
1733 hidnplayr 1453
 
2390 hidnplayr 1454
        ;;; if debug enabled, output packet
1733 hidnplayr 1455
 
2390 hidnplayr 1456
        ;test    needoutput, needoutput
1457
        ;jz      .dumpit
1733 hidnplayr 1458
 
2390 hidnplayr 1459
        test    [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1460
        jz      .dumpit
1733 hidnplayr 1461
 
2390 hidnplayr 1462
        DEBUGF  1,"ACK now!\n"
1733 hidnplayr 1463
 
2390 hidnplayr 1464
        push    ebx
1465
        mov     eax, ebx
1466
        call    TCP_output
1467
        pop     ebx
1733 hidnplayr 1468
 
1469
  .dumpit:
1470
 
2402 hidnplayr 1471
        pusha
1472
        lea     ecx, [ebx + SOCKET.mutex]
1473
        call    mutex_unlock
1474
        popa
1733 hidnplayr 1475
 
2390 hidnplayr 1476
        call    kernel_free
1477
        add     esp, 4
1478
        ret
1733 hidnplayr 1479
 
1480
 
1481
 
1482
 
1483
 
1484
 
1485
 
1486
;------------------------------------------
1487
; Generate an ACK, droping incoming segment
1488
 
1489
align 4
1490
.drop_after_ack:
1491
 
2390 hidnplayr 1492
        DEBUGF  1,"Drop after ACK\n"
1733 hidnplayr 1493
 
2390 hidnplayr 1494
        test    [edx + TCP_header.Flags], TH_RST
1495
        jnz     .drop
1733 hidnplayr 1496
 
2390 hidnplayr 1497
        and     [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1733 hidnplayr 1498
 
2402 hidnplayr 1499
        pusha
1500
        lea     ecx, [ebx + SOCKET.mutex]
1501
        call    mutex_unlock
1502
        popa
1733 hidnplayr 1503
 
2390 hidnplayr 1504
        push    ebx
1838 hidnplayr 1505
;        mov     cl, TH_ACK
1506
;        call    TCP_respond_socket
2390 hidnplayr 1507
        mov     eax, ebx
1508
        call    TCP_output
1509
        pop     ebx
1733 hidnplayr 1510
 
2390 hidnplayr 1511
        call    kernel_free
1512
        add     esp, 4
1513
        ret
1733 hidnplayr 1514
 
1515
 
1516
 
1517
 
1518
 
1519
 
1520
 
1521
 
1522
;-------------------------------------------
1523
; Generate an RST, dropping incoming segment
1524
 
1525
align 4
1526
.drop_with_reset:
1527
 
2402 hidnplayr 1528
        pusha
1529
        lea     ecx, [ebx + SOCKET.mutex]
1530
        call    mutex_unlock
1531
        popa
1733 hidnplayr 1532
 
1533
.drop_with_reset_not_locked:
1534
 
2390 hidnplayr 1535
        DEBUGF  1,"Drop with reset\n"
1733 hidnplayr 1536
 
2390 hidnplayr 1537
        test    [edx + TCP_header.Flags], TH_RST
1538
        jnz     .drop
1733 hidnplayr 1539
 
2390 hidnplayr 1540
        ;;; if its a multicast/broadcast, also drop
1733 hidnplayr 1541
 
2390 hidnplayr 1542
        test    [edx + TCP_header.Flags], TH_ACK
1543
        jnz     .respond_ack
1733 hidnplayr 1544
 
2390 hidnplayr 1545
        test    [edx + TCP_header.Flags], TH_SYN
1546
        jnz     .respond_syn
1733 hidnplayr 1547
 
2390 hidnplayr 1548
        call    kernel_free
1549
        add     esp, 4
1550
        ret
1733 hidnplayr 1551
 
1552
  .respond_ack:
1553
 
2390 hidnplayr 1554
        push    ebx
1555
        mov     cl, TH_RST
1556
        call    TCP_respond_socket
1557
        pop     ebx
1733 hidnplayr 1558
 
2390 hidnplayr 1559
        jmp     .destroy_new_socket
1733 hidnplayr 1560
 
1561
 
1562
  .respond_syn:
1563
 
2390 hidnplayr 1564
        push    ebx
1565
        mov     cl, TH_RST + TH_ACK
1566
        call    TCP_respond_socket
1567
        pop     ebx
1733 hidnplayr 1568
 
2390 hidnplayr 1569
        jmp     .destroy_new_socket
1733 hidnplayr 1570
 
1571
 
1572
 
1573
 
1574
 
1575
 
1576
 
1577
;-----
1578
; Drop
1579
 
1580
align 4
1581
.drop:
1582
 
2402 hidnplayr 1583
        pusha
1584
        lea     ecx, [ebx + SOCKET.mutex]
1585
        call    mutex_unlock
1586
        popa
1733 hidnplayr 1587
 
1588
.drop_not_locked:
1589
 
2390 hidnplayr 1590
        DEBUGF  1,"Dropping packet\n"
1733 hidnplayr 1591
 
2390 hidnplayr 1592
        ;;;; If debugging options are enabled, output the packet somwhere
1733 hidnplayr 1593
 
1594
  .destroy_new_socket:
1595
 
2390 hidnplayr 1596
        ;;;; kill the newly created socket
1733 hidnplayr 1597
 
2390 hidnplayr 1598
        call    kernel_free
1599
        add     esp, 4
1600
        ret