Subversion Repositories Kolibri OS

Rev

Rev 1635 | Rev 2209 | 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: 2130 $
20
 
21
 
261 hidnplayr 22
; TCP TCB states
907 mikedld 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
 
907 mikedld 35
TH_FIN	= 0x01
36
TH_SYN	= 0x02
37
TH_RST	= 0x04
38
TH_PUSH = 0x08
39
TH_ACK	= 0x10
40
TH_URG	= 0x20
261 hidnplayr 41
 
907 mikedld 42
TWOMSL		    equ     10	    ; # of secs to wait before closing socket
261 hidnplayr 43
 
907 mikedld 44
TCP_RETRIES	    equ 	5		; Number of times to resend a packet
1183 clevermous 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
907 mikedld 82
{  .SourcePort	     dw  ?  ;+00
261 hidnplayr 83
   .DestinationPort  dw  ?  ;+02
84
   .SequenceNumber   dd  ?  ;+04
907 mikedld 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
907 mikedld 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
113
	; scan through all the sockets, decrementing active timers
1 ha 114
 
907 mikedld 115
	mov	ebx, net_sockets
1 ha 116
 
907 mikedld 117
	cmp	[ebx + SOCKET.NextPtr], 0
118
	je	.exit
1095 diamond 119
	;DEBUGF	1, "K : sockets:\n"
1 ha 120
 
907 mikedld 121
  .next_socket:
122
	mov	ebx, [ebx + SOCKET.NextPtr]
123
	or	ebx, ebx
124
	jz	.exit
1 ha 125
 
1095 diamond 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
 
907 mikedld 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:
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
 
907 mikedld 139
	cmp	[ebx + SOCKET.TCBState], TCB_TIMED_WAIT
140
	jne	.next_socket
1 ha 141
 
907 mikedld 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:
148
	; TODO - prove it works!
149
	dec	[ebx + SOCKET.wndsizeTimer]
150
	jmp	.next_socket
1 ha 151
 
907 mikedld 152
  .exit:
153
	ret
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
 
907 mikedld 172
	mov	esi, resendQ
173
	mov	ecx, 0
1 ha 174
 
907 mikedld 175
  .next_resendq:
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
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
    @@:
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
 
907 mikedld 199
	; retries now 0, so delete from queue
200
	xchg	 [esi + 4], ebx
1 ha 201
 
907 mikedld 202
    @@: ; resend packet
203
	pushad
1 ha 204
 
907 mikedld 205
	mov	eax, EMPTY_QUEUE
206
	call	dequeue
207
	cmp	ax, NO_BUFFER
208
	jne	.tth004z
1 ha 209
 
907 mikedld 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
216
	mov	byte[esi + 1], 1
217
	mov	word[esi + 2], 1
218
	jmp	.tth005
1 ha 219
 
907 mikedld 220
  .tth004z:
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
 
907 mikedld 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,,
1183 clevermous 231
	imul	esi, ecx, IPBUFFSIZE
232
	add	esi, resendBuffer
1 ha 233
 
907 mikedld 234
	; we have resend buffer location in esi
235
	mov	ecx, IPBUFFSIZE
1 ha 236
 
907 mikedld 237
	; copy data across
238
	push	edi
239
	cld
240
	rep	movsb
241
	pop	edi
1 ha 242
 
907 mikedld 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:
251
	pop	ebx
252
	call	queue
1 ha 253
 
907 mikedld 254
  .tth005:
255
	popad
1 ha 256
 
907 mikedld 257
	inc	ecx
258
	add	esi, 8
259
	jmp	.next_resendq
1 ha 260
 
907 mikedld 261
  .exit:
262
	ret
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
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
 
907 mikedld 291
	push	eax
1 ha 292
 
907 mikedld 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
 
907 mikedld 298
	mov	ebx, net_sockets
1 ha 299
 
907 mikedld 300
  .next_socket.1:
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
 
907 mikedld 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
 
907 mikedld 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
 
907 mikedld 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
 
907 mikedld 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
 
907 mikedld 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
 
907 mikedld 334
	mov	ebx, net_sockets
1 ha 335
 
907 mikedld 336
  .next_socket.2:
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
 
907 mikedld 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
 
907 mikedld 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
 
907 mikedld 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
 
907 mikedld 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
 
907 mikedld 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
 
907 mikedld 369
	mov	ebx, net_sockets
1 ha 370
 
907 mikedld 371
  .next_socket.3:
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
 
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
381
 
382
;        DEBUGF  1, "K : tcp_rx - 3.addr: 00000000 - %x\n", [ebx + SOCKET.RemoteIP]
383
 
384
	cmp	[ebx + SOCKET.RemoteIP], 0		; only match a socket remote IP of 0
385
	jne	.next_socket.3				; different - try next socket
386
 
387
;        DEBUGF  1, "K : tcp_rx - 3.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4
388
 
389
	cmp	[ebx + SOCKET.RemotePort], 0		; only match a remote socket of 0
390
	jne	.next_socket.3				; different - try next socket
391
 
392
	; We have a complete match - use this socket
393
	jmp	.change_state
394
 
395
  .next_socket.3.exit:
396
 
397
	; If we got here, we need to reject the packet
398
 
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
 
907 mikedld 402
	inc	[dumped_rx_count]
403
	jmp	.exit
404
 
405
  .change_state:
406
 
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)
411
 
412
	stdcall tcpStateMachine, ebx
413
 
414
  .exit:
415
	pop	eax
416
	call	freeBuff
417
	ret
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
437
	push	ecx			   ; Save data length
1 ha 438
 
907 mikedld 439
	; convert buffer pointer eax to the absolute address
440
	mov	ecx, IPBUFFSIZE
441
	mul	ecx
442
	add	eax, IPbuffs
1 ha 443
 
907 mikedld 444
	mov	edx, eax
1 ha 445
 
907 mikedld 446
	mov	[edx + 20 + TCP_PACKET.Flags], bl		; TCP flags
1 ha 447
 
907 mikedld 448
	mov	ebx, [sockAddr]
1 ha 449
 
907 mikedld 450
	; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
1 ha 451
 
907 mikedld 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
 
907 mikedld 458
	mov	[edx + IP_PACKET.VersionAndIHL], 0x45
459
	mov	[edx + IP_PACKET.TypeOfService], 0
1 ha 460
 
907 mikedld 461
	pop	eax		      ; Get the TCP data length
462
	push	eax
1 ha 463
 
907 mikedld 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
 
907 mikedld 472
	; Checksum left unfilled
473
	mov	[edx + IP_PACKET.HeaderChecksum], 0
1 ha 474
 
907 mikedld 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
 
907 mikedld 479
	mov	ax, [ebx + SOCKET.RemotePort]
480
	mov	[edx + 20 + TCP_PACKET.DestinationPort], ax	; desitination Port
1 ha 481
 
907 mikedld 482
	; Checksum left unfilled
483
	mov	[edx + 20 + TCP_PACKET.Checksum], 0
1 ha 484
 
907 mikedld 485
	; sequence number
486
	mov	eax, [ebx + SOCKET.SND_NXT]
487
	mov	[edx + 20 + TCP_PACKET.SequenceNumber], eax
1 ha 488
 
907 mikedld 489
	; ack number
490
	mov	eax, [ebx + SOCKET.RCV_NXT]
491
	mov	[edx + 20 + TCP_PACKET.AckNumber], eax
1 ha 492
 
907 mikedld 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
 
907 mikedld 497
	; Urgent pointer (0)
498
	mov	[edx + 20 + TCP_PACKET.UrgentPointer], 0
1 ha 499
 
907 mikedld 500
	; data offset ( 0x50 )
501
	mov	[edx + 20 + TCP_PACKET.DataOffset], 0x50
1 ha 502
 
907 mikedld 503
	pop	ecx		     ; count of bytes to send
504
	mov	ebx, ecx	    ; need the length later
1 ha 505
 
907 mikedld 506
	cmp	ebx, 0
507
	jz	@f
1 ha 508
 
907 mikedld 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.
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
 
907 mikedld 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
 
907 mikedld 535
	call	checksum
1 ha 536
 
907 mikedld 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
 
907 mikedld 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
 
907 mikedld 548
	ret
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
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
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
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
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
610
	; as a packet has been received, update the TCB timer
611
	mov	[ebx + SOCKET.TCBTimer], TWOMSL
1 ha 612
 
907 mikedld 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
 
907 mikedld 620
	; get skt number in eax
621
	stdcall net_socket_addr_to_num, ebx
1 ha 622
 
907 mikedld 623
	; The ack number is in [edx + 28], inet format
624
	; skt in eax
1 ha 625
 
907 mikedld 626
	mov	esi, resendQ
627
	xor	ecx, ecx
1 ha 628
 
907 mikedld 629
  .next_resendq:
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
 
907 mikedld 638
    @@: 		  ; Can we delete this buffer?
1 ha 639
 
907 mikedld 640
			  ; If yes, goto @@. No, goto .next_resendq
641
	; Get packet data address
1 ha 642
 
907 mikedld 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
 
907 mikedld 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
 
907 mikedld 658
	; get recievd ack #, in intel format
659
	mov	ebx, [edx + 20 + TCP_PACKET.AckNumber]
660
	bswap	ebx
1 ha 661
 
907 mikedld 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
 
907 mikedld 668
	inc	ecx
669
	add	esi, 8
670
	jmp	.next_resendq
1 ha 671
 
907 mikedld 672
    @@: mov	dword[esi + 4], 0
673
	inc	ecx
674
	add	esi, 8
675
	jmp	.next_resendq
1 ha 676
 
907 mikedld 677
  .call_handler:
678
	popad
1 ha 679
 
907 mikedld 680
	; Call handler for given TCB state
1 ha 681
 
907 mikedld 682
	mov	eax, [ebx + SOCKET.TCBState]
683
	cmp	eax, TCB_LISTEN
684
	jb	.exit
685
	cmp	eax, TCB_CLOSED
686
	ja	.exit
1 ha 687
 
907 mikedld 688
	stdcall [TCBStateHandler + (eax - 1) * 4], [sockAddr]
1 ha 689
 
907 mikedld 690
  .exit:
691
	ret
692
endp
1 ha 693
 
1181 clevermous 694
;***************************************************************************
695
;   Function
696
;      signal_network_event
697
;
698
;   Description
699
;       Signals about network event to socket owner
700
;       This is a kernel function, called from TCP handler
701
;
702
;          Socket/TCB address in ebx
703
;***************************************************************************
704
proc signal_network_event
705
	push	ecx esi eax
706
	mov	eax, [ebx + SOCKET.PID]
707
	mov	ecx, 1
708
	mov	esi, TASK_DATA + TASKDATA.pid
1 ha 709
 
1181 clevermous 710
  .next_pid:
711
	cmp	[esi], eax
712
	je	.found_pid
713
	inc	ecx
714
	add	esi, 0x20
715
	cmp	ecx, [TASK_COUNT]
716
	jbe	.next_pid
717
 
718
  .found_pid:
719
	shl	ecx, 8
720
	or	[ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event
721
	pop	eax esi ecx
722
	ret
723
endp
724
 
907 mikedld 725
proc stateTCB_LISTEN stdcall, sockAddr:DWORD
726
	; In this case, we are expecting a SYN packet
727
	; For now, if the packet is a SYN, process it, and send a response
728
	; If not, ignore it
1 ha 729
 
907 mikedld 730
	; Look at control flags
731
	test	[edx + 20 + TCP_PACKET.Flags], TH_SYN
732
	jz	.exit
1 ha 733
 
907 mikedld 734
	; We have a SYN. update the socket with this IP packets details,
735
	; And send a response
1 ha 736
 
907 mikedld 737
	mov	eax, [edx + IP_PACKET.SourceAddress]
738
	mov	[ebx + SOCKET.RemoteIP], eax
739
	mov	ax, [edx + 20 + TCP_PACKET.SourcePort]
740
	mov	[ebx + SOCKET.RemotePort], ax
741
	mov	eax, [edx + 20 + TCP_PACKET.SequenceNumber]
742
	mov	[ebx + SOCKET.IRS], eax
743
	mov	[ebx + SOCKET.RCV_NXT], eax
744
	lea	esi, [ebx + SOCKET.RCV_NXT]
745
	call	inc_inet_esi ; RCV.NXT
746
	mov	eax, [ebx + SOCKET.ISS]
747
	mov	[ebx + SOCKET.SND_NXT], eax
1 ha 748
 
907 mikedld 749
	; Now construct the response, and queue for sending by IP
750
	mov	eax, EMPTY_QUEUE
751
	call	dequeue
752
	cmp	ax, NO_BUFFER
753
	je	.exit
1 ha 754
 
1181 clevermous 755
	push	ebx
907 mikedld 756
	push	eax
757
	mov	bl, TH_SYN + TH_ACK
758
	xor	ecx, ecx
759
	xor	esi, esi
760
	stdcall build_tcp_packet, [sockAddr]
1 ha 761
 
907 mikedld 762
	mov	eax, NET1OUT_QUEUE
763
	mov	edx, [stack_ip]
764
	mov	ecx, [sockAddr]
765
	cmp	edx, [ecx + SOCKET.RemoteIP]
766
	jne	.not_local
767
	mov	eax, IPIN_QUEUE
1 ha 768
 
907 mikedld 769
  .not_local:
770
	; Send it.
771
	pop	ebx
772
	call	queue
1 ha 773
 
1181 clevermous 774
	pop	ebx
907 mikedld 775
	mov	esi, [sockAddr]
776
	mov	[esi + SOCKET.TCBState], TCB_SYN_RECEIVED
1181 clevermous 777
	call	signal_network_event
1 ha 778
 
907 mikedld 779
	; increment SND.NXT in socket
780
	add	esi, SOCKET.SND_NXT
781
	call	inc_inet_esi
1 ha 782
 
907 mikedld 783
  .exit:
784
	ret
785
endp
1 ha 786
 
787
 
907 mikedld 788
proc stateTCB_SYN_SENT stdcall, sockAddr:DWORD
789
	; We are awaiting an ACK to our SYN, with a SYM
790
	; Look at control flags - expecting an ACK
1 ha 791
 
907 mikedld 792
	mov	al, [edx + 20 + TCP_PACKET.Flags]
793
	and	al, TH_SYN + TH_ACK
794
	cmp	al, TH_SYN + TH_ACK
795
	je	.syn_ack
1 ha 796
 
907 mikedld 797
	test	al, TH_SYN
798
	jz	.exit
1 ha 799
 
907 mikedld 800
	mov	[ebx + SOCKET.TCBState], TCB_SYN_RECEIVED
801
	push	TH_SYN + TH_ACK
802
	jmp	.send
1 ha 803
 
907 mikedld 804
  .syn_ack:
805
	mov	[ebx + SOCKET.TCBState], TCB_ESTABLISHED
806
	push	TH_ACK
1 ha 807
 
907 mikedld 808
  .send:
1181 clevermous 809
	call	signal_network_event
907 mikedld 810
	; Store the recv.nxt field
811
	mov	eax, [edx + 20 + TCP_PACKET.SequenceNumber]
1 ha 812
 
907 mikedld 813
	; Update our recv.nxt field
814
	mov	[ebx + SOCKET.RCV_NXT], eax
815
	lea	esi, [ebx + SOCKET.RCV_NXT]
816
	call	inc_inet_esi
1 ha 817
 
907 mikedld 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
823
	pop	ebx
824
	je	.exit
1 ha 825
 
907 mikedld 826
	push	eax
1 ha 827
 
907 mikedld 828
	xor	ecx, ecx
829
	xor	esi, esi
830
	stdcall build_tcp_packet, [sockAddr]
1 ha 831
 
907 mikedld 832
	mov	eax, NET1OUT_QUEUE
833
	mov	edx, [stack_ip]
834
	mov	ecx, [sockAddr]
835
	cmp	edx, [ecx + SOCKET.RemoteIP]
836
	jne	.not_local
837
	mov	eax, IPIN_QUEUE
1 ha 838
 
907 mikedld 839
  .not_local:
840
	; Send it.
841
	pop	ebx
842
	call	queue
1 ha 843
 
907 mikedld 844
  .exit:
845
	ret
846
endp
1 ha 847
 
848
 
907 mikedld 849
proc stateTCB_SYN_RECEIVED stdcall, sockAddr:DWORD
850
	; In this case, we are expecting an ACK packet
851
	; For now, if the packet is an ACK, process it,
852
	; If not, ignore it
1 ha 853
 
922 mikedld 854
	test	[edx + 20 + TCP_PACKET.Flags], TH_RST
855
	jz	.check_ack
1 ha 856
 
907 mikedld 857
	push	[ebx + SOCKET.OrigRemotePort] [ebx + SOCKET.OrigRemoteIP]
858
	pop	[ebx + SOCKET.RemoteIP] [ebx + SOCKET.RemotePort]
1 ha 859
 
922 mikedld 860
	mov	[ebx + SOCKET.TCBState], TCB_LISTEN
1181 clevermous 861
	jmp	.signal
1 ha 862
 
922 mikedld 863
  .check_ack:
907 mikedld 864
	; Look at control flags - expecting an ACK
865
	test	[edx + 20 + TCP_PACKET.Flags], TH_ACK
866
	jz	.exit
1 ha 867
 
907 mikedld 868
	mov	[ebx + SOCKET.TCBState], TCB_ESTABLISHED
1181 clevermous 869
  .signal:
870
	call	signal_network_event
1 ha 871
 
907 mikedld 872
  .exit:
873
	ret
874
endp
1 ha 875
 
876
 
907 mikedld 877
proc stateTCB_ESTABLISHED stdcall, sockAddr:DWORD
878
	; Here we are expecting data, or a request to close
879
	; OR both...
1 ha 880
 
1181 clevermous 881
	; Ignore all packets with sequnce number other than next expected
882
 
883
	; recv.nxt is in dword [edx+24], in inet format
884
	; recv seq is in [sktAddr]+56, in inet format
885
	; just do a comparision
886
	mov	eax, [ebx + SOCKET.RCV_NXT]
887
	cmp	eax, [edx + 20 + TCP_PACKET.SequenceNumber]
888
	jne	.exit
889
 
907 mikedld 890
	; Did we receive a FIN or RST?
1288 tsdima 891
	test	[edx + 20 + TCP_PACKET.Flags], TH_FIN+TH_RST
922 mikedld 892
	jz	.check_ack
1 ha 893
 
907 mikedld 894
	; It was a fin or reset.
1 ha 895
 
907 mikedld 896
	; Remove resend entries from the queue  - I dont want to send any more data
897
	pushad
1 ha 898
 
907 mikedld 899
	; get skt #
900
	stdcall net_socket_addr_to_num, ebx
1 ha 901
 
907 mikedld 902
	mov	esi, resendQ
903
	mov	ecx, 0
1 ha 904
 
907 mikedld 905
  .next_resendq:
906
	cmp	ecx, NUMRESENDENTRIES
907
	je	.last_resendq	    ; None left
908
	cmp	[esi + 4], eax
909
	je	@f		    ; found one
910
	inc	ecx
911
	add	esi, 8
912
	jmp	.next_resendq
1 ha 913
 
907 mikedld 914
    @@: mov	dword[esi + 4], 0
915
	inc	ecx
916
	add	esi, 8
917
	jmp	.next_resendq
1 ha 918
 
907 mikedld 919
  .last_resendq:
920
	popad
1 ha 921
 
907 mikedld 922
    @@: ; Send an ACK to that fin, and enter closewait state
1 ha 923
 
907 mikedld 924
	mov	[ebx + SOCKET.TCBState], TCB_CLOSE_WAIT
1288 tsdima 925
	test	[edx + 20 + TCP_PACKET.Flags], TH_RST
926
	je      @f
927
	mov	[ebx + SOCKET.TCBState], TCB_CLOSED
928
    @@:
1181 clevermous 929
	call	signal_network_event
907 mikedld 930
	lea	esi, [ebx + SOCKET.RCV_NXT]
931
	mov	eax, [esi]		; save original
932
	call	inc_inet_esi
933
	;; jmp    ste_ack - NO, there may be data
1 ha 934
 
907 mikedld 935
  .check_ack:
936
	; Check that we received an ACK
937
	test	[edx + 20 + TCP_PACKET.Flags], TH_ACK
938
	jz	.exit
1 ha 939
 
907 mikedld 940
	; TODO - done, I think!
941
	; First, look at the incoming window. If this is less than or equal to 1024,
942
	; Set the socket window timer to 1. This will stop an additional packets being queued.
943
	; ** I may need to tweak this value, since I do not know how many packets are already queued
944
	mov	cx, [edx + 20 + TCP_PACKET.Window]
945
	xchg	cl, ch
946
	cmp	cx, 1024
947
	ja	@f
1 ha 948
 
907 mikedld 949
	mov	[ebx + SOCKET.wndsizeTimer], 1
1 ha 950
 
907 mikedld 951
    @@: ; OK, here is the deal
1 ha 952
 
953
 
907 mikedld 954
	; Read the data bytes, store in socket buffer
955
	movzx	ecx, [edx + IP_PACKET.TotalLength]
956
	xchg	cl, ch
957
	sub	ecx, 40 		   ; Discard 40 bytes of header
1019 diamond 958
	ja	.data			   ; Read data, if any
1 ha 959
 
907 mikedld 960
	; If we had received a fin, we need to ACK it.
961
	cmp	[ebx + SOCKET.TCBState], TCB_CLOSE_WAIT
962
	je	.ack
963
	jmp	.exit
1 ha 964
 
907 mikedld 965
  .data:
2130 serge 966
    push    ecx
967
    lea     ecx, [ebx+SOCKET.lock]
968
    call    mutex_lock
1019 diamond 969
 
1181 clevermous 970
	push	ebx
1019 diamond 971
	mov	eax, [ebx + SOCKET.rxDataCount]
972
	add	eax, ecx
973
	cmp	eax, SOCKETBUFFSIZE - SOCKETHEADERSIZE
974
	ja	.overflow
1 ha 975
 
1019 diamond 976
	mov	[ebx + SOCKET.rxDataCount], eax      ; increment the count of bytes in buffer
1 ha 977
 
907 mikedld 978
	; point to the location to store the data
979
	lea	edi, [ebx + eax + SOCKETHEADERSIZE]
980
	sub	edi, ecx
1 ha 981
 
907 mikedld 982
	add	edx, 40        ; edx now points to the data
983
	mov	esi, edx
1 ha 984
 
907 mikedld 985
	cld
986
	rep	movsb	       ; copy the data across
1 ha 987
 
2130 serge 988
    lea ecx,[ebx + SOCKET.lock]
989
    call mutex_unlock
990
 
907 mikedld 991
	; flag an event to the application
1181 clevermous 992
	pop	ebx
993
	call	signal_network_event
1 ha 994
 
907 mikedld 995
	pop	ecx
1 ha 996
 
907 mikedld 997
	; Update our recv.nxt field
998
	lea	esi, [ebx + SOCKET.RCV_NXT]
999
	call	add_inet_esi
1 ha 1000
 
907 mikedld 1001
  .ack:
1002
	; Send an ACK
1003
	; Now construct the response, and queue for sending by IP
1004
	mov	eax, EMPTY_QUEUE
1005
	call	dequeue
1006
	cmp	ax, NO_BUFFER
1007
	je	.exit
1 ha 1008
 
907 mikedld 1009
	push	eax
1 ha 1010
 
907 mikedld 1011
	mov	bl, TH_ACK
1012
	xor	ecx, ecx
1013
	xor	esi, esi
1014
	stdcall build_tcp_packet, [sockAddr]
1 ha 1015
 
907 mikedld 1016
	mov	eax, NET1OUT_QUEUE
1 ha 1017
 
907 mikedld 1018
	mov	edx, [stack_ip]
1019
	mov	ecx, [sockAddr]
1020
	cmp	edx, [ecx + SOCKET.RemoteIP]
1021
	jne	.not_local
1022
	mov	eax, IPIN_QUEUE
1 ha 1023
 
907 mikedld 1024
  .not_local:
1025
	; Send it.
1026
	pop	ebx
1027
	call	queue
1 ha 1028
 
907 mikedld 1029
  .exit:
1030
	ret
1019 diamond 1031
  .overflow:
1032
	; no place in buffer
1033
	; so simply restore stack and exit
2130 serge 1034
    lea ecx, [ebx + SOCKET.lock]
1035
    call mutex_unlock
1019 diamond 1036
	pop	eax ecx
1037
	ret
907 mikedld 1038
endp
1 ha 1039
 
1040
 
907 mikedld 1041
proc stateTCB_FIN_WAIT_1 stdcall, sockAddr:DWORD
1042
	; We can either receive an ACK of a fin, or a fin
1043
	mov	al, [edx + 20 + TCP_PACKET.Flags]
1044
	and	al, TH_FIN + TH_ACK
1 ha 1045
 
907 mikedld 1046
	cmp	al, TH_ACK
1047
	jne	@f
1 ha 1048
 
907 mikedld 1049
	; It was an ACK
1050
	mov	[ebx + SOCKET.TCBState], TCB_FIN_WAIT_2
1051
	jmp	.exit
1 ha 1052
 
907 mikedld 1053
    @@: mov	[ebx + SOCKET.TCBState], TCB_CLOSING
1054
	cmp	al, TH_FIN
1055
	je	@f
1056
	mov	[ebx + SOCKET.TCBState], TCB_TIMED_WAIT
1 ha 1057
 
907 mikedld 1058
    @@: lea	esi, [ebx + SOCKET.RCV_NXT]
1059
	call	inc_inet_esi
1 ha 1060
 
907 mikedld 1061
	; Send an ACK
1062
	mov	eax, EMPTY_QUEUE
1063
	call	dequeue
1064
	cmp	ax, NO_BUFFER
1065
	je	.exit
1 ha 1066
 
907 mikedld 1067
	push	eax
1 ha 1068
 
907 mikedld 1069
	mov	bl, TH_ACK
1070
	xor	ecx, ecx
1071
	xor	esi, esi
1072
	stdcall build_tcp_packet, [sockAddr]
1 ha 1073
 
907 mikedld 1074
	mov	eax, NET1OUT_QUEUE
1075
	mov	edx, [stack_ip]
1076
	mov	ecx, [sockAddr]
1077
	cmp	edx, [ecx + SOCKET.RemoteIP]
1078
	jne	.not_local
1079
	mov	eax, IPIN_QUEUE
1 ha 1080
 
907 mikedld 1081
  .not_local:
1082
	; Send it.
1083
	pop	ebx
1084
	call	queue
1 ha 1085
 
907 mikedld 1086
  .exit:
1087
	ret
1088
endp
1 ha 1089
 
1090
 
907 mikedld 1091
proc stateTCB_FIN_WAIT_2 stdcall, sockAddr:DWORD
1092
	test	[edx + 20 + TCP_PACKET.Flags], TH_FIN
1093
	jz	.exit
1 ha 1094
 
907 mikedld 1095
	; Change state, as we have a fin
1096
	mov	[ebx + SOCKET.TCBState], TCB_TIMED_WAIT
1 ha 1097
 
907 mikedld 1098
	lea	esi, [ebx + SOCKET.RCV_NXT]
1099
	call	inc_inet_esi
1 ha 1100
 
907 mikedld 1101
	; Send an ACK
1102
	mov	eax, EMPTY_QUEUE
1103
	call	dequeue
1104
	cmp	ax, NO_BUFFER
1105
	je	.exit
1 ha 1106
 
907 mikedld 1107
	push	eax
1 ha 1108
 
907 mikedld 1109
	mov	bl, TH_ACK
1110
	xor	ecx, ecx
1111
	xor	esi, esi
1112
	stdcall build_tcp_packet, [sockAddr]
1 ha 1113
 
907 mikedld 1114
	mov	eax, NET1OUT_QUEUE
1115
	mov	edx, [stack_ip]
1116
	mov	ecx, [sockAddr]
1117
	cmp	edx, [ecx + SOCKET.RemoteIP]
1118
	jne	.not_local
1119
	mov	eax, IPIN_QUEUE
1 ha 1120
 
907 mikedld 1121
  .not_local:
1122
	; Send it.
1123
	pop	ebx
1124
	call	queue
1 ha 1125
 
907 mikedld 1126
  .exit:
1127
	ret
1128
endp
1 ha 1129
 
1130
 
907 mikedld 1131
proc stateTCB_CLOSE_WAIT stdcall, sockAddr:DWORD
1132
	; Intentionally left empty
1133
	; socket_close_tcp handles this
1134
	ret
1135
endp
1 ha 1136
 
1137
 
907 mikedld 1138
proc stateTCB_CLOSING stdcall, sockAddr:DWORD
1139
	; We can either receive an ACK of a fin, or a fin
1140
	test	[edx + 20 + TCP_PACKET.Flags], TH_ACK
1141
	jz	.exit
1 ha 1142
 
907 mikedld 1143
	mov	[ebx + SOCKET.TCBState], TCB_TIMED_WAIT
1 ha 1144
 
907 mikedld 1145
  .exit:
1146
	ret
1147
endp
1 ha 1148
 
1149
 
907 mikedld 1150
proc stateTCB_LAST_ACK stdcall, sockAddr:DWORD
1151
	; Look at control flags - expecting an ACK
1152
	test	[edx + 20 + TCP_PACKET.Flags], TH_ACK
1153
	jz	.exit
1 ha 1154
 
907 mikedld 1155
	; delete the socket
1156
	stdcall net_socket_free, ebx
1 ha 1157
 
907 mikedld 1158
  .exit:
1159
	ret
1160
endp
1 ha 1161
 
1162
 
907 mikedld 1163
proc stateTCB_TIME_WAIT stdcall, sockAddr:DWORD
1164
	ret
1165
endp
1 ha 1166
 
1167
 
907 mikedld 1168
proc stateTCB_CLOSED stdcall, sockAddr:DWORD
1169
	ret
1170
endp