Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
983 diamond 3
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
431 serge 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;  TCP.INC                                                     ;;
7
;;                                                              ;;
8
;;  TCP Processes for Menuet OS  TCP/IP stack                   ;;
9
;;                                                              ;;
10
;;  Copyright 2002 Mike Hibbett, mikeh@oceanfree.net            ;;
11
;;                                                              ;;
12
;;  See file COPYING for details                                ;;
13
;;  v0.6 : Added reset handling in the established state        ;;
14
;;         Added a timer per socket to allow delays when        ;;
15
;;         rx window gets below 1KB                             ;;
907 mikedld 16
;;                                                              ;;
431 serge 17
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1 ha 18
 
593 mikedld 19
$Revision: 2434 $
20
 
21
 
261 hidnplayr 22
; TCP TCB states
2434 Serge 23
TCB_LISTEN         equ        1
24
TCB_SYN_SENT       equ        2
25
TCB_SYN_RECEIVED   equ        3
26
TCB_ESTABLISHED    equ        4
27
TCB_FIN_WAIT_1     equ        5
28
TCB_FIN_WAIT_2     equ        6
29
TCB_CLOSE_WAIT     equ        7
30
TCB_CLOSING        equ        8
31
TCB_LAST_ACK       equ        9
32
TCB_TIMED_WAIT     equ        10
33
TCB_CLOSED         equ        11
1 ha 34
 
2434 Serge 35
TH_FIN  = 0x01
36
TH_SYN  = 0x02
37
TH_RST  = 0x04
907 mikedld 38
TH_PUSH = 0x08
2434 Serge 39
TH_ACK  = 0x10
40
TH_URG  = 0x20
261 hidnplayr 41
 
2434 Serge 42
TWOMSL              equ     10      ; # of secs to wait before closing socket
261 hidnplayr 43
 
2434 Serge 44
TCP_RETRIES         equ         5               ; Number of times to resend a packet
45
TCP_TIMEOUT         equ         20              ; resend if not replied to in x hs
907 mikedld 46
 
1 ha 47
;*******************************************************************
48
;   Interface
49
;
50
;       tcp_tx_handler      Handles the TCP transmit queue
51
;       tcp_rx              The protocol handler for received data
52
;       buildTCPPacket      fills in the packet headers and data
53
;       tcpStateMachine     Main state machine for received TCP packets
54
;       tcp_tcb_handler     1s timer, to erase tcb's in TIME_WAIT state
55
;
56
;*******************************************************************
57
 
58
 
261 hidnplayr 59
;   TCP Payload ( Data field in IP datagram )
60
;
61
;    0                   1                   2                   3
62
;    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
63
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64
;20 |          Source Port          |       Destination Port        |
65
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66
;24 |                        Sequence Number                        |
67
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68
;28 |                    Acknowledgment Number                      |
69
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70
;32 |  Data |           |U|A|P|R|S|F|                               |
71
;   | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
72
;   |       |           |G|K|H|T|N|N|                               |
73
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74
;36 |           Checksum            |         Urgent Pointer        |
75
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
76
;40 |                    Options                    |    Padding    |
77
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
78
;   |                             data
1 ha 79
 
261 hidnplayr 80
 
81
struc TCP_PACKET
2434 Serge 82
{  .SourcePort       dw  ?  ;+00
261 hidnplayr 83
   .DestinationPort  dw  ?  ;+02
84
   .SequenceNumber   dd  ?  ;+04
2434 Serge 85
   .AckNumber        dd  ?  ;+08
86
   .DataOffset       db  ?  ;+12 - DataOffset[0-3 bits] and Reserved[4-7]
87
   .Flags            db  ?  ;+13 - Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN
88
   .Window           dw  ?  ;+14
89
   .Checksum         dw  ?  ;+16
261 hidnplayr 90
   .UrgentPointer    dw  ?  ;+18
2434 Serge 91
   .Options          rb  3  ;+20
92
   .Padding          db  ?  ;+23
93
   .Data             db  ?  ;+24
261 hidnplayr 94
}
95
 
96
virtual at 0
97
  TCP_PACKET TCP_PACKET
98
end virtual
99
 
100
 
101
 
1 ha 102
;***************************************************************************
103
;   Function
104
;      tcp_tcb_handler
105
;
106
;   Description
107
;       Handles sockets in the timewait state, closing them
108
;       when the TCB timer expires
109
;
110
;***************************************************************************
111
 
907 mikedld 112
proc tcp_tcb_handler stdcall uses ebx
2434 Serge 113
        ; scan through all the sockets, decrementing active timers
1 ha 114
 
2434 Serge 115
        mov     ebx, net_sockets
1 ha 116
 
2434 Serge 117
        cmp     [ebx + SOCKET.NextPtr], 0
118
        je      .exit
119
        ;DEBUGF 1, "K : sockets:\n"
1 ha 120
 
907 mikedld 121
  .next_socket:
2434 Serge 122
        mov     ebx, [ebx + SOCKET.NextPtr]
123
        or      ebx, ebx
124
        jz      .exit
1 ha 125
 
2434 Serge 126
        ;DEBUGF 1, "K :   %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState]
1 ha 127
 
2434 Serge 128
        cmp     [ebx + SOCKET.TCBTimer], 0
129
        jne     .decrement_tcb
130
        cmp     [ebx + SOCKET.wndsizeTimer], 0
131
        jne     .decrement_wnd
132
        jmp     .next_socket
1 ha 133
 
907 mikedld 134
  .decrement_tcb:
2434 Serge 135
        ; decrement it, delete socket if TCB timer = 0 & socket in timewait state
136
        dec     [ebx + SOCKET.TCBTimer]
137
        jnz     .next_socket
1 ha 138
 
2434 Serge 139
        cmp     [ebx + SOCKET.TCBState], TCB_TIMED_WAIT
140
        jne     .next_socket
1 ha 141
 
2434 Serge 142
        push    [ebx + SOCKET.PrevPtr]
143
        stdcall net_socket_free, ebx
144
        pop     ebx
145
        jmp     .next_socket
1 ha 146
 
907 mikedld 147
  .decrement_wnd:
2434 Serge 148
        ; TODO - prove it works!
149
        dec     [ebx + SOCKET.wndsizeTimer]
150
        jmp     .next_socket
1 ha 151
 
907 mikedld 152
  .exit:
2434 Serge 153
        ret
907 mikedld 154
endp
1 ha 155
 
156
 
157
;***************************************************************************
158
;   Function
159
;      tcp_tx_handler
160
;
161
;   Description
162
;       Handles queued TCP data
163
;       This is a kernel function, called by stack_handler
164
;
165
;***************************************************************************
907 mikedld 166
 
167
proc tcp_tx_handler stdcall
1 ha 168
    ; decrement all resend buffers timers. If they
169
    ; expire, queue them for sending, and restart the timer.
170
    ; If the retries counter reach 0, delete the entry
171
 
2434 Serge 172
        mov     esi, resendQ
173
        mov     ecx, 0
1 ha 174
 
907 mikedld 175
  .next_resendq:
2434 Serge 176
        cmp     ecx, NUMRESENDENTRIES
177
        je      .exit               ; None left
178
        cmp     dword[esi + 4], 0
179
        jne     @f                   ; found one
180
        inc     ecx
181
        add     esi, 8
182
        jmp     .next_resendq
1 ha 183
 
907 mikedld 184
    @@: ; we have one. decrement it's timer by 1
2434 Serge 185
        dec     word[esi + 2]
186
        jz      @f
187
        inc     ecx
188
        add     esi, 8
189
        jmp     .next_resendq       ; Timer not zero, so move on
1 ha 190
 
907 mikedld 191
    @@:
2434 Serge 192
        xor     ebx, ebx
193
        ; restart timer, and decrement retries
194
        ; After the first resend, back of on next, by a factor of 5
195
        mov     [esi + 2], word TCP_TIMEOUT * 5
196
        dec     byte[esi + 1]
197
        jnz     @f
1 ha 198
 
2434 Serge 199
        ; retries now 0, so delete from queue
200
        xchg    [esi + 4], ebx
1 ha 201
 
907 mikedld 202
    @@: ; resend packet
2434 Serge 203
        pushad
1 ha 204
 
2434 Serge 205
        mov     eax, EMPTY_QUEUE
206
        call    dequeue
207
        cmp     ax, NO_BUFFER
208
        jne     .tth004z
1 ha 209
 
2434 Serge 210
        ; TODO - try again in 10ms.
211
        test    ebx, ebx
212
        jnz     @f
213
        mov     [esi + 4], ebx
1 ha 214
 
907 mikedld 215
    @@: ; Mark it to expire in 10ms - 1 tick
2434 Serge 216
        mov     byte[esi + 1], 1
217
        mov     word[esi + 2], 1
218
        jmp     .tth005
1 ha 219
 
907 mikedld 220
  .tth004z:
2434 Serge 221
        ; we have a buffer # in ax
222
        push    eax ecx
223
        mov     ecx, IPBUFFSIZE
224
        mul     ecx
225
        add     eax, IPbuffs
1 ha 226
 
2434 Serge 227
        ; we have the buffer address in eax
228
        mov     edi, eax
229
        pop     ecx
230
        ; Now get buffer location, and copy buffer across. argh! more copying,,
231
        imul    esi, ecx, IPBUFFSIZE
232
        add     esi, resendBuffer
1 ha 233
 
2434 Serge 234
        ; we have resend buffer location in esi
235
        mov     ecx, IPBUFFSIZE
1 ha 236
 
2434 Serge 237
        ; copy data across
238
        push    edi
239
        cld
240
        rep movsb
241
        pop     edi
1 ha 242
 
2434 Serge 243
        ; queue packet
244
        mov     eax, NET1OUT_QUEUE
245
        mov     edx, [stack_ip]
246
        cmp     edx, [edi + IP_PACKET.DestinationAddress]
247
        jne     .not_local
248
        mov     eax, IPIN_QUEUE
1 ha 249
 
907 mikedld 250
  .not_local:
2434 Serge 251
        pop     ebx
252
        call    queue
1 ha 253
 
907 mikedld 254
  .tth005:
2434 Serge 255
        popad
1 ha 256
 
2434 Serge 257
        inc     ecx
258
        add     esi, 8
259
        jmp     .next_resendq
1 ha 260
 
907 mikedld 261
  .exit:
2434 Serge 262
        ret
907 mikedld 263
endp
1 ha 264
 
265
 
266
;***************************************************************************
267
;   Function
268
;      tcp_rx
269
;
270
;   Description
271
;       TCP protocol handler
272
;       This is a kernel function, called by ip_rx
273
;       IP buffer address given in edx
274
;          IP buffer number in eax
275
;          Free up (or re-use) IP buffer when finished
276
;
277
;***************************************************************************
278
 
907 mikedld 279
proc tcp_rx stdcall uses ebx
2434 Serge 280
        ; The process is as follows.
281
        ; Look for a socket with matching remote IP, remote port, local port
282
        ; if not found, then
283
        ; look for remote IP + local port match ( where sockets remote port = 0)
284
        ; if not found, then
285
        ; look for a socket where local socket port == IP packets remote port
286
        ; where sockets remote port, remote IP = 0
287
        ; discard if not found
288
        ; Call sockets tcbStateMachine, with pointer to packet.
289
        ; the state machine will not delete the packet, so do that here.
1 ha 290
 
2434 Serge 291
        push    eax
1 ha 292
 
2434 Serge 293
        ; Look for a socket where
294
        ; IP Packet TCP Destination Port = local Port
295
        ; IP Packet SA = Remote IP
296
        ; IP Packet TCP Source Port = remote Port
1 ha 297
 
2434 Serge 298
        mov     ebx, net_sockets
1 ha 299
 
907 mikedld 300
  .next_socket.1:
2434 Serge 301
        mov     ebx, [ebx + SOCKET.NextPtr]
302
        or      ebx, ebx
303
        jz      .next_socket.1.exit
1 ha 304
 
907 mikedld 305
;        DEBUGF  1, "K : tcp_rx - 1.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4
1 ha 306
 
2434 Serge 307
        mov     ax, [edx + 20 + TCP_PACKET.DestinationPort]  ; get the dest. port from the TCP hdr
308
        cmp     [ebx + SOCKET.LocalPort], ax            ; get the dest. port from the TCP hdr
309
        jne     .next_socket.1                          ; different - try next socket
1 ha 310
 
907 mikedld 311
;        DEBUGF  1, "K : tcp_rx - 1.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP]
1 ha 312
 
2434 Serge 313
        mov     eax, [edx + IP_PACKET.SourceAddress]    ; get the source IP Addr from the IP hdr
314
        cmp     [ebx + SOCKET.RemoteIP], eax            ; compare with socket's remote IP
315
        jne     .next_socket.1                          ; different - try next socket
1 ha 316
 
907 mikedld 317
;        DEBUGF  1, "K : tcp_rx - 1.sport: %x - %x\n", [edx + 20 + TCP_PACKET.SourcePort]:4, [ebx + SOCKET.RemotePort]:4
1 ha 318
 
2434 Serge 319
        mov     ax, [edx + 20 + TCP_PACKET.SourcePort]  ; get the source port from the TCP hdr
320
        cmp     [ebx + SOCKET.RemotePort], ax           ; compare with socket's remote port
321
        jne     .next_socket.1                          ; different - try next socket
1 ha 322
 
2434 Serge 323
        ; We have a complete match - use this socket
324
        jmp     .change_state
1 ha 325
 
907 mikedld 326
  .next_socket.1.exit:
1 ha 327
 
2434 Serge 328
        ; If we got here, there was no match
329
        ; Look for a socket where
330
        ; IP Packet TCP Destination Port = local Port
331
        ; IP Packet SA = Remote IP
332
        ; socket remote Port = 0
1 ha 333
 
2434 Serge 334
        mov     ebx, net_sockets
1 ha 335
 
907 mikedld 336
  .next_socket.2:
2434 Serge 337
        mov     ebx, [ebx + SOCKET.NextPtr]
338
        or      ebx, ebx
339
        jz      .next_socket.2.exit
1 ha 340
 
907 mikedld 341
;        DEBUGF  1, "K : tcp_rx - 2.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4
1 ha 342
 
2434 Serge 343
        mov     ax, [edx + 20 + TCP_PACKET.DestinationPort]  ; get the dest. port from the TCP hdr
344
        cmp     [ebx + SOCKET.LocalPort], ax            ; compare with socket's local port
345
        jne     .next_socket.2                          ; different - try next socket
1 ha 346
 
907 mikedld 347
;        DEBUGF  1, "K : tcp_rx - 2.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP]
1 ha 348
 
2434 Serge 349
        mov     eax, [edx + IP_PACKET.SourceAddress]    ; get the source IP Addr from the IP hdr
350
        cmp     [ebx + SOCKET.RemoteIP], eax            ; compare with socket's remote IP
351
        jne     .next_socket.2                          ; different - try next socket
1 ha 352
 
907 mikedld 353
;        DEBUGF  1, "K : tcp_rx - 2.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4
1 ha 354
 
2434 Serge 355
        cmp     [ebx + SOCKET.RemotePort], 0            ; only match a remote socket of 0
356
        jne     .next_socket.2                          ; different - try next socket
1 ha 357
 
2434 Serge 358
        ; We have a complete match - use this socket
359
        jmp     .change_state
1 ha 360
 
907 mikedld 361
  .next_socket.2.exit:
1 ha 362
 
2434 Serge 363
        ; If we got here, there was no match
364
        ; Look for a socket where
365
        ; IP Packet TCP Destination Port = local Port
366
        ; socket Remote IP = 0
367
        ; socket remote Port = 0
1 ha 368
 
2434 Serge 369
        mov     ebx, net_sockets
1 ha 370
 
907 mikedld 371
  .next_socket.3:
2434 Serge 372
        mov     ebx, [ebx + SOCKET.NextPtr]
373
        or      ebx, ebx
374
        jz      .next_socket.3.exit
1 ha 375
 
907 mikedld 376
;        DEBUGF  1, "K : tcp_rx - 3.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4
377
 
2434 Serge 378
        mov     ax, [edx + 20 + TCP_PACKET.DestinationPort]  ; get destination port from the TCP hdr
379
        cmp     [ebx + SOCKET.LocalPort], ax            ; compare with socket's local port
380
        jne     .next_socket.3                          ; different - try next socket
907 mikedld 381
 
382
;        DEBUGF  1, "K : tcp_rx - 3.addr: 00000000 - %x\n", [ebx + SOCKET.RemoteIP]
383
 
2434 Serge 384
        cmp     [ebx + SOCKET.RemoteIP], 0              ; only match a socket remote IP of 0
385
        jne     .next_socket.3                          ; different - try next socket
907 mikedld 386
 
387
;        DEBUGF  1, "K : tcp_rx - 3.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4
388
 
2434 Serge 389
        cmp     [ebx + SOCKET.RemotePort], 0            ; only match a remote socket of 0
390
        jne     .next_socket.3                          ; different - try next socket
907 mikedld 391
 
2434 Serge 392
        ; We have a complete match - use this socket
393
        jmp     .change_state
907 mikedld 394
 
395
  .next_socket.3.exit:
396
 
2434 Serge 397
        ; If we got here, we need to reject the packet
907 mikedld 398
 
2434 Serge 399
        DEBUGF  1, "K : tcp_rx - dumped\n"
400
        DEBUGF  1, "K :   --------: %x-%x-%x (flags: %x)\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [edx + IP_PACKET.SourceAddress], [edx + 20 + TCP_PACKET.SourcePort]:4, [edx + 20 + TCP_PACKET.Flags]:2
922 mikedld 401
 
2434 Serge 402
        inc     [dumped_rx_count]
403
        jmp     .exit
907 mikedld 404
 
405
  .change_state:
406
 
2434 Serge 407
        ; We have a valid socket/TCB, so call the TCB State Machine for that skt.
408
        ; socket is pointed to by ebx
409
        ; IP packet is pointed to by edx
410
        ; IP buffer number is on stack ( it will be popped at the end)
907 mikedld 411
 
2434 Serge 412
        stdcall tcpStateMachine, ebx
907 mikedld 413
 
414
  .exit:
2434 Serge 415
        pop     eax
416
        call    freeBuff
417
        ret
907 mikedld 418
endp
419
 
420
 
1 ha 421
;***************************************************************************
422
;   Function
423
;      buildTCPPacket
424
;
425
;   Description
426
;       builds an IP Packet with TCP data fully populated for transmission
427
;       You may destroy any and all registers
428
;          TCP control flags specified in bl
429
;          This TCB is in [sktAddr]
430
;          User data pointed to by esi
431
;       Data length in ecx
432
;          Transmit buffer number in eax
433
;
434
;***************************************************************************
435
 
907 mikedld 436
proc build_tcp_packet stdcall, sockAddr:DWORD
2434 Serge 437
        push    ecx                        ; Save data length
1 ha 438
 
2434 Serge 439
        ; convert buffer pointer eax to the absolute address
440
        mov     ecx, IPBUFFSIZE
441
        mul     ecx
442
        add     eax, IPbuffs
1 ha 443
 
2434 Serge 444
        mov     edx, eax
1 ha 445
 
2434 Serge 446
        mov     [edx + 20 + TCP_PACKET.Flags], bl               ; TCP flags
1 ha 447
 
2434 Serge 448
        mov     ebx, [sockAddr]
1 ha 449
 
2434 Serge 450
        ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
1 ha 451
 
2434 Serge 452
        ; Fill in the IP header ( some data is in the socket descriptor)
453
        mov     eax, [ebx + SOCKET.LocalIP]
454
        mov     [edx + IP_PACKET.SourceAddress], eax
455
        mov     eax, [ebx + SOCKET.RemoteIP]
456
        mov     [edx + IP_PACKET.DestinationAddress], eax
1 ha 457
 
2434 Serge 458
        mov     [edx + IP_PACKET.VersionAndIHL], 0x45
459
        mov     [edx + IP_PACKET.TypeOfService], 0
1 ha 460
 
2434 Serge 461
        pop     eax                   ; Get the TCP data length
462
        push    eax
1 ha 463
 
2434 Serge 464
        add     eax, 20 + 20           ; add IP header and TCP header lengths
465
        rol     ax, 8
466
        mov     [edx + IP_PACKET.TotalLength], ax
467
        mov     [edx + IP_PACKET.Identification], 0
468
        mov     [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040
469
        mov     [edx + IP_PACKET.TimeToLive], 0x20
470
        mov     [edx + IP_PACKET.Protocol], PROTOCOL_TCP
1 ha 471
 
2434 Serge 472
        ; Checksum left unfilled
473
        mov     [edx + IP_PACKET.HeaderChecksum], 0
1 ha 474
 
2434 Serge 475
        ; Fill in the TCP header (some data is in the socket descriptor)
476
        mov     ax, [ebx + SOCKET.LocalPort]
477
        mov     [edx + 20 + TCP_PACKET.SourcePort], ax          ; Local Port
1 ha 478
 
2434 Serge 479
        mov     ax, [ebx + SOCKET.RemotePort]
480
        mov     [edx + 20 + TCP_PACKET.DestinationPort], ax     ; desitination Port
1 ha 481
 
2434 Serge 482
        ; Checksum left unfilled
483
        mov     [edx + 20 + TCP_PACKET.Checksum], 0
1 ha 484
 
2434 Serge 485
        ; sequence number
486
        mov     eax, [ebx + SOCKET.SND_NXT]
487
        mov     [edx + 20 + TCP_PACKET.SequenceNumber], eax
1 ha 488
 
2434 Serge 489
        ; ack number
490
        mov     eax, [ebx + SOCKET.RCV_NXT]
491
        mov     [edx + 20 + TCP_PACKET.AckNumber], eax
1 ha 492
 
2434 Serge 493
        ; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size)
494
        ; 768 bytes seems better
495
        mov     [edx + 20 + TCP_PACKET.Window], 0x0003
1 ha 496
 
2434 Serge 497
        ; Urgent pointer (0)
498
        mov     [edx + 20 + TCP_PACKET.UrgentPointer], 0
1 ha 499
 
2434 Serge 500
        ; data offset ( 0x50 )
501
        mov     [edx + 20 + TCP_PACKET.DataOffset], 0x50
1 ha 502
 
2434 Serge 503
        pop     ecx                  ; count of bytes to send
504
        mov     ebx, ecx            ; need the length later
1 ha 505
 
2434 Serge 506
        cmp     ebx, 0
507
        jz      @f
1 ha 508
 
2434 Serge 509
        mov     edi, edx
510
        add     edi, 40
511
        cld
512
        rep movsb                   ; copy the data across
1 ha 513
 
907 mikedld 514
    @@: ; we have edx as IPbuffer ptr.
2434 Serge 515
        ; Fill in the TCP checksum
516
        ; First, fill in pseudoheader
517
        mov     eax, [edx + IP_PACKET.SourceAddress]
518
        mov     [pseudoHeader], eax
519
        mov     eax, [edx + IP_PACKET.DestinationAddress]
520
        mov     [pseudoHeader + 4], eax
521
        mov     word[pseudoHeader + 8], PROTOCOL_TCP shl 8 + 0
522
        add     ebx, 20
523
        mov     [pseudoHeader + 10], bh
524
        mov     [pseudoHeader + 11], bl
1 ha 525
 
2434 Serge 526
        mov     eax, pseudoHeader
527
        mov     [checkAdd1], eax
528
        mov     word[checkSize1], 12
529
        mov     eax, edx
530
        add     eax, 20
531
        mov     [checkAdd2], eax
532
        mov     eax, ebx
533
        mov     [checkSize2], ax
1 ha 534
 
2434 Serge 535
        call    checksum
1 ha 536
 
2434 Serge 537
        ; store it in the TCP checksum ( in the correct order! )
538
        mov     ax, [checkResult]
539
        rol     ax, 8
540
        mov     [edx + 20 + TCP_PACKET.Checksum], ax
1 ha 541
 
2434 Serge 542
        ; Fill in the IP header checksum
543
        GET_IHL eax, edx               ; get IP-Header length
544
        stdcall checksum_jb, edx, eax  ; buf_ptr, buf_size
545
        rol     ax, 8
546
        mov     [edx + IP_PACKET.HeaderChecksum], ax
1 ha 547
 
2434 Serge 548
        ret
907 mikedld 549
endp
1 ha 550
 
551
 
552
; Increments the 32 bit value pointed to by esi in internet order
907 mikedld 553
proc inc_inet_esi stdcall
2434 Serge 554
        push    eax
555
        mov     eax, [esi]
556
        bswap   eax
557
        inc     eax
558
        bswap   eax
559
        mov     [esi], eax
560
        pop     eax
561
        ret
907 mikedld 562
endp
1 ha 563
 
564
 
565
; Increments the 32 bit value pointed to by esi in internet order
566
; by the value in ecx
907 mikedld 567
proc add_inet_esi stdcall
2434 Serge 568
        push    eax
569
        mov     eax, [esi]
570
        bswap   eax
571
        add     eax, ecx
572
        bswap   eax
573
        mov     [esi], eax
574
        pop     eax
575
        ret
907 mikedld 576
endp
1 ha 577
 
578
 
579
iglobal
907 mikedld 580
  TCBStateHandler dd \
581
    stateTCB_LISTEN, \
582
    stateTCB_SYN_SENT, \
583
    stateTCB_SYN_RECEIVED, \
584
    stateTCB_ESTABLISHED, \
585
    stateTCB_FIN_WAIT_1, \
586
    stateTCB_FIN_WAIT_2, \
587
    stateTCB_CLOSE_WAIT, \
588
    stateTCB_CLOSING, \
589
    stateTCB_LAST_ACK, \
590
    stateTCB_TIME_WAIT, \
591
    stateTCB_CLOSED
1 ha 592
endg
593
 
907 mikedld 594
 
1 ha 595
;***************************************************************************
596
;   Function
597
;      tcpStateMachine
598
;
599
;   Description
600
;       TCP state machine
601
;       This is a kernel function, called by tcp_rx
602
;
603
;       IP buffer address given in edx
907 mikedld 604
;          Socket/TCB address in ebx
1 ha 605
;
606
;       The IP buffer will be released by the caller
607
;***************************************************************************
608
 
907 mikedld 609
proc tcpStateMachine stdcall, sockAddr:DWORD
2434 Serge 610
        ; as a packet has been received, update the TCB timer
611
        mov     [ebx + SOCKET.TCBTimer], TWOMSL
1 ha 612
 
2434 Serge 613
        ; If the received packet has an ACK bit set,
614
        ; remove any packets in the resend queue that this
615
        ; received packet acknowledges
616
        pushad
617
        test    [edx + 20 + TCP_PACKET.Flags], TH_ACK
618
        jz      .call_handler                                   ; No ACK, so no data yet
1 ha 619
 
2434 Serge 620
        ; get skt number in eax
621
        stdcall net_socket_addr_to_num, ebx
1 ha 622
 
2434 Serge 623
        ; The ack number is in [edx + 28], inet format
624
        ; skt in eax
1 ha 625
 
2434 Serge 626
        mov     esi, resendQ
627
        xor     ecx, ecx
1 ha 628
 
907 mikedld 629
  .next_resendq:
2434 Serge 630
        cmp     ecx, NUMRESENDENTRIES
631
        je      .call_handler     ; None left
632
        cmp     [esi + 4], eax
633
        je      @f                ; found one
634
        inc     ecx
635
        add     esi, 8
636
        jmp     .next_resendq
1 ha 637
 
2434 Serge 638
    @@:                   ; Can we delete this buffer?
1 ha 639
 
2434 Serge 640
                          ; If yes, goto @@. No, goto .next_resendq
641
        ; Get packet data address
1 ha 642
 
2434 Serge 643
        push    ecx
644
        ; Now get buffer location, and copy buffer across. argh! more copying,,
645
        imul    edi, ecx, IPBUFFSIZE
646
        add     edi, resendBuffer
1 ha 647
 
2434 Serge 648
        ; we have dest buffer location in edi. incoming packet in edx.
649
        ; Get this packets sequence number
650
        ; preserve al, ecx, esi, edx
651
        mov     ecx, [edi + 20 + TCP_PACKET.SequenceNumber]
652
        bswap   ecx
653
        movzx   ebx, word[edi + 2]
654
        xchg    bl, bh
655
        sub     ebx, 40
656
        add     ecx, ebx          ; ecx is now seq# of last byte +1, intel format
1 ha 657
 
2434 Serge 658
        ; get recievd ack #, in intel format
659
        mov     ebx, [edx + 20 + TCP_PACKET.AckNumber]
660
        bswap   ebx
1 ha 661
 
2434 Serge 662
        cmp     ebx, ecx        ; Finally. ecx = rx'ed ack. ebx = last byte in que
663
                                ; DANGER! need to handle case that we have just
664
                                ; passed the 2**32, and wrapped round!
665
        pop     ecx
666
        jae     @f              ; if rx > old, delete old
1 ha 667
 
2434 Serge 668
        inc     ecx
669
        add     esi, 8
670
        jmp     .next_resendq
1 ha 671
 
2434 Serge 672
    @@:
673
        mov     dword[esi + 4], 0
674
        inc     ecx
675
        add     esi, 8
676
        jmp     .next_resendq
1 ha 677
 
907 mikedld 678
  .call_handler:
2434 Serge 679
        popad
1 ha 680
 
2434 Serge 681
        ; Call handler for given TCB state
1 ha 682
 
2434 Serge 683
        mov     eax, [ebx + SOCKET.TCBState]
684
        cmp     eax, TCB_LISTEN
685
        jb      .exit
686
        cmp     eax, TCB_CLOSED
687
        ja      .exit
1 ha 688
 
2434 Serge 689
        stdcall [TCBStateHandler + (eax - 1) * 4], [sockAddr]
1 ha 690
 
907 mikedld 691
  .exit:
2434 Serge 692
        ret
907 mikedld 693
endp
1 ha 694
 
1181 clevermous 695
;***************************************************************************
696
;   Function
697
;      signal_network_event
698
;
699
;   Description
700
;       Signals about network event to socket owner
2434 Serge 701
;       This is a kernel function, called from TCP handler
1181 clevermous 702
;
703
;          Socket/TCB address in ebx
704
;***************************************************************************
705
proc signal_network_event
2434 Serge 706
        push    ecx esi eax
707
        mov     eax, [ebx + SOCKET.PID]
708
        mov     ecx, 1
709
        mov     esi, TASK_DATA + TASKDATA.pid
1 ha 710
 
1181 clevermous 711
  .next_pid:
2434 Serge 712
        cmp     [esi], eax
713
        je      .found_pid
714
        inc     ecx
715
        add     esi, 0x20
716
        cmp     ecx, [TASK_COUNT]
717
        jbe     .next_pid
1181 clevermous 718
 
719
  .found_pid:
2434 Serge 720
        shl     ecx, 8
721
        or      [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event
722
        pop     eax esi ecx
723
        ret
1181 clevermous 724
endp
725
 
907 mikedld 726
proc stateTCB_LISTEN stdcall, sockAddr:DWORD
2434 Serge 727
        ; In this case, we are expecting a SYN packet
728
        ; For now, if the packet is a SYN, process it, and send a response
729
        ; If not, ignore it
1 ha 730
 
2434 Serge 731
        ; Look at control flags
732
        test    [edx + 20 + TCP_PACKET.Flags], TH_SYN
733
        jz      .exit
1 ha 734
 
2434 Serge 735
        ; We have a SYN. update the socket with this IP packets details,
736
        ; And send a response
1 ha 737
 
2434 Serge 738
        mov     eax, [edx + IP_PACKET.SourceAddress]
739
        mov     [ebx + SOCKET.RemoteIP], eax
740
        mov     ax, [edx + 20 + TCP_PACKET.SourcePort]
741
        mov     [ebx + SOCKET.RemotePort], ax
742
        mov     eax, [edx + 20 + TCP_PACKET.SequenceNumber]
743
        mov     [ebx + SOCKET.IRS], eax
744
        mov     [ebx + SOCKET.RCV_NXT], eax
745
        lea     esi, [ebx + SOCKET.RCV_NXT]
746
        call    inc_inet_esi ; RCV.NXT
747
        mov     eax, [ebx + SOCKET.ISS]
748
        mov     [ebx + SOCKET.SND_NXT], eax
1 ha 749
 
2434 Serge 750
        ; Now construct the response, and queue for sending by IP
751
        mov     eax, EMPTY_QUEUE
752
        call    dequeue
753
        cmp     ax, NO_BUFFER
754
        je      .exit
1 ha 755
 
2434 Serge 756
        push    ebx
757
        push    eax
758
        mov     bl, TH_SYN + TH_ACK
759
        xor     ecx, ecx
760
        xor     esi, esi
761
        stdcall build_tcp_packet, [sockAddr]
1 ha 762
 
2434 Serge 763
        mov     eax, NET1OUT_QUEUE
764
        mov     edx, [stack_ip]
765
        mov     ecx, [sockAddr]
766
        cmp     edx, [ecx + SOCKET.RemoteIP]
767
        jne     .not_local
768
        mov     eax, IPIN_QUEUE
1 ha 769
 
907 mikedld 770
  .not_local:
2434 Serge 771
        ; Send it.
772
        pop     ebx
773
        call    queue
1 ha 774
 
2434 Serge 775
        pop     ebx
776
        mov     esi, [sockAddr]
777
        mov     [esi + SOCKET.TCBState], TCB_SYN_RECEIVED
778
        call    signal_network_event
1 ha 779
 
2434 Serge 780
        ; increment SND.NXT in socket
781
        add     esi, SOCKET.SND_NXT
782
        call    inc_inet_esi
1 ha 783
 
907 mikedld 784
  .exit:
2434 Serge 785
        ret
907 mikedld 786
endp
1 ha 787
 
788
 
907 mikedld 789
proc stateTCB_SYN_SENT stdcall, sockAddr:DWORD
2434 Serge 790
        ; We are awaiting an ACK to our SYN, with a SYM
791
        ; Look at control flags - expecting an ACK
1 ha 792
 
2434 Serge 793
        mov     al, [edx + 20 + TCP_PACKET.Flags]
794
        and     al, TH_SYN + TH_ACK
795
        cmp     al, TH_SYN + TH_ACK
796
        je      .syn_ack
1 ha 797
 
2434 Serge 798
        test    al, TH_SYN
799
        jz      .exit
1 ha 800
 
2434 Serge 801
        mov     [ebx + SOCKET.TCBState], TCB_SYN_RECEIVED
802
        push    TH_SYN + TH_ACK
803
        jmp     .send
1 ha 804
 
907 mikedld 805
  .syn_ack:
2434 Serge 806
        mov     [ebx + SOCKET.TCBState], TCB_ESTABLISHED
807
        push    TH_ACK
1 ha 808
 
907 mikedld 809
  .send:
2434 Serge 810
        call    signal_network_event
811
        ; Store the recv.nxt field
812
        mov     eax, [edx + 20 + TCP_PACKET.SequenceNumber]
1 ha 813
 
2434 Serge 814
        ; Update our recv.nxt field
815
        mov     [ebx + SOCKET.RCV_NXT], eax
816
        lea     esi, [ebx + SOCKET.RCV_NXT]
817
        call    inc_inet_esi
1 ha 818
 
2434 Serge 819
        ; Send an ACK
820
        ; Now construct the response, and queue for sending by IP
821
        mov     eax, EMPTY_QUEUE
822
        call    dequeue
823
        cmp     ax, NO_BUFFER
824
        pop     ebx
825
        je      .exit
1 ha 826
 
2434 Serge 827
        push    eax
1 ha 828
 
2434 Serge 829
        xor     ecx, ecx
830
        xor     esi, esi
831
        stdcall build_tcp_packet, [sockAddr]
1 ha 832
 
2434 Serge 833
        mov     eax, NET1OUT_QUEUE
834
        mov     edx, [stack_ip]
835
        mov     ecx, [sockAddr]
836
        cmp     edx, [ecx + SOCKET.RemoteIP]
837
        jne     .not_local
838
        mov     eax, IPIN_QUEUE
1 ha 839
 
907 mikedld 840
  .not_local:
2434 Serge 841
        ; Send it.
842
        pop     ebx
843
        call    queue
1 ha 844
 
907 mikedld 845
  .exit:
2434 Serge 846
        ret
907 mikedld 847
endp
1 ha 848
 
849
 
907 mikedld 850
proc stateTCB_SYN_RECEIVED stdcall, sockAddr:DWORD
2434 Serge 851
        ; In this case, we are expecting an ACK packet
852
        ; For now, if the packet is an ACK, process it,
853
        ; If not, ignore it
1 ha 854
 
2434 Serge 855
        test    [edx + 20 + TCP_PACKET.Flags], TH_RST
856
        jz      .check_ack
1 ha 857
 
2434 Serge 858
        push    [ebx + SOCKET.OrigRemotePort] [ebx + SOCKET.OrigRemoteIP]
859
        pop     [ebx + SOCKET.RemoteIP] [ebx + SOCKET.RemotePort]
1 ha 860
 
2434 Serge 861
        mov     [ebx + SOCKET.TCBState], TCB_LISTEN
862
        jmp     .signal
1 ha 863
 
922 mikedld 864
  .check_ack:
2434 Serge 865
        ; Look at control flags - expecting an ACK
866
        test    [edx + 20 + TCP_PACKET.Flags], TH_ACK
867
        jz      .exit
1 ha 868
 
2434 Serge 869
        mov     [ebx + SOCKET.TCBState], TCB_ESTABLISHED
1181 clevermous 870
  .signal:
2434 Serge 871
        call    signal_network_event
1 ha 872
 
907 mikedld 873
  .exit:
2434 Serge 874
        ret
907 mikedld 875
endp
1 ha 876
 
877
 
907 mikedld 878
proc stateTCB_ESTABLISHED stdcall, sockAddr:DWORD
2434 Serge 879
        ; Here we are expecting data, or a request to close
880
        ; OR both...
1 ha 881
 
2434 Serge 882
        ; Ignore all packets with sequnce number other than next expected
1181 clevermous 883
 
2434 Serge 884
        ; recv.nxt is in dword [edx+24], in inet format
885
        ; recv seq is in [sktAddr]+56, in inet format
886
        ; just do a comparision
887
        mov     eax, [ebx + SOCKET.RCV_NXT]
888
        cmp     eax, [edx + 20 + TCP_PACKET.SequenceNumber]
889
        jne     .exit
1181 clevermous 890
 
2434 Serge 891
        ; Did we receive a FIN or RST?
892
        test    [edx + 20 + TCP_PACKET.Flags], TH_FIN+TH_RST
893
        jz      .check_ack
1 ha 894
 
2434 Serge 895
        ; It was a fin or reset.
1 ha 896
 
2434 Serge 897
        ; Remove resend entries from the queue  - I dont want to send any more data
898
        pushad
1 ha 899
 
2434 Serge 900
        ; get skt #
901
        stdcall net_socket_addr_to_num, ebx
1 ha 902
 
2434 Serge 903
        mov     esi, resendQ
904
        mov     ecx, 0
1 ha 905
 
907 mikedld 906
  .next_resendq:
2434 Serge 907
        cmp     ecx, NUMRESENDENTRIES
908
        je      .last_resendq       ; None left
909
        cmp     [esi + 4], eax
910
        je      @f                  ; found one
911
        inc     ecx
912
        add     esi, 8
913
        jmp     .next_resendq
1 ha 914
 
2434 Serge 915
    @@:
916
        mov     dword[esi + 4], 0
917
        inc     ecx
918
        add     esi, 8
919
        jmp     .next_resendq
1 ha 920
 
907 mikedld 921
  .last_resendq:
2434 Serge 922
        popad
1 ha 923
 
907 mikedld 924
    @@: ; Send an ACK to that fin, and enter closewait state
1 ha 925
 
2434 Serge 926
        mov     [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT
927
        test    [edx + 20 + TCP_PACKET.Flags], TH_RST
928
        je      @f
929
        mov     [ebx + SOCKET.TCBState], TCB_CLOSED
930
    @@:
931
        call    signal_network_event
932
        lea     esi, [ebx + SOCKET.RCV_NXT]
933
        mov     eax, [esi]              ; save original
934
        call    inc_inet_esi
935
        ;; jmp    ste_ack - NO, there may be data
1 ha 936
 
907 mikedld 937
  .check_ack:
2434 Serge 938
        ; Check that we received an ACK
939
        test    [edx + 20 + TCP_PACKET.Flags], TH_ACK
940
        jz      .exit
1 ha 941
 
2434 Serge 942
        ; TODO - done, I think!
943
        ; First, look at the incoming window. If this is less than or equal to 1024,
944
        ; Set the socket window timer to 1. This will stop an additional packets being queued.
945
        ; ** I may need to tweak this value, since I do not know how many packets are already queued
946
        mov     cx, [edx + 20 + TCP_PACKET.Window]
947
        xchg    cl, ch
948
        cmp     cx, 1024
949
        ja      @f
1 ha 950
 
2434 Serge 951
        mov     [ebx + SOCKET.wndsizeTimer], 1
1 ha 952
 
907 mikedld 953
    @@: ; OK, here is the deal
1 ha 954
 
955
 
2434 Serge 956
        ; Read the data bytes, store in socket buffer
957
        movzx   ecx, [edx + IP_PACKET.TotalLength]
958
        xchg    cl, ch
959
        sub     ecx, 40                    ; Discard 40 bytes of header
960
        ja      .data                      ; Read data, if any
1 ha 961
 
2434 Serge 962
        ; If we had received a fin, we need to ACK it.
963
        cmp     [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT
964
        je      .ack
965
        jmp     .exit
1 ha 966
 
907 mikedld 967
  .data:
2434 Serge 968
        push    ecx
969
        push    ecx edx
970
        lea     ecx, [ebx+SOCKET.mutex]
971
        call    mutex_lock
2209 Serge 972
        pop     edx ecx
1019 diamond 973
 
2434 Serge 974
        push    ebx
975
        mov     eax, [ebx + SOCKET.rxDataCount]
976
        add     eax, ecx
977
        cmp     eax, SOCKETBUFFSIZE - SOCKETHEADERSIZE
978
        ja      .overflow
1 ha 979
 
2434 Serge 980
        mov     [ebx + SOCKET.rxDataCount], eax      ; increment the count of bytes in buffer
1 ha 981
 
2434 Serge 982
        ; point to the location to store the data
983
        lea     edi, [ebx + eax + SOCKETHEADERSIZE]
984
        sub     edi, ecx
1 ha 985
 
2434 Serge 986
        add     edx, 40        ; edx now points to the data
987
        mov     esi, edx
1 ha 988
 
2434 Serge 989
        cld
990
        rep movsb              ; copy the data across
1 ha 991
 
2434 Serge 992
        lea     ecx, [ebx + SOCKET.mutex]
993
        call    mutex_unlock
2130 serge 994
 
2434 Serge 995
        ; flag an event to the application
996
        pop     ebx
997
        call    signal_network_event
1 ha 998
 
2434 Serge 999
        pop     ecx
1 ha 1000
 
2434 Serge 1001
        ; Update our recv.nxt field
1002
        lea     esi, [ebx + SOCKET.RCV_NXT]
1003
        call    add_inet_esi
1 ha 1004
 
907 mikedld 1005
  .ack:
2434 Serge 1006
        ; Send an ACK
1007
        ; Now construct the response, and queue for sending by IP
1008
        mov     eax, EMPTY_QUEUE
1009
        call    dequeue
1010
        cmp     ax, NO_BUFFER
1011
        je      .exit
1 ha 1012
 
2434 Serge 1013
        push    eax
1 ha 1014
 
2434 Serge 1015
        mov     bl, TH_ACK
1016
        xor     ecx, ecx
1017
        xor     esi, esi
1018
        stdcall build_tcp_packet, [sockAddr]
1 ha 1019
 
2434 Serge 1020
        mov     eax, NET1OUT_QUEUE
1 ha 1021
 
2434 Serge 1022
        mov     edx, [stack_ip]
1023
        mov     ecx, [sockAddr]
1024
        cmp     edx, [ecx + SOCKET.RemoteIP]
1025
        jne     .not_local
1026
        mov     eax, IPIN_QUEUE
1 ha 1027
 
907 mikedld 1028
  .not_local:
2434 Serge 1029
        ; Send it.
1030
        pop     ebx
1031
        call    queue
1 ha 1032
 
907 mikedld 1033
  .exit:
2434 Serge 1034
        ret
1019 diamond 1035
  .overflow:
2434 Serge 1036
        ; no place in buffer
1037
        ; so simply restore stack and exit
1038
        lea     ecx, [ebx + SOCKET.mutex]
1039
        call    mutex_unlock
1040
        pop     eax ecx
1041
        ret
907 mikedld 1042
endp
1 ha 1043
 
1044
 
907 mikedld 1045
proc stateTCB_FIN_WAIT_1 stdcall, sockAddr:DWORD
2434 Serge 1046
        ; We can either receive an ACK of a fin, or a fin
1047
        mov     al, [edx + 20 + TCP_PACKET.Flags]
1048
        and     al, TH_FIN + TH_ACK
1 ha 1049
 
2434 Serge 1050
        cmp     al, TH_ACK
1051
        jne     @f
1 ha 1052
 
2434 Serge 1053
        ; It was an ACK
1054
        mov     [ebx + SOCKET.TCBState], TCB_FIN_WAIT_2
1055
        jmp     .exit
1 ha 1056
 
2434 Serge 1057
    @@:
1058
        mov     [ebx + SOCKET.TCBState], TCB_CLOSING
1059
        cmp     al, TH_FIN
1060
        je      @f
1061
        mov     [ebx + SOCKET.TCBState], TCB_TIMED_WAIT
1 ha 1062
 
2434 Serge 1063
    @@:
1064
        lea     esi, [ebx + SOCKET.RCV_NXT]
1065
        call    inc_inet_esi
1 ha 1066
 
2434 Serge 1067
        ; Send an ACK
1068
        mov     eax, EMPTY_QUEUE
1069
        call    dequeue
1070
        cmp     ax, NO_BUFFER
1071
        je      .exit
1 ha 1072
 
2434 Serge 1073
        push    eax
1 ha 1074
 
2434 Serge 1075
        mov     bl, TH_ACK
1076
        xor     ecx, ecx
1077
        xor     esi, esi
1078
        stdcall build_tcp_packet, [sockAddr]
1 ha 1079
 
2434 Serge 1080
        mov     eax, NET1OUT_QUEUE
1081
        mov     edx, [stack_ip]
1082
        mov     ecx, [sockAddr]
1083
        cmp     edx, [ecx + SOCKET.RemoteIP]
1084
        jne     .not_local
1085
        mov     eax, IPIN_QUEUE
1 ha 1086
 
907 mikedld 1087
  .not_local:
2434 Serge 1088
        ; Send it.
1089
        pop     ebx
1090
        call    queue
1 ha 1091
 
907 mikedld 1092
  .exit:
2434 Serge 1093
        ret
907 mikedld 1094
endp
1 ha 1095
 
1096
 
907 mikedld 1097
proc stateTCB_FIN_WAIT_2 stdcall, sockAddr:DWORD
2434 Serge 1098
        test    [edx + 20 + TCP_PACKET.Flags], TH_FIN
1099
        jz      .exit
1 ha 1100
 
2434 Serge 1101
        ; Change state, as we have a fin
1102
        mov     [ebx + SOCKET.TCBState], TCB_TIMED_WAIT
1 ha 1103
 
2434 Serge 1104
        lea     esi, [ebx + SOCKET.RCV_NXT]
1105
        call    inc_inet_esi
1 ha 1106
 
2434 Serge 1107
        ; Send an ACK
1108
        mov     eax, EMPTY_QUEUE
1109
        call    dequeue
1110
        cmp     ax, NO_BUFFER
1111
        je      .exit
1 ha 1112
 
2434 Serge 1113
        push    eax
1 ha 1114
 
2434 Serge 1115
        mov     bl, TH_ACK
1116
        xor     ecx, ecx
1117
        xor     esi, esi
1118
        stdcall build_tcp_packet, [sockAddr]
1 ha 1119
 
2434 Serge 1120
        mov     eax, NET1OUT_QUEUE
1121
        mov     edx, [stack_ip]
1122
        mov     ecx, [sockAddr]
1123
        cmp     edx, [ecx + SOCKET.RemoteIP]
1124
        jne     .not_local
1125
        mov     eax, IPIN_QUEUE
1 ha 1126
 
907 mikedld 1127
  .not_local:
2434 Serge 1128
        ; Send it.
1129
        pop     ebx
1130
        call    queue
1 ha 1131
 
907 mikedld 1132
  .exit:
2434 Serge 1133
        ret
907 mikedld 1134
endp
1 ha 1135
 
1136
 
907 mikedld 1137
proc stateTCB_CLOSE_WAIT stdcall, sockAddr:DWORD
2434 Serge 1138
        ; Intentionally left empty
1139
        ; socket_close_tcp handles this
1140
        ret
907 mikedld 1141
endp
1 ha 1142
 
1143
 
907 mikedld 1144
proc stateTCB_CLOSING stdcall, sockAddr:DWORD
2434 Serge 1145
        ; We can either receive an ACK of a fin, or a fin
1146
        test    [edx + 20 + TCP_PACKET.Flags], TH_ACK
1147
        jz      .exit
1 ha 1148
 
2434 Serge 1149
        mov     [ebx + SOCKET.TCBState], TCB_TIMED_WAIT
1 ha 1150
 
907 mikedld 1151
  .exit:
2434 Serge 1152
        ret
907 mikedld 1153
endp
1 ha 1154
 
1155
 
907 mikedld 1156
proc stateTCB_LAST_ACK stdcall, sockAddr:DWORD
2434 Serge 1157
        ; Look at control flags - expecting an ACK
1158
        test    [edx + 20 + TCP_PACKET.Flags], TH_ACK
1159
        jz      .exit
1 ha 1160
 
2434 Serge 1161
        ; delete the socket
1162
        stdcall net_socket_free, ebx
1 ha 1163
 
907 mikedld 1164
  .exit:
2434 Serge 1165
        ret
907 mikedld 1166
endp
1 ha 1167
 
1168
 
907 mikedld 1169
proc stateTCB_TIME_WAIT stdcall, sockAddr:DWORD
2434 Serge 1170
        ret
907 mikedld 1171
endp
1 ha 1172
 
1173
 
907 mikedld 1174
proc stateTCB_CLOSED stdcall, sockAddr:DWORD
2434 Serge 1175
        ret
907 mikedld 1176
endp