Subversion Repositories Kolibri OS

Rev

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

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