Subversion Repositories Kolibri OS

Rev

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