Subversion Repositories Kolibri OS

Rev

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

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