Subversion Repositories Kolibri OS

Rev

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