Subversion Repositories Kolibri OS

Rev

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