Subversion Repositories Kolibri OS

Rev

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

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