Subversion Repositories Kolibri OS

Rev

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