Subversion Repositories Kolibri OS

Rev

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