Subversion Repositories Kolibri OS

Rev

Rev 6907 | Rev 6910 | 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: 6908 $
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:
6908 ashmew2 40
 
3545 hidnplayr 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
 
6908 ashmew2 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
6908 ashmew2 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
 
6908 ashmew2 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
 
6908 ashmew2 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
 
6908 ashmew2 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
 
6908 ashmew2 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
6908 ashmew2 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
6908 ashmew2 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
 
6908 ashmew2 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
 
6908 ashmew2 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
 
6908 ashmew2 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
 
6908 ashmew2 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
 
6908 ashmew2 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
 
6908 ashmew2 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:
6908 ashmew2 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]
6908 ashmew2 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]
6908 ashmew2 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
       @@:
6908 ashmew2 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
 
6908 ashmew2 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
 
6908 ashmew2 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
 
6908 ashmew2 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
 
6908 ashmew2 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
6908 ashmew2 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
 
6908 ashmew2 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
 
6908 ashmew2 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:
6908 ashmew2 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:
6908 ashmew2 854
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Connection reset\n"
3545 hidnplayr 855
        mov     [ebx + SOCKET.errorcode], ECONNRESET
856
  .close:
6908 ashmew2 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
 
6710 clevermous 862
        jmp     .drop
3545 hidnplayr 863
 
6476 hidnplayr 864
;-----------------------------------------------------------------------------------
3545 hidnplayr 865
  .rst_close:
6908 ashmew2 866
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Closing with reset\n"
6710 clevermous 867
        jmp     .unlock_and_close
3545 hidnplayr 868
 
6476 hidnplayr 869
;-----------------------------------------------------------------------------------
3545 hidnplayr 870
  .no_rst:
871
 
6476 hidnplayr 872
;-----------------------------------------------------------------------------------
873
;
874
; Handle SYN-full and ACK-less segments
875
;
876
;-----------------------------------------------------------------------------------
3545 hidnplayr 877
 
6476 hidnplayr 878
; If a SYN is in the window, then this is an error so we send an RST and drop the connection
879
 
3545 hidnplayr 880
        test    [edx + TCP_header.Flags], TH_SYN
881
        jz      .not_syn_full
882
 
883
        mov     eax, ebx
884
        mov     ebx, ECONNRESET
6011 hidnplayr 885
        call    tcp_drop
3545 hidnplayr 886
        jmp     .drop_with_reset
887
  .not_syn_full:
888
 
6476 hidnplayr 889
; If ACK bit is off, we drop the segment and return
3545 hidnplayr 890
 
891
        test    [edx + TCP_header.Flags], TH_ACK
892
        jz      .drop
893
 
6476 hidnplayr 894
;----------------------------------------------------------------------------------
895
;
896
; ACK processing for SYN_RECEIVED state
897
;
898
;----------------------------------------------------------------------------------
899
 
3545 hidnplayr 900
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
901
        jb      .ack_processed                                  ; states: closed, listen, syn_sent
902
        ja      .no_syn_rcv                                     ; established, fin_wait_1, fin_wait_2, close_wait, closing, last_ack, time_wait
903
 
6908 ashmew2 904
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_received\n"
3545 hidnplayr 905
 
906
        mov     eax, [edx + TCP_header.AckNumber]
907
        cmp     [ebx + TCP_SOCKET.SND_UNA], eax
908
        ja      .drop_with_reset
909
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
910
        ja      .drop_with_reset
911
 
6476 hidnplayr 912
        inc     [TCPS_connects]
3545 hidnplayr 913
 
914
        mov     eax, ebx
6011 hidnplayr 915
        call    socket_is_connected
3545 hidnplayr 916
        mov     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
917
 
918
; Do window scaling?
919
 
920
        test    [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
921
        jz      @f
922
        test    [ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE
923
        jz      @f
924
 
6476 hidnplayr 925
        push    word[ebx + TCP_SOCKET.requested_s_scale]        ; Set send and receive scale factors to the received values
926
        pop     word[ebx + TCP_SOCKET.SND_SCALE]
3545 hidnplayr 927
       @@:
928
 
6011 hidnplayr 929
        call    tcp_reassemble
3545 hidnplayr 930
 
931
        mov     eax, [edx + TCP_header.SequenceNumber]
932
        dec     eax
933
        mov     [ebx + TCP_SOCKET.SND_WL1], eax
934
  .no_syn_rcv:
935
 
6476 hidnplayr 936
;-----------------------------------------------------------------------------------
937
;
938
; ACK processing for SYN_RECEIVED state and higher
939
;
940
;-----------------------------------------------------------------------------------
941
 
3545 hidnplayr 942
;-------------------------
6476 hidnplayr 943
; Check for duplicate ACKs
3545 hidnplayr 944
 
945
        mov     eax, [edx + TCP_header.AckNumber]
946
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
6476 hidnplayr 947
        ja      .dup_ack_complete
3545 hidnplayr 948
 
949
        test    ecx, ecx
950
        jnz     .reset_dupacks
951
 
6476 hidnplayr 952
        mov     eax, dword[edx + TCP_header.Window]
3545 hidnplayr 953
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
954
        jne     .reset_dupacks
955
 
6476 hidnplayr 956
        inc     [TCPS_rcvdupack]
6908 ashmew2 957
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Processing duplicate ACK\n"
3545 hidnplayr 958
 
959
; If we have outstanding data, other than a window probe, this is a completely duplicate ACK
960
; (window info didnt change) The ACK is the biggest we've seen and we've seen exactly our rexmt threshold of them,
961
; assume a packet has been dropped and retransmit it. Kludge snd_nxt & the congestion window so we send only this one packet.
962
 
3600 hidnplayr 963
        test    [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission
6476 hidnplayr 964
        jz      .reset_dupacks
3545 hidnplayr 965
 
966
        mov     eax, [edx + TCP_header.AckNumber]
967
        cmp     eax, [ebx + TCP_SOCKET.SND_UNA]
6476 hidnplayr 968
        jne     .reset_dupacks
3545 hidnplayr 969
 
6476 hidnplayr 970
; Increment dupplicat ACK counter
971
; If it reaches the threshold, re-transmit the missing segment
3545 hidnplayr 972
 
973
        inc     [ebx + TCP_SOCKET.t_dupacks]
974
        cmp     [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
6476 hidnplayr 975
        jb      .dup_ack_complete
976
        ja      .another_lost
3545 hidnplayr 977
 
6908 ashmew2 978
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Re-transmitting lost segment\n"
6476 hidnplayr 979
 
3545 hidnplayr 980
        push    [ebx + TCP_SOCKET.SND_NXT]              ; >>>>
981
 
982
        mov     eax, [ebx + TCP_SOCKET.SND_WND]
983
        cmp     eax, [ebx + TCP_SOCKET.SND_CWND]
4296 hidnplayr 984
        jbe     @f
985
        mov     eax, [ebx + TCP_SOCKET.SND_CWND]
986
  @@:
3545 hidnplayr 987
        shr     eax, 1
988
        push    edx
989
        xor     edx, edx
990
        div     [ebx + TCP_SOCKET.t_maxseg]
991
        cmp     eax, 2
992
        ja      @f
993
        xor     eax, eax
994
        mov     al, 2
995
       @@:
996
        mul     [ebx + TCP_SOCKET.t_maxseg]
997
        pop     edx
998
        mov     [ebx + TCP_SOCKET.SND_SSTHRESH], eax
999
 
3600 hidnplayr 1000
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission   ; turn off retransmission timer
3545 hidnplayr 1001
        mov     [ebx + TCP_SOCKET.t_rtt], 0
1002
        mov     eax, [edx + TCP_header.AckNumber]
1003
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1004
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
1005
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
1006
 
1007
; Unlock the socket
6476 hidnplayr 1008
 
3545 hidnplayr 1009
        push    ebx
1010
        lea     ecx, [ebx + SOCKET.mutex]
1011
        call    mutex_unlock
1012
 
1013
; retransmit missing segment
6476 hidnplayr 1014
 
3545 hidnplayr 1015
        mov     eax, [esp]
6011 hidnplayr 1016
        call    tcp_output
3545 hidnplayr 1017
 
1018
; Lock the socket again
6476 hidnplayr 1019
 
3545 hidnplayr 1020
        mov     ecx, [esp]
1021
        add     ecx, SOCKET.mutex
1022
        call    mutex_lock
3711 clevermous 1023
        pop     ebx
3545 hidnplayr 1024
 
1025
; Continue processing
6476 hidnplayr 1026
 
3545 hidnplayr 1027
        xor     edx, edx
1028
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
1029
        mul     [ebx + TCP_SOCKET.t_dupacks]
1030
        add     eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
1031
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
1032
 
1033
        pop     eax                                     ; <<<<
1034
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1035
        jb      @f
1036
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1037
       @@:
1038
        jmp     .drop
1039
 
6476 hidnplayr 1040
  .another_lost:
6908 ashmew2 1041
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Increasing congestion window\n"
3545 hidnplayr 1042
 
1043
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
1044
        add     [ebx + TCP_SOCKET.SND_CWND], eax
1045
 
1046
; Unlock the socket
6476 hidnplayr 1047
 
3545 hidnplayr 1048
        push    ebx
1049
        lea     ecx, [ebx + SOCKET.mutex]
1050
        call    mutex_unlock
1051
 
6476 hidnplayr 1052
; retransmit missing segment, again
1053
 
3545 hidnplayr 1054
        mov     eax, [esp]
6011 hidnplayr 1055
        call    tcp_output
3545 hidnplayr 1056
 
1057
; Lock the socket again
6476 hidnplayr 1058
 
3545 hidnplayr 1059
        mov     ecx, [esp]
1060
        add     ecx, SOCKET.mutex
1061
        call    mutex_lock
1062
        pop     ebx
1063
 
6476 hidnplayr 1064
; And drop the incoming segment
1065
 
3545 hidnplayr 1066
        jmp     .drop
1067
 
6476 hidnplayr 1068
  .reset_dupacks:               ; We got a new ACK, reset duplicate ACK counter
1069
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
1070
        jmp     .ack_processed
3545 hidnplayr 1071
 
6476 hidnplayr 1072
  .dup_ack_complete:
3545 hidnplayr 1073
 
1074
;-------------------------------------------------
1075
; If the congestion window was inflated to account
1076
; for the other side's cached packets, retract it
1077
 
1078
        mov     eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
1079
        cmp     eax, [ebx + TCP_SOCKET.SND_CWND]
1080
        ja      @f
1081
        cmp     [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
1082
        jbe     @f
1083
        mov     [ebx + TCP_SOCKET.SND_CWND], eax
1084
       @@:
1085
 
1086
        mov     [ebx + TCP_SOCKET.t_dupacks], 0
1087
 
1088
        mov     eax, [edx + TCP_header.AckNumber]
1089
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
1090
        jbe     @f
5442 hidnplayr 1091
        inc     [TCPS_rcvacktoomuch]
3545 hidnplayr 1092
        jmp     .drop_after_ack
1093
       @@:
1094
 
1095
        mov     edi, [edx + TCP_header.AckNumber]
1096
        sub     edi, [ebx + TCP_SOCKET.SND_UNA]         ; now we got the number of acked bytes in edi
5442 hidnplayr 1097
        inc     [TCPS_rcvackpack]
1098
        add     [TCPS_rcvackbyte], edi
6908 ashmew2 1099
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: acceptable ACK for %u bytes\n", edi
3545 hidnplayr 1100
 
6476 hidnplayr 1101
;-----------------------------------------------------------------------------------
1102
;
4347 hidnplayr 1103
; RTT measurements and retransmission timer
6476 hidnplayr 1104
;
1105
;-----------------------------------------------------------------------------------
3545 hidnplayr 1106
 
1107
; If we have a timestamp, update smoothed RTT
1108
 
4347 hidnplayr 1109
        test    [temp_bits], TCP_BIT_TIMESTAMP
3545 hidnplayr 1110
        jz      .timestamp_not_present
4344 hidnplayr 1111
        mov     eax, [timestamp]
3545 hidnplayr 1112
        sub     eax, [ebx + TCP_SOCKET.ts_ecr]
1113
        inc     eax
6011 hidnplayr 1114
        call    tcp_xmit_timer
3545 hidnplayr 1115
        jmp     .rtt_done_
1116
 
1117
; If no timestamp but transmit timer is running and timed sequence number was acked,
1118
; update smoothed RTT. Since we now have an RTT measurement, cancel the timer backoff
1119
; (Phil Karn's retransmit algo)
1120
; Recompute the initial retransmit timer
1121
 
1122
  .timestamp_not_present:
1123
        mov     eax, [edx + TCP_header.AckNumber]
1124
        cmp     eax, [ebx + TCP_SOCKET.t_rtseq]
1125
        jbe     .rtt_done_
1126
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
1127
        test    eax, eax
1128
        jz      .rtt_done_
6011 hidnplayr 1129
        call    tcp_xmit_timer
3545 hidnplayr 1130
  .rtt_done_:
1131
 
1132
; If all outstanding data is acked, stop retransmit timer and remember to restart (more output or persist)
1133
; If there is more data to be acked, restart retransmit timer, using current (possible backed-off) value.
1134
 
1135
        mov     eax, [ebx + TCP_SOCKET.SND_MAX]
1136
        cmp     eax, [edx + TCP_header.AckNumber]
1137
        jne     .more_data
3600 hidnplayr 1138
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission
4347 hidnplayr 1139
        or      [temp_bits], TCP_BIT_NEEDOUTPUT
3545 hidnplayr 1140
        jmp     .no_restart
1141
  .more_data:
3600 hidnplayr 1142
        test    [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
1143
        jnz     .no_restart
3545 hidnplayr 1144
 
1145
        mov     eax, [ebx + TCP_SOCKET.t_rxtcur]
1146
        mov     [ebx + TCP_SOCKET.timer_retransmission], eax
3600 hidnplayr 1147
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission
3545 hidnplayr 1148
  .no_restart:
1149
 
6476 hidnplayr 1150
;-----------------------------------------------------------------------------------
1151
;
3545 hidnplayr 1152
; Open congestion window in response to ACKs
6476 hidnplayr 1153
;
1154
;-----------------------------------------------------------------------------------
3545 hidnplayr 1155
 
6476 hidnplayr 1156
; If the window gives us less then sstresh packets in flight, open exponentially.
1157
; Otherwise, open lineary
1158
 
3545 hidnplayr 1159
        mov     esi, [ebx + TCP_SOCKET.SND_CWND]
1160
        mov     eax, [ebx + TCP_SOCKET.t_maxseg]
1161
        cmp     esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
1162
        jbe     @f
1163
        push    edx
1164
        push    eax
6476 hidnplayr 1165
        mul     eax             ; t_maxseg*t_maxseg
1166
        div     esi             ; t_maxseg*t_maxseg/snd_cwnd
1167
        pop     edx             ; t_maxseg
1168
        shr     edx, 3          ; t_maxseg/8
1169
        add     eax, edx        ; t_maxseg*t_maxseg/snd_cwnd + t_maxseg/8
3545 hidnplayr 1170
        pop     edx
1171
       @@:
1172
        add     esi, eax
1173
 
1174
        push    ecx
1175
        mov     cl, [ebx + TCP_SOCKET.SND_SCALE]
1176
        mov     eax, TCP_max_win
1177
        shl     eax, cl
1178
        pop     ecx
1179
 
1180
        cmp     esi, eax
4296 hidnplayr 1181
        jbe     @f
1182
        mov     esi, eax
1183
  @@:
3545 hidnplayr 1184
        mov     [ebx + TCP_SOCKET.SND_CWND], esi
1185
 
6476 hidnplayr 1186
;-----------------------------------------------------------------------------------
1187
;
3545 hidnplayr 1188
; Remove acknowledged data from send buffer
6476 hidnplayr 1189
;
1190
;-----------------------------------------------------------------------------------
3545 hidnplayr 1191
 
6476 hidnplayr 1192
; If the number of bytes acknowledged exceeds the number of bytes on the send buffer,
1193
; snd_wnd is decremented by the number of bytes in the send buffer and TCP knows
1194
; that its FIN has been ACKed. (FIN occupies 1 byte in the sequence number space)
1195
 
3545 hidnplayr 1196
        cmp     edi, [ebx + STREAM_SOCKET.snd.size]
6476 hidnplayr 1197
        jbe     .no_fin_ack
3545 hidnplayr 1198
 
6476 hidnplayr 1199
; Drop all data in output buffer
1200
 
3545 hidnplayr 1201
        push    ecx edx ebx
1202
        mov     ecx, [ebx + STREAM_SOCKET.snd.size]
6476 hidnplayr 1203
        sub     [ebx + TCP_SOCKET.SND_WND], ecx
3545 hidnplayr 1204
        lea     eax, [ebx + STREAM_SOCKET.snd]
6011 hidnplayr 1205
        call    socket_ring_free
3545 hidnplayr 1206
        pop     ebx edx ecx
1207
 
6908 ashmew2 1208
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is acked\n"
5133 hidnplayr 1209
        or      [temp_bits], TCP_BIT_FIN_IS_ACKED
6476 hidnplayr 1210
        jmp     .ack_complete
1211
  .no_fin_ack:
3545 hidnplayr 1212
 
6476 hidnplayr 1213
; Drop acknowledged data
3545 hidnplayr 1214
 
1215
        push    ecx edx ebx
1216
        mov     ecx, edi
1217
        lea     eax, [ebx + STREAM_SOCKET.snd]
6011 hidnplayr 1218
        call    socket_ring_free
3545 hidnplayr 1219
        pop     ebx
1220
        sub     [ebx + TCP_SOCKET.SND_WND], ecx
1221
        pop     edx ecx
6476 hidnplayr 1222
  .ack_complete:
3545 hidnplayr 1223
 
6476 hidnplayr 1224
;-----------------------------------------------------------------------------------
1225
;
3545 hidnplayr 1226
; Wake up process waiting on send buffer
6476 hidnplayr 1227
;
1228
;-----------------------------------------------------------------------------------
3545 hidnplayr 1229
 
1230
        mov     eax, ebx
6011 hidnplayr 1231
        call    socket_notify
3545 hidnplayr 1232
 
1233
; Update TCPS
6476 hidnplayr 1234
 
3545 hidnplayr 1235
        mov     eax, [edx + TCP_header.AckNumber]
1236
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1237
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1238
        jb      @f
1239
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1240
       @@:
1241
 
6476 hidnplayr 1242
;-----------------------------------------------------------------------------------
1243
;
1244
; State specific ACK handeling
1245
;
1246
;-----------------------------------------------------------------------------------
3545 hidnplayr 1247
 
1248
        mov     eax, [ebx + TCP_SOCKET.t_state]
6476 hidnplayr 1249
        jmp     dword[.ack_sw_list+eax*4]
3545 hidnplayr 1250
 
6476 hidnplayr 1251
  .ack_sw_list:
3545 hidnplayr 1252
        dd      .ack_processed  ; TCPS_CLOSED
1253
        dd      .ack_processed  ; TCPS_LISTEN
1254
        dd      .ack_processed  ; TCPS_SYN_SENT
1255
        dd      .ack_processed  ; TCPS_SYN_RECEIVED
1256
        dd      .ack_processed  ; TCPS_ESTABLISHED
1257
        dd      .ack_processed  ; TCPS_CLOSE_WAIT
1258
        dd      .ack_fw1        ; TCPS_FIN_WAIT_1
1259
        dd      .ack_c          ; TCPS_CLOSING
1260
        dd      .ack_la         ; TCPS_LAST_ACK
1261
        dd      .ack_processed  ; TCPS_FIN_WAIT_2
1262
        dd      .ack_tw         ; TCPS_TIMED_WAIT
1263
 
6476 hidnplayr 1264
;-----------------------------------------------------------------------------------
1265
  .ack_fw1:
1266
; If our FIN is now acked, enter FIN_WAIT_2
3545 hidnplayr 1267
 
5133 hidnplayr 1268
        test    [temp_bits], TCP_BIT_FIN_IS_ACKED
1269
        jz      .ack_processed
3545 hidnplayr 1270
 
6476 hidnplayr 1271
; If we can't receive any more data, then closing user can proceed.
1272
; Starting the timer is contrary to the specification, but if we dont get a FIN,
1273
; we'll hang forever.
1274
 
3545 hidnplayr 1275
        test    [ebx + SOCKET.state], SS_CANTRCVMORE
1276
        jnz     @f
1277
        mov     eax, ebx
6011 hidnplayr 1278
        call    socket_is_disconnected
3545 hidnplayr 1279
        mov     [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle
3600 hidnplayr 1280
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
3545 hidnplayr 1281
       @@:
1282
        mov     [ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
1283
        jmp     .ack_processed
1284
 
6476 hidnplayr 1285
;-----------------------------------------------------------------------------------
3545 hidnplayr 1286
  .ack_c:
6476 hidnplayr 1287
; Enter the TIME_WAIT state if our FIN is acked in CLOSED state.
1288
 
5133 hidnplayr 1289
        test    [temp_bits], TCP_BIT_FIN_IS_ACKED
1290
        jz      .ack_processed
3545 hidnplayr 1291
 
6476 hidnplayr 1292
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIME_WAIT
3545 hidnplayr 1293
        mov     eax, ebx
6011 hidnplayr 1294
        call    tcp_cancel_timers
3545 hidnplayr 1295
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
3600 hidnplayr 1296
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
3545 hidnplayr 1297
        mov     eax, ebx
6011 hidnplayr 1298
        call    socket_is_disconnected
3545 hidnplayr 1299
        jmp     .ack_processed
1300
 
6476 hidnplayr 1301
;-----------------------------------------------------------------------------------
3545 hidnplayr 1302
  .ack_la:
6476 hidnplayr 1303
; In LAST_ACK state, we may still be waiting for data to drain and/or to be acked.
1304
; If our FIN is acked however, enter CLOSED state and return.
1305
 
5133 hidnplayr 1306
        test    [temp_bits], TCP_BIT_FIN_IS_ACKED
1307
        jz      .ack_processed
3545 hidnplayr 1308
 
6710 clevermous 1309
  .unlock_and_close:
3652 hidnplayr 1310
        push    ebx
1311
        lea     ecx, [ebx + SOCKET.mutex]
1312
        call    mutex_unlock
6476 hidnplayr 1313
        pop     eax
3652 hidnplayr 1314
 
6011 hidnplayr 1315
        call    tcp_close
4366 hidnplayr 1316
        jmp     .drop_no_socket
3545 hidnplayr 1317
 
6476 hidnplayr 1318
;-----------------------------------------------------------------------------------
3545 hidnplayr 1319
  .ack_tw:
6476 hidnplayr 1320
; In TIME_WAIT state the only thing that should arrive is a retransmission of the remote FIN.
1321
; Acknowledge it and restart the FINACK timer
1322
 
1323
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2*TCP_time_MSL
1324
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_2msl
3545 hidnplayr 1325
        jmp     .drop_after_ack
1326
 
6476 hidnplayr 1327
;-----------------------------------------------------------------------------------
1328
;
1329
; Initiation of Passive Open?
1330
;
1331
;-----------------------------------------------------------------------------------
3545 hidnplayr 1332
 
6476 hidnplayr 1333
  .state_listen:
6908 ashmew2 1334
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=listen\n"
3545 hidnplayr 1335
 
1336
        test    [edx + TCP_header.Flags], TH_RST
1337
        jnz     .drop
1338
 
1339
        test    [edx + TCP_header.Flags], TH_ACK
1340
        jnz     .drop_with_reset
1341
 
1342
        test    [edx + TCP_header.Flags], TH_SYN
1343
        jz      .drop
1344
 
6476 hidnplayr 1345
        inc     [TCPS_accepts]
5442 hidnplayr 1346
 
3545 hidnplayr 1347
;;; TODO: check if it's a broadcast or multicast, and drop if so
1348
 
6476 hidnplayr 1349
;-------------------------------------------
1350
; Processing of SYN received in LISTEN state
1351
 
5842 hidnplayr 1352
        push    [edi + IPv4_header.SourceAddress]
3545 hidnplayr 1353
        pop     [ebx + IP_SOCKET.RemoteIP]
1354
 
1355
        push    [edx + TCP_header.SourcePort]
1356
        pop     [ebx + TCP_SOCKET.RemotePort]
1357
 
1358
        push    [edx + TCP_header.SequenceNumber]
1359
        pop     [ebx + TCP_SOCKET.IRS]
1360
 
1361
        mov     eax, [TCP_sequence_num]
6476 hidnplayr 1362
        add     [TCP_sequence_num], TCP_ISSINCR / 2
3545 hidnplayr 1363
        mov     [ebx + TCP_SOCKET.ISS], eax
1364
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1365
 
6011 hidnplayr 1366
        tcp_sendseqinit ebx
1367
        tcp_rcvseqinit ebx
3545 hidnplayr 1368
 
1369
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
4347 hidnplayr 1370
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
3545 hidnplayr 1371
        mov     [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval  ;;;; macro
3600 hidnplayr 1372
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive
3545 hidnplayr 1373
 
1374
        lea     eax, [ebx + STREAM_SOCKET.snd]
6011 hidnplayr 1375
        call    socket_ring_create
5155 hidnplayr 1376
        test    eax, eax
1377
        jz      .drop
3545 hidnplayr 1378
 
1379
        lea     eax, [ebx + STREAM_SOCKET.rcv]
6011 hidnplayr 1380
        call    socket_ring_create
5155 hidnplayr 1381
        test    eax, eax
1382
        jz      .drop
3545 hidnplayr 1383
 
4347 hidnplayr 1384
        and     [temp_bits], not TCP_BIT_DROPSOCKET
3545 hidnplayr 1385
 
3674 hidnplayr 1386
        pusha
1387
        mov     eax, ebx
6011 hidnplayr 1388
        call    socket_notify
3674 hidnplayr 1389
        popa
3545 hidnplayr 1390
 
5133 hidnplayr 1391
        jmp     .trim
3545 hidnplayr 1392
 
6476 hidnplayr 1393
;-----------------------------------------------------------------------------------
1394
;
1395
; Completion of active open?
1396
;
1397
;-----------------------------------------------------------------------------------
3545 hidnplayr 1398
 
6476 hidnplayr 1399
  .state_syn_sent:
6908 ashmew2 1400
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_sent\n"
3545 hidnplayr 1401
 
1402
        test    [edx + TCP_header.Flags], TH_ACK
1403
        jz      @f
1404
 
1405
        mov     eax, [edx + TCP_header.AckNumber]
1406
        cmp     eax, [ebx + TCP_SOCKET.ISS]
1407
        jbe     .drop_with_reset
1408
 
1409
        cmp     eax, [ebx + TCP_SOCKET.SND_MAX]
1410
        ja      .drop_with_reset
1411
       @@:
1412
 
1413
        test    [edx + TCP_header.Flags], TH_RST
1414
        jz      @f
1415
 
1416
        test    [edx + TCP_header.Flags], TH_ACK
1417
        jz      .drop
1418
 
1419
        mov     eax, ebx
1420
        mov     ebx, ECONNREFUSED
6011 hidnplayr 1421
        call    tcp_drop
3545 hidnplayr 1422
        jmp     .drop
1423
       @@:
1424
 
6476 hidnplayr 1425
;-----------------------------------------------------------------------------------
1426
;
1427
; Process received SYN in response to an active open
1428
;
1429
;-----------------------------------------------------------------------------------
1430
 
3545 hidnplayr 1431
        test    [edx + TCP_header.Flags], TH_SYN
1432
        jz      .drop
1433
 
1434
        test    [edx + TCP_header.Flags], TH_ACK
6476 hidnplayr 1435
        jz      @f
3545 hidnplayr 1436
 
1437
        mov     eax, [edx + TCP_header.AckNumber]
1438
        mov     [ebx + TCP_SOCKET.SND_UNA], eax
1439
        cmp     eax, [ebx + TCP_SOCKET.SND_NXT]
1440
        jbe     @f
1441
        mov     [ebx + TCP_SOCKET.SND_NXT], eax
1442
 
3600 hidnplayr 1443
        and     [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission   ; disable retransmission timer
6476 hidnplayr 1444
       @@:
3545 hidnplayr 1445
 
1446
        push    [edx + TCP_header.SequenceNumber]
1447
        pop     [ebx + TCP_SOCKET.IRS]
1448
 
6011 hidnplayr 1449
        tcp_rcvseqinit ebx
3545 hidnplayr 1450
 
1451
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1452
 
1453
        mov     eax, [ebx + TCP_SOCKET.SND_UNA]
1454
        cmp     eax, [ebx + TCP_SOCKET.ISS]
1455
        jbe     .simultaneous_open
1456
 
1457
        test    [edx + TCP_header.Flags], TH_ACK
1458
        jz      .simultaneous_open
1459
 
6908 ashmew2 1460
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: active open\n"
3545 hidnplayr 1461
 
6476 hidnplayr 1462
        inc     [TCPS_connects]
3545 hidnplayr 1463
 
1464
; set socket state to connected
6476 hidnplayr 1465
 
3674 hidnplayr 1466
        push    eax
1467
        mov     eax, ebx
6011 hidnplayr 1468
        call    socket_is_connected
3674 hidnplayr 1469
        pop     eax
3545 hidnplayr 1470
        mov     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1471
 
1472
; Do window scaling on this connection ?
6476 hidnplayr 1473
 
3545 hidnplayr 1474
        mov     eax, [ebx + TCP_SOCKET.t_flags]
1475
        and     eax, TF_REQ_SCALE or TF_RCVD_SCALE
1476
        cmp     eax, TF_REQ_SCALE or TF_RCVD_SCALE
1477
        jne     .no_scaling
1478
 
6011 hidnplayr 1479
        mov     ax, word[ebx + TCP_SOCKET.requested_s_scale]
1480
        mov     word[ebx + TCP_SOCKET.SND_SCALE], ax
3545 hidnplayr 1481
  .no_scaling:
1482
 
1483
;;; TODO: reassemble packets queue
1484
 
6476 hidnplayr 1485
; If we didnt have time to re-transmit the SYN,
1486
; Use its rtt as our initial srtt & rtt var.
1487
 
3545 hidnplayr 1488
        mov     eax, [ebx + TCP_SOCKET.t_rtt]
1489
        test    eax, eax
5133 hidnplayr 1490
        je      .trim
6011 hidnplayr 1491
        call    tcp_xmit_timer
5133 hidnplayr 1492
        jmp     .trim
3545 hidnplayr 1493
 
6476 hidnplayr 1494
;-----------------------------------------------------------------------------------
1495
;
1496
; Simultaneous open (We have received a SYN but no ACK)
1497
;
1498
;-----------------------------------------------------------------------------------
1499
 
3545 hidnplayr 1500
  .simultaneous_open:
6908 ashmew2 1501
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: simultaneous open\n"
3545 hidnplayr 1502
        mov     [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1503
 
6476 hidnplayr 1504
;-----------------------------------------------------------------------------------
1505
;
3545 hidnplayr 1506
; Common processing for receipt of SYN
6476 hidnplayr 1507
;
1508
;-----------------------------------------------------------------------------------
3545 hidnplayr 1509
 
5133 hidnplayr 1510
  .trim:
6476 hidnplayr 1511
; Advance sequence number to correspond to first data byte.
1512
; If data, trim to stay within window, dropping FIN if necessary
1513
 
3545 hidnplayr 1514
        inc     [edx + TCP_header.SequenceNumber]
1515
 
4339 hidnplayr 1516
; Drop any received data that doesnt fit in the receive window.
6476 hidnplayr 1517
 
4339 hidnplayr 1518
        cmp     ecx, [ebx + TCP_SOCKET.RCV_WND]
1519
        jbe     .dont_trim
3545 hidnplayr 1520
 
6908 ashmew2 1521
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: received data does not fit in window, trimming %u bytes\n", eax
6476 hidnplayr 1522
        inc     [TCPS_rcvpackafterwin]
1523
        sub     ecx, [ebx + TCP_SOCKET.RCV_WND]
1524
        add     [TCPS_rcvbyteafterwin], ecx
1525
 
1526
        and     [edx + TCP_header.Flags], not (TH_FIN)
4339 hidnplayr 1527
        mov     ecx, [ebx + TCP_SOCKET.RCV_WND]
1528
 
1529
  .dont_trim:
3545 hidnplayr 1530
        mov     eax, [edx + TCP_header.SequenceNumber]
1531
        mov     [ebx + TCP_SOCKET.RCV_UP], eax
1532
        dec     eax
1533
        mov     [ebx + TCP_SOCKET.SND_WL1], eax
1534
 
6476 hidnplayr 1535
;-----------------------------------------------------------------------------------
1536
;
1537
; Update window information (step 6 in RFC793)
1538
;
1539
;-----------------------------------------------------------------------------------
1540
 
3545 hidnplayr 1541
  .ack_processed:
6908 ashmew2 1542
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: ACK processed\n"
3545 hidnplayr 1543
 
6476 hidnplayr 1544
; dont look at window if no ACK
3545 hidnplayr 1545
 
1546
        test    [edx + TCP_header.Flags], TH_ACK
1547
        jz      .no_window_update
1548
 
6476 hidnplayr 1549
; Does the segment contain new data?
1550
 
3545 hidnplayr 1551
        mov     eax, [ebx + TCP_SOCKET.SND_WL1]
1552
        cmp     eax, [edx + TCP_header.SequenceNumber]
1553
        jb      .update_window
1554
        ja      @f
1555
 
6476 hidnplayr 1556
; No new data but a new ACK ?
1557
 
3545 hidnplayr 1558
        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
1559
        cmp     eax, [edx + TCP_header.AckNumber]
1560
        jb      .update_window
1561
       @@:
1562
 
6476 hidnplayr 1563
; No new data or ACK but advertised window is larger then current window?
1564
 
1565
        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
1566
        cmp     eax, [edx + TCP_header.AckNumber]
1567
        jne     .no_window_update
1568
 
1569
        mov     eax, dword[edx + TCP_header.Window]
3545 hidnplayr 1570
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
1571
        jbe     .no_window_update
1572
 
6476 hidnplayr 1573
 
1574
; Keep track of pure window updates
3545 hidnplayr 1575
  .update_window:
6476 hidnplayr 1576
        test    ecx, ecx
1577
        jnz     @f
1578
        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
1579
        cmp     eax, [edx + TCP_header.AckNumber]
1580
        jne     @f
1581
        mov     eax, dword[edx + TCP_header.Window]
1582
        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
1583
        jbe     @f
1584
        inc     [TCPS_rcvwinupd]
1585
       @@:
3545 hidnplayr 1586
 
6476 hidnplayr 1587
        mov     eax, dword[edx + TCP_header.Window]
1588
        mov     [ebx + TCP_SOCKET.SND_WND], eax
3545 hidnplayr 1589
        cmp     eax, [ebx + TCP_SOCKET.max_sndwnd]
1590
        jbe     @f
1591
        mov     [ebx + TCP_SOCKET.max_sndwnd], eax
1592
       @@:
1593
 
6908 ashmew2 1594
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Updating window to %u\n", eax
3545 hidnplayr 1595
 
1596
        push    [edx + TCP_header.SequenceNumber]
1597
        pop     [ebx + TCP_SOCKET.SND_WL1]
1598
 
1599
        push    [edx + TCP_header.AckNumber]
1600
        pop     [ebx + TCP_SOCKET.SND_WL2]
1601
 
4347 hidnplayr 1602
        or      [temp_bits], TCP_BIT_NEEDOUTPUT
3545 hidnplayr 1603
  .no_window_update:
1604
 
6476 hidnplayr 1605
;-----------------------------------------------------------------------------------
1606
;
1607
; Process URG flag
1608
;
1609
;-----------------------------------------------------------------------------------
3545 hidnplayr 1610
 
1611
        test    [edx + TCP_header.Flags], TH_URG
1612
        jz      .not_urgent
1613
 
1614
        cmp     [edx + TCP_header.UrgentPointer], 0
1615
        jz      .not_urgent
1616
 
6476 hidnplayr 1617
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIME_WAIT
3545 hidnplayr 1618
        je      .not_urgent
1619
 
1620
; Ignore bogus urgent offsets
1621
 
1622
        movzx   eax, [edx + TCP_header.UrgentPointer]
1623
        add     eax, [ebx + STREAM_SOCKET.rcv.size]
6413 hidnplayr 1624
        cmp     eax, SOCKET_BUFFER_SIZE
3545 hidnplayr 1625
        jbe     .not_urgent
1626
 
1627
        mov     [edx + TCP_header.UrgentPointer], 0
1628
        and     [edx + TCP_header.Flags], not (TH_URG)
1629
        jmp     .do_data
1630
 
1631
  .not_urgent:
1632
 
1633
; processing of received urgent pointer
1634
 
1635
        ;;; TODO (1051-1093)
1636
 
6476 hidnplayr 1637
;-----------------------------------------------------------------------------------
1638
;
1639
; Process the data
1640
;
1641
;-----------------------------------------------------------------------------------
3545 hidnplayr 1642
 
1643
  .do_data:
6476 hidnplayr 1644
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIME_WAIT
3545 hidnplayr 1645
        jae     .final_processing
1646
 
1647
        test    [edx + TCP_header.Flags], TH_FIN
1648
        jnz     @f
1649
 
1650
        test    ecx, ecx
3756 hidnplayr 1651
        jz      .final_processing
3545 hidnplayr 1652
       @@:
1653
 
1654
; The segment is in order?
6476 hidnplayr 1655
 
3545 hidnplayr 1656
        mov     eax, [edx + TCP_header.SequenceNumber]
1657
        cmp     eax, [ebx + TCP_SOCKET.RCV_NXT]
1658
        jne     .out_of_order
1659
 
1660
; The reassembly queue is empty?
6476 hidnplayr 1661
 
3545 hidnplayr 1662
        cmp     [ebx + TCP_SOCKET.seg_next], 0
1663
        jne     .out_of_order
1664
 
1665
; The connection is established?
6476 hidnplayr 1666
 
3545 hidnplayr 1667
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1668
        jne     .out_of_order
1669
 
1670
; Ok, lets do this..  Set delayed ACK flag and copy data into socket buffer
6476 hidnplayr 1671
 
3545 hidnplayr 1672
        or      [ebx + TCP_SOCKET.t_flags], TF_DELACK
1673
 
1674
        pusha
4339 hidnplayr 1675
        mov     esi, [dataoffset]
3545 hidnplayr 1676
        add     esi, edx
1677
        lea     eax, [ebx + STREAM_SOCKET.rcv]
6011 hidnplayr 1678
        call    socket_ring_write                       ; Add the data to the socket buffer
3545 hidnplayr 1679
        add     [ebx + TCP_SOCKET.RCV_NXT], ecx         ; Update sequence number with number of bytes we have copied
1680
        popa
1681
 
1682
; Wake up the sleeping process
6476 hidnplayr 1683
 
3545 hidnplayr 1684
        mov     eax, ebx
6011 hidnplayr 1685
        call    socket_notify
3545 hidnplayr 1686
 
1687
        jmp     .data_done
1688
 
1689
  .out_of_order:
6908 ashmew2 1690
        DEBUGF  DEBUG_NETWORK_VERBOSE,  "TCP data is out of order!\nSequencenumber is %u, we expected %u.\n", \
4339 hidnplayr 1691
        [edx + TCP_header.SequenceNumber], [ebx + TCP_SOCKET.RCV_NXT]
3545 hidnplayr 1692
 
1693
; Uh-oh, some data is out of order, lets call TCP reassemble for help
1694
 
6011 hidnplayr 1695
        call    tcp_reassemble
3545 hidnplayr 1696
 
4339 hidnplayr 1697
; Generate ACK immediately, to let the other end know that a segment was received out of order,
1698
; and to tell it what sequence number is expected. This aids the fast-retransmit algorithm.
6476 hidnplayr 1699
 
3545 hidnplayr 1700
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1701
  .data_done:
1702
 
6476 hidnplayr 1703
;-----------------------------------------------------------------------------------
1704
;
1705
; Process FIN
1706
;
1707
;-----------------------------------------------------------------------------------
3545 hidnplayr 1708
 
1709
        test    [edx + TCP_header.Flags], TH_FIN
1710
        jz      .final_processing
1711
 
6908 ashmew2 1712
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Processing FIN\n"
3545 hidnplayr 1713
 
6476 hidnplayr 1714
        cmp     [ebx + TCP_SOCKET.t_state], TCPS_TIME_WAIT
3545 hidnplayr 1715
        jae     .not_first_fin
1716
 
6908 ashmew2 1717
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: First FIN for this connection\n"
3545 hidnplayr 1718
 
1719
        mov     eax, ebx
6011 hidnplayr 1720
        call    socket_cant_recv_more
3545 hidnplayr 1721
 
4347 hidnplayr 1722
        or      [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
3545 hidnplayr 1723
        inc     [ebx + TCP_SOCKET.RCV_NXT]
1724
 
1725
  .not_first_fin:
1726
        mov     eax, [ebx + TCP_SOCKET.t_state]
6476 hidnplayr 1727
        jmp     dword[.fin_sw_list+eax*4]
3545 hidnplayr 1728
 
6476 hidnplayr 1729
  .fin_sw_list:
3545 hidnplayr 1730
        dd      .final_processing       ; TCPS_CLOSED
1731
        dd      .final_processing       ; TCPS_LISTEN
1732
        dd      .final_processing       ; TCPS_SYN_SENT
1733
        dd      .fin_syn_est            ; TCPS_SYN_RECEIVED
1734
        dd      .fin_syn_est            ; TCPS_ESTABLISHED
1735
        dd      .final_processing       ; TCPS_CLOSE_WAIT
1736
        dd      .fin_wait1              ; TCPS_FIN_WAIT_1
1737
        dd      .final_processing       ; TCPS_CLOSING
1738
        dd      .final_processing       ; TCPS_LAST_ACK
1739
        dd      .fin_wait2              ; TCPS_FIN_WAIT_2
1740
        dd      .fin_timed              ; TCPS_TIMED_WAIT
1741
 
6476 hidnplayr 1742
;-----------------------------------------------------------------------------------
3545 hidnplayr 1743
  .fin_syn_est:
6476 hidnplayr 1744
; In SYN_RECEIVED and ESTABLISHED state, enter the CLOSE_WAIT state
1745
 
3545 hidnplayr 1746
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
1747
        jmp     .final_processing
1748
 
6476 hidnplayr 1749
;-----------------------------------------------------------------------------------
3545 hidnplayr 1750
  .fin_wait1:
6476 hidnplayr 1751
; From FIN_WAIT_1 state, enter CLOSING state (our FIN has not been ACKed)
1752
 
3545 hidnplayr 1753
        mov     [ebx + TCP_SOCKET.t_state], TCPS_CLOSING
1754
        jmp     .final_processing
1755
 
6476 hidnplayr 1756
;-----------------------------------------------------------------------------------
3545 hidnplayr 1757
  .fin_wait2:
6476 hidnplayr 1758
; From FIN_WAIT_2 state, enter TIME_WAIT state and start the timer
1759
 
1760
        mov     [ebx + TCP_SOCKET.t_state], TCPS_TIME_WAIT
3545 hidnplayr 1761
        mov     eax, ebx
6011 hidnplayr 1762
        call    tcp_cancel_timers
1763
        call    socket_is_disconnected
3545 hidnplayr 1764
 
6476 hidnplayr 1765
;-----------------------------------------------------------------------------------
3545 hidnplayr 1766
  .fin_timed:
6476 hidnplayr 1767
; (re)start the 2 MSL timer
3545 hidnplayr 1768
        mov     [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
3600 hidnplayr 1769
        or      [ebx + TCP_SOCKET.timer_flags], timer_flag_wait
3545 hidnplayr 1770
 
6476 hidnplayr 1771
;-----------------------------------------------------------------------------------
1772
;
1773
; Finally, drop the segment
1774
;
1775
;-----------------------------------------------------------------------------------
3545 hidnplayr 1776
 
4347 hidnplayr 1777
  .final_processing:
6908 ashmew2 1778
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Final processing\n"
4347 hidnplayr 1779
 
1780
        push    ebx
1781
        lea     ecx, [ebx + SOCKET.mutex]
1782
        call    mutex_unlock
1783
        pop     eax
1784
 
1785
        test    [temp_bits], TCP_BIT_NEEDOUTPUT
1786
        jnz     .need_output
1787
 
1788
        test    [eax + TCP_SOCKET.t_flags], TF_ACKNOW
5133 hidnplayr 1789
        jz      .done
6908 ashmew2 1790
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: ACK now!\n"
4347 hidnplayr 1791
 
1792
  .need_output:
6908 ashmew2 1793
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: need output\n"
6011 hidnplayr 1794
        call    tcp_output
4347 hidnplayr 1795
 
5133 hidnplayr 1796
  .done:
6908 ashmew2 1797
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n"
4347 hidnplayr 1798
 
6011 hidnplayr 1799
        call    net_buff_free
4347 hidnplayr 1800
        jmp     .loop
1801
 
6476 hidnplayr 1802
;-----------------------------------------------------------------------------------
1803
;
1804
; Drop segment, reply with an RST segment when needed
1805
;
1806
;-----------------------------------------------------------------------------------
4347 hidnplayr 1807
 
6476 hidnplayr 1808
;-----------------------------------------------------------------------------------
3545 hidnplayr 1809
  .drop_after_ack:
6908 ashmew2 1810
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop after ACK\n"
3545 hidnplayr 1811
 
1812
        push    edx ebx
1813
        lea     ecx, [ebx + SOCKET.mutex]
1814
        call    mutex_unlock
1815
        pop     eax edx
1816
 
1817
        test    [edx + TCP_header.Flags], TH_RST
5133 hidnplayr 1818
        jnz     .done
3545 hidnplayr 1819
 
1820
        or      [eax + TCP_SOCKET.t_flags], TF_ACKNOW
1821
        jmp     .need_output
1822
 
6476 hidnplayr 1823
;-----------------------------------------------------------------------------------
3545 hidnplayr 1824
  .drop_with_reset:
6908 ashmew2 1825
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop with reset\n"
3545 hidnplayr 1826
 
1827
        push    ebx edx
1828
        lea     ecx, [ebx + SOCKET.mutex]
1829
        call    mutex_unlock
1830
        pop     edx ebx
1831
 
1832
        test    [edx + TCP_header.Flags], TH_RST
5133 hidnplayr 1833
        jnz     .done
3545 hidnplayr 1834
 
6011 hidnplayr 1835
; TODO: if its a multicast/broadcast, also drop
3545 hidnplayr 1836
 
1837
        test    [edx + TCP_header.Flags], TH_ACK
1838
        jnz     .respond_ack
1839
 
1840
        test    [edx + TCP_header.Flags], TH_SYN
1841
        jnz     .respond_syn
5133 hidnplayr 1842
        jmp     .done
3545 hidnplayr 1843
 
1844
  .respond_ack:
1845
        push    ebx
1846
        mov     cl, TH_RST
6011 hidnplayr 1847
        call    tcp_respond
3545 hidnplayr 1848
        pop     ebx
1849
        jmp     .destroy_new_socket
1850
 
1851
  .respond_syn:
1852
        push    ebx
1853
        mov     cl, TH_RST + TH_ACK
6011 hidnplayr 1854
        call    tcp_respond
3545 hidnplayr 1855
        pop     ebx
1856
        jmp     .destroy_new_socket
1857
 
5133 hidnplayr 1858
;-----------------------------------------
1859
; The connection has no associated socket
1860
 
3647 hidnplayr 1861
  .no_socket:
1862
        pusha
1863
        mov     ecx, socket_mutex
1864
        call    mutex_unlock
1865
        popa
1866
 
3545 hidnplayr 1867
  .respond_seg_reset:
1868
        test    [edx + TCP_header.Flags], TH_RST
1869
        jnz     .drop_no_socket
1870
 
6011 hidnplayr 1871
; TODO: if its a multicast/broadcast, also drop
3545 hidnplayr 1872
 
1873
        test    [edx + TCP_header.Flags], TH_ACK
1874
        jnz     .respond_seg_ack
1875
 
1876
        test    [edx + TCP_header.Flags], TH_SYN
1877
        jnz     .respond_seg_syn
1878
 
1879
        jmp     .drop_no_socket
1880
 
1881
  .respond_seg_ack:
1882
        mov     cl, TH_RST
5842 hidnplayr 1883
        xor     ebx, ebx                ; FIXME: find a way to get the receiving device ptr
6011 hidnplayr 1884
        call    tcp_respond_segment
3545 hidnplayr 1885
        jmp     .drop_no_socket
1886
 
1887
  .respond_seg_syn:
1888
        mov     cl, TH_RST + TH_ACK
5842 hidnplayr 1889
        xor     ebx, ebx                ; FIXME: find a way to get the receiving device ptr
6011 hidnplayr 1890
        call    tcp_respond_segment
3545 hidnplayr 1891
        jmp     .drop_no_socket
1892
 
5133 hidnplayr 1893
;------------------------------------------------
1894
; Unlock socket mutex and prepare to drop segment
3545 hidnplayr 1895
 
1896
  .drop:
6908 ashmew2 1897
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Dropping segment\n"
3545 hidnplayr 1898
 
1899
        pusha
1900
        lea     ecx, [ebx + SOCKET.mutex]
1901
        call    mutex_unlock
1902
        popa
1903
 
5133 hidnplayr 1904
;--------------------------------------------
1905
; Destroy the newly created socket if needed
1906
 
3545 hidnplayr 1907
  .destroy_new_socket:
4347 hidnplayr 1908
        test    [temp_bits], TCP_BIT_DROPSOCKET
3545 hidnplayr 1909
        jz      .drop_no_socket
1910
 
1911
        mov     eax, ebx
6011 hidnplayr 1912
        call    socket_free
3545 hidnplayr 1913
 
5133 hidnplayr 1914
;------------------
1915
; Drop the segment
1916
 
3545 hidnplayr 1917
  .drop_no_socket:
6908 ashmew2 1918
        DEBUGF  DEBUG_NETWORK_VERBOSE, "TCP_input: Drop (no socket)\n"
3545 hidnplayr 1919
 
6011 hidnplayr 1920
        call    net_buff_free
3545 hidnplayr 1921
        jmp     .loop
4339 hidnplayr 1922
 
1923
endp