Subversion Repositories Kolibri OS

Rev

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

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