Subversion Repositories Kolibri OS

Rev

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