Subversion Repositories Kolibri OS

Rev

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

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