Subversion Repositories Kolibri OS

Rev

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

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