Subversion Repositories Kolibri OS

Rev

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

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