Subversion Repositories Kolibri OS

Rev

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

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