Subversion Repositories Kolibri OS

Rev

Rev 7974 | Details | Compare with Previous | Last modification | View Log | RSS feed

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