Subversion Repositories Kolibri OS

Rev

Rev 3389 | 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: 3406 $
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
3389 hidnplayr 52
 
53
        mov     [check_idle_semaphore], 5
54
        xor     edx, edx
55
        mov     eax, [TCP_input_event]
56
        mov     ebx, [eax + EVENT.id]
57
        xor     esi, esi
58
        call    raise_event
59
 
3251 hidnplayr 60
        ret
61
 
62
  .fail:
3293 hidnplayr 63
        popf
3251 hidnplayr 64
        DEBUGF  2, "TCP incoming queue is full, discarding packet!\n"
65
 
3275 hidnplayr 66
        inc     [TCP_segments_missed]   ; FIXME: use correct interface
67
 
3251 hidnplayr 68
        add     esp, sizeof.TCP_queue_entry - 8
69
        call    kernel_free
70
        add     esp, 4
3389 hidnplayr 71
 
3251 hidnplayr 72
        ret
73
 
74
 
75
 
3406 hidnplayr 76
 
3251 hidnplayr 77
align 4
78
TCP_process_input:
79
 
3389 hidnplayr 80
        xor     esi, esi
81
        mov     ecx, MANUAL_DESTROY
82
        call    create_event
83
        mov     [TCP_input_event], eax
84
 
3406 hidnplayr 85
  .wait:
3389 hidnplayr 86
        mov     eax, [TCP_input_event]
87
        call    wait_event
3251 hidnplayr 88
 
3406 hidnplayr 89
  .loop:
90
        get_from_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .wait
3389 hidnplayr 91
 
3406 hidnplayr 92
        push    [esi + TCP_queue_entry.timestamp]
3251 hidnplayr 93
        push    [esi + TCP_queue_entry.buffer_ptr]
94
 
95
        mov     ebx, [esi + TCP_queue_entry.device_ptr]
96
        mov     ecx, [esi + TCP_queue_entry.segment_size]
3406 hidnplayr 97
        mov     edi, [esi + TCP_queue_entry.ip_ptr]                     ; ptr to ipv4 source address, followed by ipv4 destination address
3251 hidnplayr 98
        mov     esi, [esi + TCP_queue_entry.segment_ptr]                ; change esi last
99
 
2957 hidnplayr 100
        DEBUGF  1,"TCP_input: size=%u time=%d\n", ecx, [timer_ticks]
1733 hidnplayr 101
 
3406 hidnplayr 102
        mov     edx, esi
103
 
104
        cmp     ebx, LOOPBACK_DEVICE
105
        je      .checksum_ok
106
 
3252 hidnplayr 107
; re-calculate the checksum (if not already done by hw)
2930 hidnplayr 108
;        test    [ebx + NET_DEVICE.hwacc], HWACC_TCP_IPv4_IN
109
;        jnz     .checksum_ok
110
 
2390 hidnplayr 111
        push    ecx esi
112
        pushw   [esi + TCP_header.Checksum]
113
        mov     [esi + TCP_header.Checksum], 0
114
        TCP_checksum (edi), (edi+4)
2937 hidnplayr 115
        pop     cx                      ; previous checksum
2390 hidnplayr 116
        cmp     cx, dx
117
        pop     edx ecx
2600 hidnplayr 118
        jne     .drop_no_socket
2930 hidnplayr 119
  .checksum_ok:
1733 hidnplayr 120
 
2930 hidnplayr 121
; Verify the data offset
2390 hidnplayr 122
        and     [edx + TCP_header.DataOffset], 0xf0                     ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
123
        shr     [edx + TCP_header.DataOffset], 2
124
        cmp     [edx + TCP_header.DataOffset], sizeof.TCP_header        ; Now see if it's at least the size of a standard TCP header
2600 hidnplayr 125
        jb      .drop_no_socket                                         ; If not, drop the packet
1733 hidnplayr 126
 
2390 hidnplayr 127
        movzx   eax, [edx + TCP_header.DataOffset]
128
        sub     ecx, eax                                                ; substract TCP header size from total segment size
2600 hidnplayr 129
        jb      .drop_no_socket                                         ; If total segment size is less then the advertised header size, drop packet
2891 hidnplayr 130
        DEBUGF  1,"TCP_input: %u bytes of data\n", ecx
1733 hidnplayr 131
 
132
;-------------------------------------------
133
; Convert Big-endian values to little endian
134
 
2390 hidnplayr 135
        ntohd   [edx + TCP_header.SequenceNumber]
136
        ntohd   [edx + TCP_header.AckNumber]
1733 hidnplayr 137
 
2390 hidnplayr 138
        ntohw   [edx + TCP_header.Window]
139
        ntohw   [edx + TCP_header.UrgentPointer]
1733 hidnplayr 140
 
2930 hidnplayr 141
;------------------------
142
; Find the socket pointer
1733 hidnplayr 143
 
144
; IP Packet TCP Destination Port = local Port
145
; (IP Packet SenderAddress = Remote IP)  OR  (Remote IP = 0)
2309 hidnplayr 146
; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0)
1733 hidnplayr 147
 
2937 hidnplayr 148
  .findpcb:
2390 hidnplayr 149
        mov     ebx, net_sockets
150
        mov     si, [edx + TCP_header.DestinationPort]
1733 hidnplayr 151
 
152
  .socket_loop:
2390 hidnplayr 153
        mov     ebx, [ebx + SOCKET.NextPtr]
154
        or      ebx, ebx
3275 hidnplayr 155
        jz      .respond_seg_reset
1733 hidnplayr 156
 
2390 hidnplayr 157
        cmp     [ebx + SOCKET.Domain], AF_INET4
158
        jne     .socket_loop
1733 hidnplayr 159
 
2390 hidnplayr 160
        cmp     [ebx + SOCKET.Protocol], IP_PROTO_TCP
161
        jne     .socket_loop
1733 hidnplayr 162
 
2390 hidnplayr 163
        cmp     [ebx + TCP_SOCKET.LocalPort], si
164
        jne     .socket_loop
1733 hidnplayr 165
 
2390 hidnplayr 166
        mov     eax, [ebx + IP_SOCKET.RemoteIP]
3406 hidnplayr 167
        cmp     eax, [edi]                              ; Ipv4 source address
2390 hidnplayr 168
        je      @f
169
        test    eax, eax
170
        jnz     .socket_loop
1733 hidnplayr 171
       @@:
172
 
2390 hidnplayr 173
        mov     ax, [ebx + TCP_SOCKET.RemotePort]
174
        cmp     [edx + TCP_header.SourcePort], ax
175
        je      .found_socket
176
        test    ax, ax
177
        jnz     .socket_loop
178
  .found_socket:                                        ; ebx now contains the socketpointer
2891 hidnplayr 179
        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 180
 
2930 hidnplayr 181
;-------------
2890 hidnplayr 182
; update stats
2930 hidnplayr 183
 
2890 hidnplayr 184
        inc     [TCP_segments_rx]                       ; FIXME: correct interface?
1733 hidnplayr 185
 
186
;----------------------------
187
; Check if socket isnt closed
188
 
2390 hidnplayr 189
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
2937 hidnplayr 190
        je      .drop_no_socket
1733 hidnplayr 191
 
192
;----------------
193
; Lock the socket
194
 
2402 hidnplayr 195
        pusha
196
        lea     ecx, [ebx + SOCKET.mutex]
197
        call    mutex_lock
198
        popa
1830 hidnplayr 199
 
2891 hidnplayr 200
        DEBUGF  1,"TCP_input: socket locked\n"
1733 hidnplayr 201
 
2937 hidnplayr 202
;---------------------------
203
; disable all temporary bits
2891 hidnplayr 204
 
2937 hidnplayr 205
        mov     [ebx + TCP_SOCKET.temp_bits], 0
2891 hidnplayr 206
 
1733 hidnplayr 207
;---------------------------------------
208
; unscale the window into a 32 bit value
209
 
2390 hidnplayr 210
        movzx   eax, [edx + TCP_header.Window]
211
        push    ecx
212
        mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
213
        shl     eax, cl
214
        mov     dword [edx + TCP_header.Window], eax    ; word after window is checksum, we dont need checksum anymore
215
        pop     ecx
1733 hidnplayr 216
 
2930 hidnplayr 217
;---------------------------------------
218
; Are we accepting incoming connections?
1733 hidnplayr 219
 
2390 hidnplayr 220
        test    [ebx + SOCKET.options], SO_ACCEPTCON
2954 hidnplayr 221
        jz      .no_accept
1733 hidnplayr 222
 
2954 hidnplayr 223
        DEBUGF  1,"TCP_input: Accepting new connection\n"
224
 
225
        pusha
226
        lea     ecx, [ebx + SOCKET.mutex]
227
        call    mutex_unlock
228
        popa
229
 
230
        push    ecx edx esi edi         ;;;
231
        call    SOCKET_fork
232
        pop     edi esi edx ecx
233
 
234
        test    eax, eax
235
        jz      .drop_no_socket
236
 
237
        mov     ebx, eax
238
 
239
        mov     [ebx + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET        ;;; FIXME: should we take over bits from previous socket?
240
 
241
        push    dword [edi + 4]                         ; Ipv4 destination addres
242
        pop     [ebx + IP_SOCKET.LocalIP]
243
 
244
        push    [edx + TCP_header.DestinationPort]
245
        pop     [ebx + TCP_SOCKET.LocalPort]
246
 
247
        mov     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
248
  .no_accept:
249
 
250
 
1733 hidnplayr 251
;-------------------------------------
252
; Reset idle timer and keepalive timer
253
 
2390 hidnplayr 254
        mov     [ebx + TCP_SOCKET.t_idle], 0
3143 hidnplayr 255
        mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_idle
1733 hidnplayr 256
 
257
;--------------------
258
; Process TCP options
259
 
3275 hidnplayr 260
        push    ecx
2954 hidnplayr 261
 
262
        movzx   ecx, [edx + TCP_header.DataOffset]
263
        cmp     ecx, sizeof.TCP_header                  ; Does header contain any options?
2390 hidnplayr 264
        je      .no_options
1733 hidnplayr 265
 
2891 hidnplayr 266
        DEBUGF  1,"TCP_input: Segment has options\n"
1733 hidnplayr 267
 
2954 hidnplayr 268
;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS
269
;;;        cmp     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
270
;;;        jz      .not_uni_xfer                           ; also no header prediction
1733 hidnplayr 271
 
2954 hidnplayr 272
        add     ecx, edx
2390 hidnplayr 273
        lea     esi, [edx + sizeof.TCP_header]
1733 hidnplayr 274
 
275
  .opt_loop:
2954 hidnplayr 276
        cmp     esi, ecx                        ; are we scanning outside of header?
2390 hidnplayr 277
        jae     .no_options
2954 hidnplayr 278
        lodsb
279
        cmp     al, TCP_OPT_EOL                 ; end of option list?
280
        je      .no_options
281
        cmp     al, TCP_OPT_NOP
282
        je      .opt_loop
283
        cmp     al, TCP_OPT_MAXSEG
2390 hidnplayr 284
        je      .opt_maxseg
2954 hidnplayr 285
        cmp     al, TCP_OPT_WINDOW
2390 hidnplayr 286
        je      .opt_window
2954 hidnplayr 287
        cmp     al, TCP_OPT_SACK_PERMIT
288
        je      .opt_sack_permit
289
;        cmp     al, TCP_OPT_SACK
290
;        je      .opt_sack
291
        cmp     al, TCP_OPT_TIMESTAMP
2390 hidnplayr 292
        je      .opt_timestamp
2954 hidnplayr 293
        DEBUGF  1,"TCP_input: unknown option:%u\n", al
2937 hidnplayr 294
        jmp     .no_options                     ; If we reach here, some unknown options were received, skip them all!
1733 hidnplayr 295
 
296
  .opt_maxseg:
2954 hidnplayr 297
        lodsb
298
        cmp     al, 4
2937 hidnplayr 299
        jne     .no_options                     ; error occured, ignore all options!
1733 hidnplayr 300
 
2390 hidnplayr 301
        test    [edx + TCP_header.Flags], TH_SYN
302
        jz      @f
1733 hidnplayr 303
 
2954 hidnplayr 304
        lodsw
2390 hidnplayr 305
        rol     ax, 8
2891 hidnplayr 306
        DEBUGF  1,"TCP_input: Maxseg=%u\n", ax
3144 hidnplayr 307
        call    TCP_mss
1733 hidnplayr 308
       @@:
2390 hidnplayr 309
        jmp     .opt_loop
1733 hidnplayr 310
 
311
 
312
  .opt_window:
2954 hidnplayr 313
        lodsb
314
        cmp     al, 3
2390 hidnplayr 315
        jne     .no_options
1733 hidnplayr 316
 
2390 hidnplayr 317
        test    [edx + TCP_header.Flags], TH_SYN
318
        jz      @f
1733 hidnplayr 319
 
2954 hidnplayr 320
        DEBUGF  1,"TCP_input: Got window scale option\n"
321
        or      [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
1733 hidnplayr 322
 
2954 hidnplayr 323
        lodsb
324
        mov     [ebx + TCP_SOCKET.SND_SCALE], al
325
        ;;;;; TODO
326
 
1733 hidnplayr 327
       @@:
2390 hidnplayr 328
        jmp     .opt_loop
1733 hidnplayr 329
 
330
 
2954 hidnplayr 331
  .opt_sack_permit:
332
        lodsb
333
        cmp     al, 2
334
        jne     .no_options
335
 
336
        test    [edx + TCP_header.Flags], TH_SYN
337
        jz      @f
338
 
339
        DEBUGF  1,"TCP_input: Selective Acknowledgement permitted\n"
340
        or      [ebx + TCP_SOCKET.t_flags], TF_SACK_PERMIT
341
 
342
       @@:
343
        jmp     .opt_loop
344
 
345
 
1733 hidnplayr 346
  .opt_timestamp:
2954 hidnplayr 347
        lodsb
348
        cmp     al, 10                          ; length must be 10
2390 hidnplayr 349
        jne     .no_options
1733 hidnplayr 350
 
2891 hidnplayr 351
        DEBUGF  1,"TCP_input: Got timestamp option\n"
1733 hidnplayr 352
 
2954 hidnplayr 353
        test    [edx + TCP_header.Flags], TH_SYN
354
        jz      @f
355
        or      [ebx + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
356
       @@:
357
 
358
        lodsd
359
        mov     [ebx + TCP_SOCKET.ts_val], eax
360
        lodsd                                   ; timestamp echo reply
361
        mov     [ebx + TCP_SOCKET.ts_ecr], eax
2937 hidnplayr 362
        or      [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
2930 hidnplayr 363
 
2946 hidnplayr 364
        ; Since we have a timestamp, lets do the paws test right away!
365
 
366
        test    [edx + TCP_header.Flags], TH_RST
367
        jnz     .no_paws
368
 
369
        mov     eax, [ebx + TCP_SOCKET.ts_recent]
370
        test    eax, eax
371
        jz      .no_paws
372
        cmp     eax, [ebx + TCP_SOCKET.ts_val]
373
        jge     .no_paws
374
 
375
        DEBUGF  1,"TCP_input: PAWS: detected an old segment\n"
376
 
3251 hidnplayr 377
        mov     eax, [esp+4+4]                          ; tcp_now
2946 hidnplayr 378
        sub     eax, [ebx + TCP_SOCKET.ts_recent_age]
3252 hidnplayr 379
 
380
        pop     ecx
2946 hidnplayr 381
        cmp     eax, TCP_PAWS_IDLE
2947 hidnplayr 382
        jle     .drop_after_ack                         ; TODO: update stats
3252 hidnplayr 383
        push    ecx
2946 hidnplayr 384
 
385
        mov     [ebx + TCP_SOCKET.ts_recent], 0         ; timestamp was invalid, fix it.
386
  .no_paws:
2390 hidnplayr 387
        jmp     .opt_loop
1733 hidnplayr 388
 
389
  .no_options:
390
 
3275 hidnplayr 391
        pop     ecx
2954 hidnplayr 392
 
1733 hidnplayr 393
;-----------------------------------------------------------------------
394
; Time to do some header prediction (Original Principle by Van Jacobson)
395
 
396
; There are two common cases for an uni-directional data transfer.
397
;
398
; General rule: the packets has no control flags, is in-sequence,
399
;   window width didnt change and we're not retransmitting.
400
;
401
; Second rules:
402
;  -  If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
403
;      In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
404
;
405
;  -  If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
406
;      If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
407
 
2390 hidnplayr 408
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
409
        jnz     .not_uni_xfer
1733 hidnplayr 410
 
2390 hidnplayr 411
        test    [edx + TCP_header.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
412
        jnz     .not_uni_xfer
1733 hidnplayr 413
 
2390 hidnplayr 414
        test    [edx + TCP_header.Flags], TH_ACK
415
        jz      .not_uni_xfer
1733 hidnplayr 416
 
2390 hidnplayr 417
        mov     eax, [edx + TCP_header.SequenceNumber]
418
        cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
419
        jne     .not_uni_xfer
1733 hidnplayr 420
 
2390 hidnplayr 421
        mov     eax, dword [edx + TCP_header.Window]
422
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
423
        jne     .not_uni_xfer
1733 hidnplayr 424
 
2390 hidnplayr 425
        mov     eax, [ebx + TCP_SOCKET.SND_NXT]
426
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
427
        jne     .not_uni_xfer
1733 hidnplayr 428
 
429
;---------------------------------------
430
; check if we are sender in the uni-xfer
431
 
432
; If the following 4 conditions are all true, this segment is a pure ACK.
433
;
434
; - The segment contains no data.
2390 hidnplayr 435
        test    ecx, ecx
436
        jnz     .not_sender
1733 hidnplayr 437
 
438
; - The congestion window is greater than or equal to the current send window.
439
;     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 440
        mov     eax, [ebx + TCP_SOCKET.SND_CWND]
441
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
442
        jb      .not_uni_xfer
1733 hidnplayr 443
 
444
; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
2390 hidnplayr 445
        mov     eax, [edx + TCP_header.AckNumber]
446
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
447
        ja      .not_uni_xfer
1733 hidnplayr 448
 
449
; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
2390 hidnplayr 450
        sub     eax, [ebx + TCP_SOCKET.SND_UNA]
451
        jbe     .not_uni_xfer
1733 hidnplayr 452
 
2891 hidnplayr 453
        DEBUGF  1,"TCP_input: Header prediction: we are sender\n"
1733 hidnplayr 454
 
455
;---------------------------------
456
; Packet is a pure ACK, process it
457
 
458
; Delete acknowledged bytes from send buffer
2390 hidnplayr 459
        pusha
460
        mov     ecx, eax
461
        lea     eax, [ebx + STREAM_SOCKET.snd]
462
        call    SOCKET_ring_free
463
        popa
1733 hidnplayr 464
 
2930 hidnplayr 465
; Update RTT estimators
466
 
2937 hidnplayr 467
        test    [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
468
        jz      .no_timestamp_rtt
3251 hidnplayr 469
        mov     eax, [esp + 4]                          ; timestamp when this segment was received
2937 hidnplayr 470
        sub     eax, [ebx + TCP_SOCKET.ts_ecr]
471
        inc     eax
472
        call    TCP_xmit_timer
473
        jmp     .rtt_done
2930 hidnplayr 474
 
2937 hidnplayr 475
  .no_timestamp_rtt:
476
        cmp     [ebx + TCP_SOCKET.t_rtt], 0
477
        je      .rtt_done
478
        mov     eax, [edx + TCP_header.AckNumber]
479
        cmp     eax, [ebx + TCP_SOCKET.t_rtseq]
480
        jbe     .rtt_done
481
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
482
        call    TCP_xmit_timer
2930 hidnplayr 483
 
2937 hidnplayr 484
  .rtt_done:
485
 
1733 hidnplayr 486
; update window pointers
2390 hidnplayr 487
        mov     eax, [edx + TCP_header.AckNumber]
488
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1733 hidnplayr 489
 
490
; Stop retransmit timer
2390 hidnplayr 491
        mov     [ebx + TCP_SOCKET.timer_retransmission], 0
1733 hidnplayr 492
 
3275 hidnplayr 493
; Unlock the socket
2402 hidnplayr 494
        pusha
495
        lea     ecx, [ebx + SOCKET.mutex]
496
        call    mutex_unlock
497
        popa
498
 
3275 hidnplayr 499
; Awaken waiting processes
2390 hidnplayr 500
        mov     eax, ebx
3257 hidnplayr 501
        call    SOCKET_notify
1733 hidnplayr 502
 
1763 hidnplayr 503
; Generate more output
2390 hidnplayr 504
        call    TCP_output
1733 hidnplayr 505
 
2937 hidnplayr 506
        jmp     .drop_no_socket
1763 hidnplayr 507
 
1733 hidnplayr 508
;-------------------------------------------------
509
; maybe we are the receiver in the uni-xfer then..
510
 
511
  .not_sender:
512
; - The amount of data in the segment is greater than 0 (data count is in ecx)
513
 
514
; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
2390 hidnplayr 515
        mov     eax, [edx + TCP_header.AckNumber]
516
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
517
        jne     .not_uni_xfer
1733 hidnplayr 518
 
519
; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp).
520
 
521
;;; TODO
522
 
2930 hidnplayr 523
;       jnz     .not_uni_xfer
1733 hidnplayr 524
 
525
; Complete processing of received data
526
 
2891 hidnplayr 527
        DEBUGF  1,"TCP_input: Header prediction: we are receiving %u bytes\n", ecx
1733 hidnplayr 528
 
2390 hidnplayr 529
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
1763 hidnplayr 530
 
2390 hidnplayr 531
        movzx   esi, [edx + TCP_header.DataOffset]
532
        add     esi, edx
533
        lea     eax, [ebx + STREAM_SOCKET.rcv]
534
        call    SOCKET_ring_write                       ; Add the data to the socket buffer
1733 hidnplayr 535
 
2390 hidnplayr 536
        mov     eax, ebx
3257 hidnplayr 537
        call    SOCKET_notify
1733 hidnplayr 538
 
2390 hidnplayr 539
        or      [ebx + TCP_SOCKET.t_flags], TF_DELACK   ; Set delayed ack flag
1733 hidnplayr 540
 
2390 hidnplayr 541
        jmp     .drop
1733 hidnplayr 542
 
543
;--------------------------------------------------
544
; Header prediction failed, do it the slow way
545
 
546
  .not_uni_xfer:
547
 
2891 hidnplayr 548
        DEBUGF  1,"TCP_input: Header prediction failed\n"
1733 hidnplayr 549
 
550
; Calculate receive window size
551
 
2942 hidnplayr 552
        push    edx
2937 hidnplayr 553
        mov     eax, SOCKETBUFFSIZE
554
        sub     eax, [ebx + STREAM_SOCKET.rcv.size]
555
        mov     edx, [ebx + TCP_SOCKET.RCV_ADV]
556
        sub     edx, [ebx + TCP_SOCKET.RCV_NXT]
557
        cmp     eax, edx
2942 hidnplayr 558
        jg      @f
2937 hidnplayr 559
        mov     eax, edx
560
       @@:
2957 hidnplayr 561
        DEBUGF  1,"Receive window size=%d\n", eax
562
        mov     [ebx + TCP_SOCKET.RCV_WND], eax
2942 hidnplayr 563
        pop     edx
1733 hidnplayr 564
 
3275 hidnplayr 565
; If we are in listen or syn_sent state, go to that specific code right away
2937 hidnplayr 566
 
2390 hidnplayr 567
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
568
        je      .LISTEN
1733 hidnplayr 569
 
2390 hidnplayr 570
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT
571
        je      .SYN_SENT
1733 hidnplayr 572
 
573
;----------------------------
574
; trim any data not in window
575
 
3406 hidnplayr 576
; check for duplicate data at beginning of segment (635)
1733 hidnplayr 577
 
2390 hidnplayr 578
        mov     eax, [ebx + TCP_SOCKET.RCV_NXT]
579
        sub     eax, [edx + TCP_header.SequenceNumber]
2942 hidnplayr 580
        jle     .no_duplicate
1733 hidnplayr 581
 
2891 hidnplayr 582
        DEBUGF  1,"TCP_input: %u bytes duplicate data!\n", eax
1763 hidnplayr 583
 
2390 hidnplayr 584
        test    [edx + TCP_header.Flags], TH_SYN
585
        jz      .no_dup_syn
1733 hidnplayr 586
 
2942 hidnplayr 587
        DEBUGF  1,"TCP_input: got duplicate syn\n"
1733 hidnplayr 588
 
2390 hidnplayr 589
        and     [edx + TCP_header.Flags], not (TH_SYN)
590
        inc     [edx + TCP_header.SequenceNumber]
1733 hidnplayr 591
 
2390 hidnplayr 592
        cmp     [edx + TCP_header.UrgentPointer], 1
593
        jbe     @f
594
        dec     [edx + TCP_header.UrgentPointer]
595
        jmp     .dup_syn
1733 hidnplayr 596
       @@:
2390 hidnplayr 597
        and     [edx + TCP_header.Flags], not (TH_URG)
1838 hidnplayr 598
  .dup_syn:
2390 hidnplayr 599
        dec     eax
1763 hidnplayr 600
  .no_dup_syn:
1733 hidnplayr 601
 
3406 hidnplayr 602
; Check for entire duplicate segment (646)
2937 hidnplayr 603
        cmp     eax, ecx                ; eax holds number of bytes to drop, ecx is data size
604
        jb      .duplicate
605
        jnz     @f
2390 hidnplayr 606
        test    [edx + TCP_header.Flags], TH_FIN
2937 hidnplayr 607
        jnz     .duplicate
608
       @@:
1733 hidnplayr 609
 
2937 hidnplayr 610
; Any valid FIN must be to the left of the window.
611
; At this point the FIN must be out of sequence or a duplicate, drop it
2390 hidnplayr 612
        and     [edx + TCP_header.Flags], not TH_FIN
2937 hidnplayr 613
 
614
; send an ACK and resynchronize and drop any data.
615
; But keep on processing for RST or ACK
3406 hidnplayr 616
        DEBUGF  1, "616\n"
2390 hidnplayr 617
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
2937 hidnplayr 618
        mov     eax, ecx
619
;TODO: update stats
1733 hidnplayr 620
 
621
;-----------------------------------------------
622
; Remove duplicate data and update urgent offset
623
 
2937 hidnplayr 624
  .duplicate:
625
;;; TODO: 677
2390 hidnplayr 626
        add     [edx + TCP_header.SequenceNumber], eax
2937 hidnplayr 627
        sub     ecx, eax
1733 hidnplayr 628
 
2390 hidnplayr 629
        sub     [edx + TCP_header.UrgentPointer], ax
2942 hidnplayr 630
        jg      @f
2390 hidnplayr 631
        and     [edx + TCP_header.Flags], not (TH_URG)
632
        mov     [edx + TCP_header.UrgentPointer], 0
1733 hidnplayr 633
       @@:
634
 
635
;--------------------------------------------------
3406 hidnplayr 636
; Handle data that arrives after process terminates (687)
1733 hidnplayr 637
 
2937 hidnplayr 638
  .no_duplicate:
2390 hidnplayr 639
        cmp     [ebx + SOCKET.PID], 0
2937 hidnplayr 640
        jne     .not_terminated
2390 hidnplayr 641
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
2937 hidnplayr 642
        jbe     .not_terminated
2390 hidnplayr 643
        test    ecx, ecx
2937 hidnplayr 644
        jz      .not_terminated
1733 hidnplayr 645
 
2937 hidnplayr 646
        mov     eax, ebx
647
        call    TCP_close
648
;;;TODO: update stats
3275 hidnplayr 649
        jmp     .respond_seg_reset
1733 hidnplayr 650
 
651
;----------------------------------------
2937 hidnplayr 652
; Remove data beyond right edge of window (700-736)
1733 hidnplayr 653
 
2937 hidnplayr 654
  .not_terminated:
2390 hidnplayr 655
        mov     eax, [edx + TCP_header.SequenceNumber]
656
        add     eax, ecx
657
        sub     eax, [ebx + TCP_SOCKET.RCV_NXT]
2957 hidnplayr 658
        sub     eax, [ebx + TCP_SOCKET.RCV_WND]         ; eax now holds the number of bytes to drop
2942 hidnplayr 659
        jle     .no_excess_data
1733 hidnplayr 660
 
2942 hidnplayr 661
        DEBUGF  1,"%d bytes beyond right edge of window\n", eax
662
 
1733 hidnplayr 663
;;; TODO: update stats
2390 hidnplayr 664
        cmp     eax, ecx
2942 hidnplayr 665
        jl      .dont_drop_all
2937 hidnplayr 666
; If a new connection request is received while in TIME_WAIT, drop the old connection and start over,
667
; if the sequence numbers are above the previous ones
1733 hidnplayr 668
 
2937 hidnplayr 669
        test    [edx + TCP_header.Flags], TH_SYN
670
        jz      .no_new_request
671
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
672
        jne     .no_new_request
2942 hidnplayr 673
;        mov     edx, [ebx + TCP_SOCKET.RCV_NXT]
674
;        cmp     edx, [edx + TCP_header.SequenceNumber]
675
;        add     edx, 64000      ; TCP_ISSINCR   FIXME
2937 hidnplayr 676
        mov     eax, ebx
677
        call    TCP_close
678
        jmp     .findpcb        ; FIXME: skip code for unscaling window, ...
679
  .no_new_request:
1733 hidnplayr 680
 
2937 hidnplayr 681
; If window is closed can only take segments at window edge, and have to drop data and PUSH from
682
; incoming segments. Continue processing, but remember to ACK. Otherwise drop segment and ACK
683
 
684
        cmp     [ebx + TCP_SOCKET.RCV_WND], 0
685
        jne     .drop_after_ack
686
        mov     eax, [edx + TCP_header.SequenceNumber]
687
        cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
688
        jne     .drop_after_ack
689
 
3406 hidnplayr 690
        DEBUGF  1, "690\n"
2937 hidnplayr 691
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
692
;;; TODO: update stats
693
        jmp     .no_excess_data
1733 hidnplayr 694
  .dont_drop_all:
2937 hidnplayr 695
;;; TODO: update stats
696
;;; TODO: 733
2957 hidnplayr 697
 
2937 hidnplayr 698
        sub     ecx, eax
699
        and     [ebx + TCP_SOCKET.t_flags], not (TH_PUSH or TH_FIN)
1733 hidnplayr 700
  .no_excess_data:
701
 
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
 
1433
 
3406 hidnplayr 1434
; The segment is in order?
1435
        mov     eax, [edx + TCP_header.SequenceNumber]
1436
        cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
1437
        jne     .out_of_order
1438
 
1439
; The reassembly queue is empty?
1440
        cmp     [ebx + TCP_SOCKET.seg_next], 0
1441
        jne     .out_of_order
1442
 
1443
; The connection is established?
1444
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1445
        jne     .out_of_order
1446
 
1447
; Ok, lets do this..  Set delayed ACK flag and copy data into socket buffer
1448
        or      [ebx + TCP_SOCKET.t_flags], TF_DELACK
1449
 
1450
        pusha
1451
        movzx   esi, [edx + TCP_header.DataOffset]
1452
        add     esi, edx
1453
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1454
        call    SOCKET_ring_write                       ; Add the data to the socket buffer
1455
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
1456
        popa
1457
 
1458
; Wake up the sleeping process
1459
        mov     eax, ebx
1460
        call    SOCKET_notify
1461
 
1462
        jmp     .data_done
1463
 
1464
  .out_of_order:
1465
 
1466
; Uh-oh, some data is out of order, lets call TCP reassemble for help
1467
 
1468
        call    TCP_reassemble
1469
 
1470
        DEBUGF  1, "1470\n"
1471
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1472
 
1473
  .data_done:
1474
 
1733 hidnplayr 1475
;---------------
1476
; FIN processing
1477
 
2891 hidnplayr 1478
        test    [edx + TCP_header.Flags], TH_FIN
2930 hidnplayr 1479
        jz      .final_processing
1733 hidnplayr 1480
 
2891 hidnplayr 1481
        DEBUGF  1,"TCP_input: Processing FIN\n"
1733 hidnplayr 1482
 
2891 hidnplayr 1483
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1484
        jae     .not_first_fin
1774 hidnplayr 1485
 
2891 hidnplayr 1486
        DEBUGF  1,"TCP_input: First FIN for this connection\n"
1774 hidnplayr 1487
 
2390 hidnplayr 1488
        mov     eax, ebx
1489
        call    SOCKET_cant_recv_more
1774 hidnplayr 1490
 
2390 hidnplayr 1491
        mov     [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1492
        inc     [ebx + TCP_SOCKET.RCV_NXT]
1774 hidnplayr 1493
 
1494
  .not_first_fin:
2390 hidnplayr 1495
        mov     eax, [ebx + TCP_SOCKET.t_state]
1496
        shl     eax, 2
1497
        jmp     dword [eax + .FIN_sw_list]
1733 hidnplayr 1498
 
1499
  .FIN_sw_list:
2937 hidnplayr 1500
        dd      .final_processing       ; TCPS_CLOSED
1501
        dd      .final_processing       ; TCPS_LISTEN
1502
        dd      .final_processing       ; TCPS_SYN_SENT
1503
        dd      .fin_syn_est            ; TCPS_SYN_RECEIVED
1504
        dd      .fin_syn_est            ; TCPS_ESTABLISHED
1505
        dd      .final_processing       ; TCPS_CLOSE_WAIT
1506
        dd      .fin_wait1              ; TCPS_FIN_WAIT_1
1507
        dd      .final_processing       ; TCPS_CLOSING
1508
        dd      .final_processing       ; TCPS_LAST_ACK
1509
        dd      .fin_wait2              ; TCPS_FIN_WAIT_2
1510
        dd      .fin_timed              ; TCPS_TIMED_WAIT
1733 hidnplayr 1511
 
1512
  .fin_syn_est:
1513
 
2390 hidnplayr 1514
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
2930 hidnplayr 1515
        jmp     .final_processing
1733 hidnplayr 1516
 
1517
  .fin_wait1:
1518
 
2390 hidnplayr 1519
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSING
2930 hidnplayr 1520
        jmp     .final_processing
1733 hidnplayr 1521
 
1522
  .fin_wait2:
1523
 
2390 hidnplayr 1524
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1525
        mov     eax, ebx
1526
        call    TCP_cancel_timers
1527
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1528
        call    SOCKET_is_disconnected
2930 hidnplayr 1529
        jmp     .final_processing
1733 hidnplayr 1530
 
1531
  .fin_timed:
2390 hidnplayr 1532
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
2930 hidnplayr 1533
        jmp     .final_processing
1733 hidnplayr 1534
 
1535
 
2930 hidnplayr 1536
  .drop_after_ack:
1537
        DEBUGF  1,"TCP_input: Drop after ACK\n"
1733 hidnplayr 1538
 
2930 hidnplayr 1539
        push    edx ebx
2891 hidnplayr 1540
        lea     ecx, [ebx + SOCKET.mutex]
1541
        call    mutex_unlock
2930 hidnplayr 1542
        pop     eax edx
2891 hidnplayr 1543
 
2930 hidnplayr 1544
        test    [edx + TCP_header.Flags], TH_RST
1545
        jnz     .dumpit
1733 hidnplayr 1546
 
2930 hidnplayr 1547
        or      [eax + TCP_SOCKET.t_flags], TF_ACKNOW
1548
        jmp     .need_output
2891 hidnplayr 1549
 
2930 hidnplayr 1550
  .drop_with_reset:
1551
        DEBUGF  1,"TCP_input: Drop with reset\n"
1552
 
1553
        push    ebx edx
2402 hidnplayr 1554
        lea     ecx, [ebx + SOCKET.mutex]
1555
        call    mutex_unlock
2930 hidnplayr 1556
        pop     edx ebx
1733 hidnplayr 1557
 
2930 hidnplayr 1558
        test    [edx + TCP_header.Flags], TH_RST
1559
        jnz     .dumpit
1733 hidnplayr 1560
 
2930 hidnplayr 1561
        ;;; if its a multicast/broadcast, also drop
1733 hidnplayr 1562
 
2930 hidnplayr 1563
        test    [edx + TCP_header.Flags], TH_ACK
1564
        jnz     .respond_ack
1733 hidnplayr 1565
 
2930 hidnplayr 1566
        test    [edx + TCP_header.Flags], TH_SYN
1567
        jnz     .respond_syn
1568
        jmp     .dumpit
1733 hidnplayr 1569
 
2930 hidnplayr 1570
;-----------------
1571
; Final processing
1733 hidnplayr 1572
 
2930 hidnplayr 1573
  .final_processing:
1574
        DEBUGF  1,"TCP_input: Final processing\n"
1733 hidnplayr 1575
 
2930 hidnplayr 1576
        push    ebx
1577
        lea     ecx, [ebx + SOCKET.mutex]
1578
        call    mutex_unlock
1579
        pop     eax
1733 hidnplayr 1580
 
2937 hidnplayr 1581
        test    [eax + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
1582
        jnz     .need_output
1733 hidnplayr 1583
 
2930 hidnplayr 1584
        test    [eax + TCP_SOCKET.t_flags], TF_ACKNOW
1585
        jz      .dumpit
1586
        DEBUGF  1,"TCP_input: ACK now!\n"
1733 hidnplayr 1587
 
2930 hidnplayr 1588
  .need_output:
2954 hidnplayr 1589
        DEBUGF  1,"TCP_input: need output\n"
2930 hidnplayr 1590
        call    TCP_output
1733 hidnplayr 1591
 
2930 hidnplayr 1592
  .dumpit:
1593
        DEBUGF  1,"TCP_input: dumping\n"
1733 hidnplayr 1594
 
2390 hidnplayr 1595
        call    kernel_free
1596
        add     esp, 4
3406 hidnplayr 1597
        jmp     .loop
1733 hidnplayr 1598
 
3275 hidnplayr 1599
;---------
1600
; Respond
1733 hidnplayr 1601
 
1602
  .respond_ack:
2390 hidnplayr 1603
        push    ebx
1604
        mov     cl, TH_RST
3143 hidnplayr 1605
        call    TCP_respond
2390 hidnplayr 1606
        pop     ebx
1607
        jmp     .destroy_new_socket
1733 hidnplayr 1608
 
1609
  .respond_syn:
2390 hidnplayr 1610
        push    ebx
1611
        mov     cl, TH_RST + TH_ACK
3143 hidnplayr 1612
        call    TCP_respond
2390 hidnplayr 1613
        pop     ebx
1614
        jmp     .destroy_new_socket
1733 hidnplayr 1615
 
3275 hidnplayr 1616
  .respond_seg_reset:
1617
        test    [edx + TCP_header.Flags], TH_RST
1618
        jnz     .drop_no_socket
1733 hidnplayr 1619
 
3275 hidnplayr 1620
        ;;; TODO: if its a multicast/broadcast, also drop
1733 hidnplayr 1621
 
3275 hidnplayr 1622
        test    [edx + TCP_header.Flags], TH_ACK
1623
        jnz     .respond_seg_ack
1624
 
1625
        test    [edx + TCP_header.Flags], TH_SYN
1626
        jnz     .respond_seg_syn
1627
 
1628
        jmp     .drop_no_socket
1629
 
1630
  .respond_seg_ack:
1631
        mov     cl, TH_RST
1632
        call    TCP_respond_segment
1633
        jmp     .drop_no_socket
1634
 
1635
  .respond_seg_syn:
1636
        mov     cl, TH_RST + TH_ACK
1637
        call    TCP_respond_segment
1638
        jmp     .drop_no_socket
1639
 
1733 hidnplayr 1640
;-----
1641
; Drop
1642
 
2930 hidnplayr 1643
  .drop:
3275 hidnplayr 1644
        DEBUGF  1,"TCP_input: Dropping segment\n"
1733 hidnplayr 1645
 
2402 hidnplayr 1646
        pusha
1647
        lea     ecx, [ebx + SOCKET.mutex]
1648
        call    mutex_unlock
1649
        popa
1733 hidnplayr 1650
 
2937 hidnplayr 1651
  .destroy_new_socket:
1652
        test    [ebx + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET
1653
        jz      .drop_no_socket
1733 hidnplayr 1654
 
2937 hidnplayr 1655
        mov     eax, ebx
1656
        call    SOCKET_free
1733 hidnplayr 1657
 
2930 hidnplayr 1658
  .drop_no_socket:
1659
        DEBUGF  1,"TCP_input: Drop (no socket)\n"
1660
 
2390 hidnplayr 1661
        call    kernel_free
1662
        add     esp, 4
3406 hidnplayr 1663
        jmp     .loop