Subversion Repositories Kolibri OS

Rev

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

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