Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1196 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  TCP.INC                                                        ;;
7
;;                                                                 ;;
8
;;  Part of the tcp/ip network stack for KolibriOS                 ;;
9
;;                                                                 ;;
10
;;    Written by hidnplayr@kolibrios.org                           ;;
11
;;                                                                 ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
13
;;             Version 2, June 1991                                ;;
14
;;                                                                 ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1159 hidnplayr 16
 
1196 hidnplayr 17
 
1159 hidnplayr 18
$Revision: 1019 $
19
 
20
 
21
; TCP TCB states
22
TCB_LISTEN		equ 1
23
TCB_SYN_SENT		equ 2
24
TCB_SYN_RECEIVED	equ 3
25
TCB_ESTABLISHED 	equ 4
26
TCB_FIN_WAIT_1		equ 5
27
TCB_FIN_WAIT_2		equ 6
28
TCB_CLOSE_WAIT		equ 7
29
TCB_CLOSING		equ 8
30
TCB_LAST_ACK		equ 9
31
TCB_TIMED_WAIT		equ 10
32
TCB_CLOSED		equ 11
33
 
34
TH_FIN			equ 0x01
35
TH_SYN			equ 0x02
36
TH_RST			equ 0x04
37
TH_PUSH 		equ 0x08
38
TH_ACK			equ 0x10
39
TH_URG			equ 0x20
40
 
1196 hidnplayr 41
TWOMSL			equ 10		; # of secs to wait before closing socket
1159 hidnplayr 42
 
1196 hidnplayr 43
TCP_RETRIES		equ 5		; Number of times to resend a Packet
44
TCP_TIMEOUT		equ 10		; resend if not replied to in x hs
1159 hidnplayr 45
 
1196 hidnplayr 46
TCP_QUEUE_SIZE		equ 16
47
 
1159 hidnplayr 48
struct	TCP_Packet
49
	.SourcePort		dw ?
50
	.DestinationPort	dw ?
51
	.SequenceNumber 	dd ?
52
	.AckNumber		dd ?
1196 hidnplayr 53
	.DataOffset		db ?	; DataOffset[0-3 bits] and Reserved[4-7]
54
	.Flags			db ?	; Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN
1159 hidnplayr 55
	.Window 		dw ?
56
	.Checksum		dw ?
57
	.UrgentPointer		dw ?
58
	.Options		rb 3
59
	.Padding		db ?
60
	.Data:
61
ends
62
 
1196 hidnplayr 63
align 4
64
uglobal
65
	TCP_PACKETS_TX		rd  MAX_IP
66
	TCP_PACKETS_RX		rd  MAX_IP
1159 hidnplayr 67
 
1196 hidnplayr 68
	TCP_IN_QUEUE	rd  3*TCP_QUEUE_SIZE+3
69
	TCP_OUT_QUEUE	rd  3*TCP_QUEUE_SIZE+3
70
endg
71
 
72
 
73
 
74
 
75
 
76
;-----------------------------------------------------------------
77
;
78
; TCP_init
79
;
80
;  This function resets all TCP variables
81
;
82
;  IN:  /
83
;  OUT: /
84
;
85
;-----------------------------------------------------------------
86
 
87
align 4
88
TCP_init:
89
 
90
	xor	eax, eax
91
	mov	edi, TCP_PACKETS_TX
92
	mov	ecx, 2*MAX_IP
93
	rep	stosd
94
 
95
	mov	dword [TCP_IN_QUEUE], TCP_QUEUE_SIZE
96
	mov	dword [TCP_IN_QUEUE+4], TCP_IN_QUEUE + queue.data
97
	mov	dword [TCP_IN_QUEUE+8], TCP_IN_QUEUE + queue.data
98
 
99
	mov	dword [TCP_OUT_QUEUE], TCP_QUEUE_SIZE
100
	mov	dword [TCP_OUT_QUEUE+4], TCP_OUT_QUEUE + queue.data
101
	mov	dword [TCP_OUT_QUEUE+8], TCP_OUT_QUEUE + queue.data
102
 
103
	ret
104
 
105
 
106
;-----------------------------------------------------------------
107
;
1159 hidnplayr 108
;      tcp_tcb_handler
109
;
110
;       Handles sockets in the timewait state, closing them
111
;       when the TCB timer expires
112
;
1196 hidnplayr 113
;-----------------------------------------------------------------
1159 hidnplayr 114
 
1196 hidnplayr 115
align 4
1159 hidnplayr 116
tcp_tcb_handler:
117
	; scan through all the sockets, decrementing active timers
118
 
119
	mov	ebx, net_sockets
120
 
121
	cmp	[ebx + SOCKET.NextPtr], 0
122
	je	.exit
123
	DEBUGF	1, "K : sockets:\n"
124
 
125
  .next_socket:
126
	mov	ebx, [ebx + SOCKET.NextPtr]
127
	or	ebx, ebx
128
	jz	.exit
129
 
1196 hidnplayr 130
;        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]
1159 hidnplayr 131
 
132
	cmp	[ebx + SOCKET.TCBTimer], 0
133
	jne	.decrement_tcb
134
	cmp	[ebx + SOCKET.wndsizeTimer], 0
135
	jne	.decrement_wnd
136
	jmp	.next_socket
137
 
138
  .decrement_tcb:
139
	; decrement it, delete socket if TCB timer = 0 & socket in timewait state
140
	dec	[ebx + SOCKET.TCBTimer]
141
	jnz	.next_socket
142
 
143
	cmp	[ebx + SOCKET.TCBState], TCB_TIMED_WAIT
144
	jne	.next_socket
145
 
146
	push	[ebx + SOCKET.PrevPtr]
147
	stdcall net_socket_free, ebx
148
	pop	ebx
149
	jmp	.next_socket
150
 
151
  .decrement_wnd:
152
	; TODO - prove it works!
153
	dec	[ebx + SOCKET.wndsizeTimer]
154
	jmp	.next_socket
155
 
156
  .exit:
157
	ret
158
 
159
 
160
;***************************************************************************
161
;   Function
162
;      tcp_tx_handler
163
;
164
;   Description
165
;       Handles queued TCP data
166
;       This is a kernel function, called by stack_handler
167
;
168
;***************************************************************************
169
 
1196 hidnplayr 170
align 4
171
tcp_tx_handler:
1159 hidnplayr 172
    ; decrement all resend buffers timers. If they
173
    ; expire, queue them for sending, and restart the timer.
174
    ; If the retries counter reach 0, delete the entry
175
 
176
	mov	esi, resendQ
177
	mov	ecx, 0
178
 
179
  .next_resendq:
1196 hidnplayr 180
;        cmp     ecx, NUMRESENDENTRIES
1159 hidnplayr 181
	je	.exit		    ; None left
182
	cmp	dword[esi + 4], 0
183
	jne	@f		     ; found one
184
	inc	ecx
185
	add	esi, 8
186
	jmp	.next_resendq
187
 
188
    @@: ; we have one. decrement it's timer by 1
189
	dec	word[esi + 2]
190
	jz	@f
191
	inc	ecx
192
	add	esi, 8
193
	jmp	.next_resendq	    ; Timer not zero, so move on
194
 
195
    @@:
196
	xor	ebx, ebx
197
	; restart timer, and decrement retries
198
	; After the first resend, back of on next, by a factor of 5
199
	mov	[esi + 2], word TCP_TIMEOUT * 5
200
	dec	byte[esi + 1]
201
	jnz	@f
202
 
203
	; retries now 0, so delete from queue
204
	xchg	 [esi + 4], ebx
205
 
206
    @@: ; resend Packet
207
	pushad
208
 
1196 hidnplayr 209
;        mov     eax, EMPTY_QUEUE
210
;        call    dequeue
211
;        cmp     ax, NO_BUFFER
1159 hidnplayr 212
	jne	.tth004z
213
 
214
	; TODO - try again in 10ms.
215
	test	ebx, ebx
216
	jnz	@f
217
	mov	[esi + 4], ebx
218
 
219
    @@: ; Mark it to expire in 10ms - 1 tick
220
	mov	byte[esi + 1], 1
221
	mov	word[esi + 2], 1
222
	jmp	.tth005
223
 
224
  .tth004z:
225
	; we have a buffer # in ax
1196 hidnplayr 226
;        push    eax ecx
227
;        mov     ecx, IPBUFFSIZE
228
;        mul     ecx
229
;        add     eax, IPbuffs
1159 hidnplayr 230
 
231
	; we have the buffer address in eax
232
	mov	edi, eax
233
	pop	ecx
234
	; Now get buffer location, and copy buffer across. argh! more copying,,
1196 hidnplayr 235
;        mov     esi, resendBuffer
236
;    @@: add     esi, IPBUFFSIZE
1159 hidnplayr 237
	loop	@b
238
 
239
	; we have resend buffer location in esi
1196 hidnplayr 240
;        mov     ecx, IPBUFFSIZE
1159 hidnplayr 241
 
242
	; copy data across
243
	push	edi
244
	cld
245
	rep	movsb
246
	pop	edi
247
 
248
	; queue Packet
1196 hidnplayr 249
;        mov     eax, NET1OUT_QUEUE
250
;        mov     edx, [IP_LIST]
251
;        cmp     edx, [edi + IP_Packet.DestinationAddress]
252
;        jne     .not_local
253
;        mov     eax, IPIN_QUEUE
1159 hidnplayr 254
 
255
  .not_local:
256
	pop	ebx
1196 hidnplayr 257
;        call    queue
1159 hidnplayr 258
 
259
  .tth005:
260
	popad
261
 
262
	inc	ecx
263
	add	esi, 8
264
	jmp	.next_resendq
265
 
266
  .exit:
267
	ret
268
 
269
 
1196 hidnplayr 270
 
271
;-----------------------------------------------------------------
1159 hidnplayr 272
;
1196 hidnplayr 273
; TCP_Handler:
1159 hidnplayr 274
;
1196 hidnplayr 275
;  Called by IPv4_handler,
276
;  this procedure will inject the tcp data diagrams in the application sockets.
277
;
278
;  IN:  Pointer to buffer in [esp]
279
;       size of buffer in [esp+4]
280
;       pointer to device struct in ebx
281
;       TCP Packet size in ecx
282
;       pointer to TCP Packet data in edx
283
;       SourceAddres in esi
284
;  OUT: /
285
;
286
;-----------------------------------------------------------------
1159 hidnplayr 287
 
1196 hidnplayr 288
TCP_Handler :
1159 hidnplayr 289
 
290
 
1196 hidnplayr 291
       DEBUGF 1,"TCP_Handler\n"
292
 
293
	jmp .exit ;;;;
294
 
1159 hidnplayr 295
	; Look for a socket where
296
	; IP Packet TCP Destination Port = local Port
297
	; IP Packet SA = Remote IP
298
	; IP Packet TCP Source Port = remote Port
299
 
300
	mov	ebx, net_sockets
301
 
302
  .next_socket.1:
303
	mov	ebx, [ebx + SOCKET.NextPtr]
304
	or	ebx, ebx
305
	jz	.next_socket.1.exit
306
 
307
;        DEBUGF  1, "K : tcp_rx - 1.dport: %x - %x\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4
308
 
1196 hidnplayr 309
	mov	ax, [edx + TCP_Packet.DestinationPort]	; get the dest. port from the TCP hdr
1159 hidnplayr 310
	cmp	[ebx + SOCKET.LocalPort], ax		; get the dest. port from the TCP hdr
311
	jne	.next_socket.1				; different - try next socket
312
 
313
;        DEBUGF  1, "K : tcp_rx - 1.addr: %x - %x\n", [edx + IP_Packet.SourceAddress], [ebx + SOCKET.RemoteIP]
314
 
1196 hidnplayr 315
	mov	eax, esi ;[edx + IP_Packet.SourceAddress]    ; get the source IP Addr from the IP hdr
1159 hidnplayr 316
	cmp	[ebx + SOCKET.RemoteIP], eax		; compare with socket's remote IP
317
	jne	.next_socket.1				; different - try next socket
318
 
319
;        DEBUGF  1, "K : tcp_rx - 1.sport: %x - %x\n", [edx + 20 + TCP_Packet.SourcePort]:4, [ebx + SOCKET.RemotePort]:4
320
 
1196 hidnplayr 321
	mov	ax, [edx + TCP_Packet.SourcePort]  ; get the source port from the TCP hdr
1159 hidnplayr 322
	cmp	[ebx + SOCKET.RemotePort], ax		; compare with socket's remote port
323
	jne	.next_socket.1				; different - try next socket
324
 
325
	; We have a complete match - use this socket
326
	jmp	.change_state
327
 
328
  .next_socket.1.exit:
329
 
330
	; If we got here, there was no match
331
	; Look for a socket where
332
	; IP Packet TCP Destination Port = local Port
333
	; IP Packet SA = Remote IP
334
	; socket remote Port = 0
335
 
336
	mov	ebx, net_sockets
337
 
338
  .next_socket.2:
339
	mov	ebx, [ebx + SOCKET.NextPtr]
340
	or	ebx, ebx
341
	jz	.next_socket.2.exit
342
 
343
;        DEBUGF  1, "K : tcp_rx - 2.dport: %x - %x\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4
344
 
1196 hidnplayr 345
	mov	ax, [edx + TCP_Packet.DestinationPort]	; get the dest. port from the TCP hdr
1159 hidnplayr 346
	cmp	[ebx + SOCKET.LocalPort], ax		; compare with socket's local port
347
	jne	.next_socket.2				; different - try next socket
348
 
349
;        DEBUGF  1, "K : tcp_rx - 2.addr: %x - %x\n", [edx + IP_Packet.SourceAddress], [ebx + SOCKET.RemoteIP]
350
 
1196 hidnplayr 351
;        mov     eax, esi ;[edx + IP_Packet.SourceAddress]    ; get the source IP Addr from the IP hdr
352
	cmp	[ebx + SOCKET.RemoteIP], esi		; compare with socket's remote IP
1159 hidnplayr 353
	jne	.next_socket.2				; different - try next socket
354
 
355
;        DEBUGF  1, "K : tcp_rx - 2.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4
356
 
357
	cmp	[ebx + SOCKET.RemotePort], 0		; only match a remote socket of 0
358
	jne	.next_socket.2				; different - try next socket
359
 
360
	; We have a complete match - use this socket
361
	jmp	.change_state
362
 
363
  .next_socket.2.exit:
364
 
365
	; If we got here, there was no match
366
	; Look for a socket where
367
	; IP Packet TCP Destination Port = local Port
368
	; socket Remote IP = 0
369
	; socket remote Port = 0
370
 
371
	mov	ebx, net_sockets
372
 
373
  .next_socket.3:
374
	mov	ebx, [ebx + SOCKET.NextPtr]
375
	or	ebx, ebx
376
	jz	.next_socket.3.exit
377
 
378
;        DEBUGF  1, "K : tcp_rx - 3.dport: %x - %x\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4
379
 
1196 hidnplayr 380
	mov	ax, [edx + TCP_Packet.DestinationPort]	; get destination port from the TCP hdr
1159 hidnplayr 381
	cmp	[ebx + SOCKET.LocalPort], ax		; compare with socket's local port
382
	jne	.next_socket.3				; different - try next socket
383
 
384
;        DEBUGF  1, "K : tcp_rx - 3.addr: 00000000 - %x\n", [ebx + SOCKET.RemoteIP]
385
 
386
	cmp	[ebx + SOCKET.RemoteIP], 0		; only match a socket remote IP of 0
387
	jne	.next_socket.3				; different - try next socket
388
 
389
;        DEBUGF  1, "K : tcp_rx - 3.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4
390
 
391
	cmp	[ebx + SOCKET.RemotePort], 0		; only match a remote socket of 0
392
	jne	.next_socket.3				; different - try next socket
393
 
394
	; We have a complete match - use this socket
395
	jmp	.change_state
396
 
397
  .next_socket.3.exit:
398
 
399
	; If we got here, we need to reject the Packet
400
 
401
	DEBUGF	1, "K : tcp_rx - dumped\n"
1196 hidnplayr 402
;        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
1159 hidnplayr 403
 
1196 hidnplayr 404
;        inc     [dumped_rx_count]
1159 hidnplayr 405
	jmp	.exit
406
 
407
  .change_state:
408
 
409
	; We have a valid socket/TCB, so call the TCB State Machine for that skt.
410
	; socket is pointed to by ebx
411
	; IP Packet is pointed to by edx
412
	; IP buffer number is on stack ( it will be popped at the end)
413
 
414
	stdcall tcpStateMachine, ebx
415
 
416
  .exit:
417
 
1196 hidnplayr 418
	call	kernel_free
419
	add	esp, 4 ; pop (balance stack)
1159 hidnplayr 420
 
1196 hidnplayr 421
ret
422
 
423
 
424
 
425
;-----------------------------------------------------------------
426
;
427
; IN: eax = dest ip
428
;     ebx = source ip
429
;     ecx = data length
430
;     edx = remote port shl 16 + local port
431
;     esi = data offset
432
;
433
;-----------------------------------------------------------------
434
 
435
TCP_create_Packet:
436
 
437
	DEBUGF 1,"Create TCP Packet\n"
1159 hidnplayr 438
;***************************************************************************
439
;   Function
440
;      buildTCPPacket
441
;
442
;   Description
443
;       builds an IP Packet with TCP data fully populated for transmission
444
;       You may destroy any and all registers
445
;          TCP control flags specified in bl
446
;          This TCB is in [sktAddr]
447
;          User data pointed to by esi
448
;       Data length in ecx
449
;          Transmit buffer number in eax
450
;
451
;***************************************************************************
452
 
453
	push	ecx			   ; Save data length
454
 
1196 hidnplayr 455
	add	ecx, UDP_Packet.Data
456
	mov	di , IP_PROTO_UDP
1159 hidnplayr 457
 
1196 hidnplayr 458
;       dx  = fragment id
1159 hidnplayr 459
 
1196 hidnplayr 460
	call	IPv4_create_Packet				; TODO: figure out a way to choose between IPv4 and IPv6
461
	cmp	edi, -1
462
	je	.exit
1159 hidnplayr 463
 
1196 hidnplayr 464
	mov	[edi + TCP_Packet.Flags], bl		   ; TCP flags
1159 hidnplayr 465
 
1196 hidnplayr 466
;        mov     ebx, [sockAddr];---------------------------------------------------------- eof
467
 
1159 hidnplayr 468
	; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
469
 
470
	; Fill in the IP header ( some data is in the socket descriptor)
471
	mov	eax, [ebx + SOCKET.LocalIP]
1196 hidnplayr 472
;        mov     [edx + IP_Packet.SourceAddress], eax
1159 hidnplayr 473
	mov	eax, [ebx + SOCKET.RemoteIP]
1196 hidnplayr 474
;        mov     [edx + IP_Packet.DestinationAddress], eax
1159 hidnplayr 475
 
1196 hidnplayr 476
;        mov     [edx + IP_Packet.VersionAndIHL], 0x45
477
;        mov     [edx + IP_Packet.TypeOfService], 0
1159 hidnplayr 478
 
479
	pop	eax		      ; Get the TCP data length
480
	push	eax
481
 
482
	add	eax, 20 + 20	       ; add IP header and TCP header lengths
483
	rol	ax, 8
1196 hidnplayr 484
;        mov     [edx + IP_Packet.TotalLength], ax
485
;        mov     [edx + IP_Packet.Identification], 0
486
;        mov     [edx + IP_Packet.FlagsAndFragmentOffset], 0x0040
487
;        mov     [edx + IP_Packet.TimeToLive], 0x20
488
;        mov     [edx + IP_Packet.Protocol], PROTOCOL_TCP
1159 hidnplayr 489
 
490
	; Checksum left unfilled
1196 hidnplayr 491
;        mov     [edx + IP_Packet.HeaderChecksum], 0
1159 hidnplayr 492
 
493
	; Fill in the TCP header (some data is in the socket descriptor)
494
	mov	ax, [ebx + SOCKET.LocalPort]
495
	mov	[edx + 20 + TCP_Packet.SourcePort], ax		; Local Port
496
 
497
	mov	ax, [ebx + SOCKET.RemotePort]
498
	mov	[edx + 20 + TCP_Packet.DestinationPort], ax	; desitination Port
499
 
500
	; Checksum left unfilled
501
	mov	[edx + 20 + TCP_Packet.Checksum], 0
502
 
503
	; sequence number
504
	mov	eax, [ebx + SOCKET.SND_NXT]
505
	mov	[edx + 20 + TCP_Packet.SequenceNumber], eax
506
 
507
	; ack number
508
	mov	eax, [ebx + SOCKET.RCV_NXT]
509
	mov	[edx + 20 + TCP_Packet.AckNumber], eax
510
 
511
	; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size)
512
	; 768 bytes seems better
513
	mov	[edx + 20 + TCP_Packet.Window], 0x0003
514
 
515
	; Urgent pointer (0)
516
	mov	[edx + 20 + TCP_Packet.UrgentPointer], 0
517
 
518
	; data offset ( 0x50 )
519
	mov	[edx + 20 + TCP_Packet.DataOffset], 0x50
520
 
521
	pop	ecx		     ; count of bytes to send
522
	mov	ebx, ecx	    ; need the length later
523
 
524
	cmp	ebx, 0
525
	jz	@f
526
 
527
	mov	edi, edx
528
	add	edi, 40
529
	cld
530
	rep	movsb		    ; copy the data across
531
 
532
    @@: ; we have edx as IPbuffer ptr.
533
	; Fill in the TCP checksum
534
	; First, fill in pseudoheader
1196 hidnplayr 535
;        mov     eax, [edx + IP_Packet.SourceAddress]
536
;        mov     [pseudoHeader], eax
537
;        mov     eax, [edx + IP_Packet.DestinationAddress]
538
;        mov     [pseudoHeader + 4], eax
539
;        mov     word[pseudoHeader + 8], PROTOCOL_TCP shl 8 + 0
540
;        add     ebx, 20
541
;        mov     [pseudoHeader + 10], bh
542
;        mov     [pseudoHeader + 11], bl
543
;
544
;        mov     eax, pseudoHeader
545
;        mov     [checkAdd1], eax
546
;        mov     word[checkSize1], 12
547
;        mov     eax, edx
548
;        add     eax, 20
549
;        mov     [checkAdd2], eax
550
;        mov     eax, ebx
551
;        mov     [checkSize2], ax
552
;
553
;        call    checksum
1159 hidnplayr 554
 
555
	; store it in the TCP checksum ( in the correct order! )
1196 hidnplayr 556
;        mov     ax, [checkResult]
557
;        rol     ax, 8
558
;        mov     [edx + 20 + TCP_Packet.Checksum], ax
1159 hidnplayr 559
 
560
	; Fill in the IP header checksum
1196 hidnplayr 561
;    movzx   eax, byte [edx + IP_Packet.VersionAndIHL]  ; Calculate Header length by using IHL field
562
;    and     eax, 0x0000000F  ;
563
;    shl     eax, 2           ;
564
;
1159 hidnplayr 565
	stdcall checksum_jb, edx, eax  ; buf_ptr, buf_size
566
	rol	ax, 8
1196 hidnplayr 567
;        mov     [edx + IP_Packet.HeaderChecksum], ax
1159 hidnplayr 568
 
1196 hidnplayr 569
 
570
       .exit:
571
 
572
	call	kernel_free
573
	add	esp, 4 ; pop (balance stack)
574
 
1159 hidnplayr 575
	ret
1196 hidnplayr 576
;endp
1159 hidnplayr 577
 
578
 
579
; Increments the 32 bit value pointed to by esi in internet order
580
proc inc_inet_esi stdcall
1196 hidnplayr 581
;        push    eax
582
;        mov     eax, [esi]
583
;        bswap   eax
584
;        inc     eax
585
;        bswap   eax
586
;        mov     [esi], eax
587
;        pop     eax
588
;        ret
589
	inc	byte[esi+0]
590
	adc	byte[esi+1],0
591
	adc	byte[esi+2],0
592
	adc	byte[esi+3],0
1159 hidnplayr 593
endp
594
 
595
 
596
; Increments the 32 bit value pointed to by esi in internet order
597
; by the value in ecx
598
proc add_inet_esi stdcall
599
	push	eax
600
	mov	eax, [esi]
601
	bswap	eax
602
	add	eax, ecx
603
	bswap	eax
604
	mov	[esi], eax
605
	pop	eax
606
	ret
607
endp
608
 
609
 
610
iglobal
611
  TCBStateHandler dd \
612
    stateTCB_LISTEN, \
613
    stateTCB_SYN_SENT, \
614
    stateTCB_SYN_RECEIVED, \
615
    stateTCB_ESTABLISHED, \
616
    stateTCB_FIN_WAIT_1, \
617
    stateTCB_FIN_WAIT_2, \
618
    stateTCB_CLOSE_WAIT, \
619
    stateTCB_CLOSING, \
620
    stateTCB_LAST_ACK, \
621
    stateTCB_TIME_WAIT, \
622
    stateTCB_CLOSED
623
endg
624
 
625
 
626
;***************************************************************************
627
;   Function
628
;      tcpStateMachine
629
;
630
;   Description
631
;       TCP state machine
632
;       This is a kernel function, called by tcp_rx
633
;
634
;       IP buffer address given in edx
635
;          Socket/TCB address in ebx
636
;
637
;       The IP buffer will be released by the caller
638
;***************************************************************************
639
 
640
proc tcpStateMachine stdcall, sockAddr:DWORD
641
	; as a Packet has been received, update the TCB timer
642
	mov	[ebx + SOCKET.TCBTimer], TWOMSL
643
 
644
	; If the received Packet has an ACK bit set,
645
	; remove any Packets in the resend queue that this
646
	; received Packet acknowledges
647
	pushad
648
	test	[edx + 20 + TCP_Packet.Flags], TH_ACK
649
	jz	.call_handler					; No ACK, so no data yet
650
 
651
	; get skt number in eax
652
	stdcall net_socket_addr_to_num, ebx
653
 
654
	; The ack number is in [edx + 28], inet format
655
	; skt in eax
656
 
657
	mov	esi, resendQ
658
	xor	ecx, ecx
659
 
660
  .next_resendq:
1196 hidnplayr 661
;        cmp     ecx, NUMRESENDENTRIES
1159 hidnplayr 662
	je	.call_handler	  ; None left
663
	cmp	[esi + 4], eax
664
	je	@f		  ; found one
665
	inc	ecx
666
	add	esi, 8
667
	jmp	.next_resendq
668
 
669
    @@: 		  ; Can we delete this buffer?
670
 
671
			  ; If yes, goto @@. No, goto .next_resendq
672
	; Get Packet data address
673
 
674
	push	ecx
675
	; Now get buffer location, and copy buffer across. argh! more copying,,
1196 hidnplayr 676
;        imul    edi, ecx, IPBUFFSIZE
677
;        add     edi, resendBuffer
1159 hidnplayr 678
 
679
	; we have dest buffer location in edi. incoming Packet in edx.
680
	; Get this Packets sequence number
681
	; preserve al, ecx, esi, edx
682
	mov	ecx, [edi + 20 + TCP_Packet.SequenceNumber]
683
	bswap	ecx
684
	movzx	ebx, word[edi + 2]
685
	xchg	bl, bh
686
	sub	ebx, 40
687
	add	ecx, ebx	  ; ecx is now seq# of last byte +1, intel format
688
 
689
	; get recievd ack #, in intel format
690
	mov	ebx, [edx + 20 + TCP_Packet.AckNumber]
691
	bswap	ebx
692
 
693
	cmp	ebx, ecx	; Finally. ecx = rx'ed ack. ebx = last byte in que
694
				; DANGER! need to handle case that we have just
695
				; passed the 2**32, and wrapped round!
696
	pop	ecx
697
	jae	@f		; if rx > old, delete old
698
 
699
	inc	ecx
700
	add	esi, 8
701
	jmp	.next_resendq
702
 
703
    @@: mov	dword[esi + 4], 0
704
	inc	ecx
705
	add	esi, 8
706
	jmp	.next_resendq
707
 
708
  .call_handler:
709
	popad
710
 
711
	; Call handler for given TCB state
712
 
713
	mov	eax, [ebx + SOCKET.TCBState]
714
	cmp	eax, TCB_LISTEN
715
	jb	.exit
716
	cmp	eax, TCB_CLOSED
717
	ja	.exit
718
 
719
	stdcall [TCBStateHandler + (eax - 1) * 4], [sockAddr]
720
 
721
  .exit:
722
	ret
723
endp
724
 
725
 
726
proc stateTCB_LISTEN stdcall, sockAddr:DWORD
727
	; In this case, we are expecting a SYN Packet
728
	; For now, if the Packet is a SYN, process it, and send a response
729
	; If not, ignore it
730
 
731
	; Look at control flags
732
	test	[edx + 20 + TCP_Packet.Flags], TH_SYN
733
	jz	.exit
734
 
735
	; We have a SYN. update the socket with this IP Packets details,
736
	; And send a response
737
 
1196 hidnplayr 738
;        mov     eax, [edx + IP_Packet.SourceAddress]
739
 ;       mov     [ebx + SOCKET.RemoteIP], eax
740
;        mov     ax, [edx + 20 + TCP_Packet.SourcePort]
741
;        mov     [ebx + SOCKET.RemotePort], ax
742
;        mov     eax, [edx + 20 + TCP_Packet.SequenceNumber]
743
;        mov     [ebx + SOCKET.IRS], eax
744
;        mov     [ebx + SOCKET.RCV_NXT], eax
745
;        lea     esi, [ebx + SOCKET.RCV_NXT]
746
;        call    inc_inet_esi ; RCV.NXT
747
;        mov     eax, [ebx + SOCKET.ISS]
748
;        mov     [ebx + SOCKET.SND_NXT], eax
749
;
1159 hidnplayr 750
	; Now construct the response, and queue for sending by IP
1196 hidnplayr 751
;        mov     eax, EMPTY_QUEUE
752
;        call    dequeue
753
;        cmp     ax, NO_BUFFER
754
 ;       je      .exit
1159 hidnplayr 755
 
756
	push	eax
757
	mov	bl, TH_SYN + TH_ACK
758
	xor	ecx, ecx
759
	xor	esi, esi
1196 hidnplayr 760
;        stdcall build_tcp_Packet, [sockAddr]
1159 hidnplayr 761
 
1196 hidnplayr 762
;        mov     eax, NET1OUT_QUEUE
1159 hidnplayr 763
;;;        mov     edx, [stack_ip]
764
	mov	ecx, [sockAddr]
765
	cmp	edx, [ecx + SOCKET.RemoteIP]
766
	jne	.not_local
1196 hidnplayr 767
;        mov     eax, IPIN_QUEUE
1159 hidnplayr 768
 
769
  .not_local:
770
	; Send it.
771
	pop	ebx
1196 hidnplayr 772
;;;        call    queue
1159 hidnplayr 773
 
774
	mov	esi, [sockAddr]
775
	mov	[esi + SOCKET.TCBState], TCB_SYN_RECEIVED
776
 
777
	; increment SND.NXT in socket
778
	add	esi, SOCKET.SND_NXT
779
	call	inc_inet_esi
780
 
781
  .exit:
782
	ret
783
endp
784
 
785
 
786
proc stateTCB_SYN_SENT stdcall, sockAddr:DWORD
787
	; We are awaiting an ACK to our SYN, with a SYM
788
	; Look at control flags - expecting an ACK
789
 
790
	mov	al, [edx + 20 + TCP_Packet.Flags]
791
	and	al, TH_SYN + TH_ACK
792
	cmp	al, TH_SYN + TH_ACK
793
	je	.syn_ack
794
 
795
	test	al, TH_SYN
796
	jz	.exit
797
 
798
	mov	[ebx + SOCKET.TCBState], TCB_SYN_RECEIVED
799
	push	TH_SYN + TH_ACK
800
	jmp	.send
801
 
802
  .syn_ack:
803
	mov	[ebx + SOCKET.TCBState], TCB_ESTABLISHED
804
	push	TH_ACK
805
 
806
  .send:
807
	; Store the recv.nxt field
808
	mov	eax, [edx + 20 + TCP_Packet.SequenceNumber]
809
 
810
	; Update our recv.nxt field
811
	mov	[ebx + SOCKET.RCV_NXT], eax
812
	lea	esi, [ebx + SOCKET.RCV_NXT]
813
	call	inc_inet_esi
814
 
815
	; Send an ACK
816
	; Now construct the response, and queue for sending by IP
1196 hidnplayr 817
;        mov     eax, EMPTY_QUEUE
818
;        call    dequeue
819
 ;       cmp     ax, NO_BUFFER
1159 hidnplayr 820
	pop	ebx
821
	je	.exit
822
 
823
	push	eax
824
 
825
	xor	ecx, ecx
826
	xor	esi, esi
1196 hidnplayr 827
;        stdcall build_tcp_Packet, [sockAddr]
1159 hidnplayr 828
 
1196 hidnplayr 829
;        mov     eax, NET1OUT_QUEUE
1159 hidnplayr 830
;;;        mov     edx, [stack_ip]
1196 hidnplayr 831
;        mov     ecx, [sockAddr]
832
 ;       cmp     edx, [ecx + SOCKET.RemoteIP]
833
  ;      jne     .not_local
834
   ;     mov     eax, IPIN_QUEUE
1159 hidnplayr 835
 
836
  .not_local:
837
	; Send it.
838
	pop	ebx
1196 hidnplayr 839
;;;        call    queue
1159 hidnplayr 840
 
841
  .exit:
842
	ret
843
endp
844
 
845
 
846
proc stateTCB_SYN_RECEIVED stdcall, sockAddr:DWORD
847
	; In this case, we are expecting an ACK Packet
848
	; For now, if the Packet is an ACK, process it,
849
	; If not, ignore it
850
 
851
	test	[edx + 20 + TCP_Packet.Flags], TH_RST
852
	jz	.check_ack
853
 
854
	push	[ebx + SOCKET.OrigRemotePort] [ebx + SOCKET.OrigRemoteIP]
855
	pop	[ebx + SOCKET.RemoteIP] [ebx + SOCKET.RemotePort]
856
 
857
	mov	[ebx + SOCKET.TCBState], TCB_LISTEN
858
	jmp	.exit
859
 
860
  .check_ack:
861
	; Look at control flags - expecting an ACK
862
	test	[edx + 20 + TCP_Packet.Flags], TH_ACK
863
	jz	.exit
864
 
865
	mov	[ebx + SOCKET.TCBState], TCB_ESTABLISHED
866
 
867
  .exit:
868
	ret
869
endp
870
 
871
 
872
proc stateTCB_ESTABLISHED stdcall, sockAddr:DWORD
873
	; Here we are expecting data, or a request to close
874
	; OR both...
875
 
876
	; Did we receive a FIN or RST?
877
	test	[edx + 20 + TCP_Packet.Flags], TH_FIN
878
	jz	.check_ack
879
 
880
	; It was a fin or reset.
881
 
882
	; Remove resend entries from the queue  - I dont want to send any more data
883
	pushad
884
 
885
	; get skt #
886
	stdcall net_socket_addr_to_num, ebx
887
 
888
	mov	esi, resendQ
889
	mov	ecx, 0
890
 
891
  .next_resendq:
1196 hidnplayr 892
;        cmp     ecx, NUMRESENDENTRIES
893
;        je      .last_resendq       ; None left
894
;        cmp     [esi + 4], eax
895
;        je      @f                  ; found one
896
;        inc     ecx
897
;        add     esi, 8
898
;        jmp     .next_resendq
1159 hidnplayr 899
 
900
    @@: mov	dword[esi + 4], 0
901
	inc	ecx
902
	add	esi, 8
903
	jmp	.next_resendq
904
 
905
  .last_resendq:
906
	popad
907
 
908
    @@: ; Send an ACK to that fin, and enter closewait state
909
 
910
	mov	[ebx + SOCKET.TCBState], TCB_CLOSE_WAIT
911
	lea	esi, [ebx + SOCKET.RCV_NXT]
912
	mov	eax, [esi]		; save original
913
	call	inc_inet_esi
914
	;; jmp    ste_ack - NO, there may be data
915
 
916
  .check_ack:
917
	; Check that we received an ACK
918
	test	[edx + 20 + TCP_Packet.Flags], TH_ACK
919
	jz	.exit
920
 
921
	; TODO - done, I think!
922
	; First, look at the incoming window. If this is less than or equal to 1024,
923
	; Set the socket window timer to 1. This will stop an additional Packets being queued.
924
	; ** I may need to tweak this value, since I do not know how many Packets are already queued
925
	mov	cx, [edx + 20 + TCP_Packet.Window]
926
	xchg	cl, ch
927
	cmp	cx, 1024
928
	ja	@f
929
 
930
	mov	[ebx + SOCKET.wndsizeTimer], 1
931
 
932
    @@: ; OK, here is the deal
933
	; My recv.nct field holds the seq of the expected next rec byte
934
	; if the recevied sequence number is not equal to this, do not
935
	; increment the recv.nxt field, do not copy data - just send a
936
	; repeat ack.
937
 
938
	; recv.nxt is in dword [edx+24], in inet format
939
	; recv seq is in [sktAddr]+56, in inet format
940
	; just do a comparision
941
	mov	ecx, [ebx + SOCKET.RCV_NXT]
942
	cmp	[ebx + SOCKET.TCBState], TCB_CLOSE_WAIT
943
	jne	@f
944
	mov	ecx, eax
945
 
946
    @@: cmp	ecx, [edx + 20 + TCP_Packet.SequenceNumber]
947
	jne	.ack
948
 
949
 
950
	; Read the data bytes, store in socket buffer
1196 hidnplayr 951
;        movzx   ecx, [edx + IP_Packet.TotalLength]
1159 hidnplayr 952
	xchg	cl, ch
953
	sub	ecx, 40 		   ; Discard 40 bytes of header
954
	ja	.data			   ; Read data, if any
955
 
956
	; If we had received a fin, we need to ACK it.
957
	cmp	[ebx + SOCKET.TCBState], TCB_CLOSE_WAIT
958
	je	.ack
959
	jmp	.exit
960
 
961
  .data:
962
	push	ebx
963
	add	ebx, SOCKET.lock
964
	call	wait_mutex
965
	pop	ebx
966
 
967
	push	ecx
968
	push	[ebx + SOCKET.PID]	; get socket owner PID
969
	mov	eax, [ebx + SOCKET.rxDataCount]
970
	add	eax, ecx
971
	cmp	eax, SOCKETBUFFSIZE - SOCKETHEADERSIZE
972
	ja	.overflow
973
 
974
	mov	[ebx + SOCKET.rxDataCount], eax      ; increment the count of bytes in buffer
975
 
976
	; point to the location to store the data
977
	lea	edi, [ebx + eax + SOCKETHEADERSIZE]
978
	sub	edi, ecx
979
 
980
	add	edx, 40        ; edx now points to the data
981
	mov	esi, edx
982
 
983
	cld
984
	rep	movsb	       ; copy the data across
985
	mov	[ebx + SOCKET.lock], 0	; release mutex
986
 
987
	; flag an event to the application
988
	pop	eax
989
	mov	ecx, 1
990
	mov	esi, TASK_DATA + TASKDATA.pid
991
 
992
  .next_pid:
993
	cmp	[esi], eax
994
	je	.found_pid
995
	inc	ecx
996
	add	esi, 0x20
997
	cmp	ecx, [TASK_COUNT]
998
	jbe	.next_pid
999
 
1000
  .found_pid:
1001
	shl	ecx, 8
1002
	or	[ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event
1003
 
1004
	pop	ecx
1005
 
1006
	; Update our recv.nxt field
1007
	lea	esi, [ebx + SOCKET.RCV_NXT]
1008
	call	add_inet_esi
1009
 
1010
  .ack:
1011
	; Send an ACK
1012
	; Now construct the response, and queue for sending by IP
1196 hidnplayr 1013
;        mov     eax, EMPTY_QUEUE
1014
;        call    dequeue
1015
;        cmp     ax, NO_BUFFER
1159 hidnplayr 1016
	je	.exit
1017
 
1018
	push	eax
1019
 
1020
	mov	bl, TH_ACK
1021
	xor	ecx, ecx
1022
	xor	esi, esi
1196 hidnplayr 1023
;        stdcall build_tcp_Packet, [sockAddr]
1159 hidnplayr 1024
 
1196 hidnplayr 1025
;        mov     eax, NET1OUT_QUEUE
1159 hidnplayr 1026
 
1027
;;;        mov     edx, [stack_ip]
1196 hidnplayr 1028
;        mov     ecx, [sockAddr]
1029
;        cmp     edx, [ecx + SOCKET.RemoteIP]
1030
;        jne     .not_local
1031
 ;       mov     eax, IPIN_QUEUE
1159 hidnplayr 1032
 
1033
  .not_local:
1034
	; Send it.
1035
	pop	ebx
1196 hidnplayr 1036
;;;        call    queue
1159 hidnplayr 1037
 
1038
  .exit:
1039
	ret
1040
  .overflow:
1041
	; no place in buffer
1042
	; so simply restore stack and exit
1043
	pop	eax ecx
1044
	mov	[ebx + SOCKET.lock], 0
1045
	ret
1046
endp
1047
 
1048
 
1049
proc stateTCB_FIN_WAIT_1 stdcall, sockAddr:DWORD
1050
	; We can either receive an ACK of a fin, or a fin
1051
	mov	al, [edx + 20 + TCP_Packet.Flags]
1052
	and	al, TH_FIN + TH_ACK
1053
 
1054
	cmp	al, TH_ACK
1055
	jne	@f
1056
 
1057
	; It was an ACK
1058
	mov	[ebx + SOCKET.TCBState], TCB_FIN_WAIT_2
1059
	jmp	.exit
1060
 
1061
    @@: mov	[ebx + SOCKET.TCBState], TCB_CLOSING
1062
	cmp	al, TH_FIN
1063
	je	@f
1064
	mov	[ebx + SOCKET.TCBState], TCB_TIMED_WAIT
1065
 
1066
    @@: lea	esi, [ebx + SOCKET.RCV_NXT]
1067
	call	inc_inet_esi
1068
 
1069
	; Send an ACK
1196 hidnplayr 1070
;        mov     eax, EMPTY_QUEUE
1071
;        call    dequeue
1072
;        cmp     ax, NO_BUFFER
1159 hidnplayr 1073
	je	.exit
1074
 
1075
	push	eax
1076
 
1077
	mov	bl, TH_ACK
1078
	xor	ecx, ecx
1079
	xor	esi, esi
1196 hidnplayr 1080
;        stdcall build_tcp_Packet, [sockAddr]
1159 hidnplayr 1081
 
1196 hidnplayr 1082
;        mov     eax, NET1OUT_QUEUE
1159 hidnplayr 1083
;;;        mov     edx, [stack_ip]
1196 hidnplayr 1084
;        mov     ecx, [sockAddr]
1085
 ;       cmp     edx, [ecx + SOCKET.RemoteIP]
1086
 ;       jne     .not_local
1087
;        mov     eax, IPIN_QUEUE
1159 hidnplayr 1088
 
1089
  .not_local:
1090
	; Send it.
1091
	pop	ebx
1196 hidnplayr 1092
;;;        call    queue
1159 hidnplayr 1093
 
1094
  .exit:
1095
	ret
1096
endp
1097
 
1098
 
1099
proc stateTCB_FIN_WAIT_2 stdcall, sockAddr:DWORD
1100
	test	[edx + 20 + TCP_Packet.Flags], TH_FIN
1101
	jz	.exit
1102
 
1103
	; Change state, as we have a fin
1104
	mov	[ebx + SOCKET.TCBState], TCB_TIMED_WAIT
1105
 
1106
	lea	esi, [ebx + SOCKET.RCV_NXT]
1107
	call	inc_inet_esi
1108
 
1109
	; Send an ACK
1196 hidnplayr 1110
;        mov     eax, EMPTY_QUEUE
1111
;        call    dequeue
1112
 ;;       cmp     ax, NO_BUFFER
1113
  ;      je      .exit
1159 hidnplayr 1114
 
1115
	push	eax
1116
 
1117
	mov	bl, TH_ACK
1118
	xor	ecx, ecx
1119
	xor	esi, esi
1196 hidnplayr 1120
;        stdcall build_tcp_Packet, [sockAddr]
1159 hidnplayr 1121
 
1196 hidnplayr 1122
;        mov     eax, NET1OUT_QUEUE
1159 hidnplayr 1123
;;;        mov     edx, [stack_ip]
1124
	mov	ecx, [sockAddr]
1125
	cmp	edx, [ecx + SOCKET.RemoteIP]
1126
	jne	.not_local
1196 hidnplayr 1127
;        mov     eax, IPIN_QUEUE
1159 hidnplayr 1128
 
1129
  .not_local:
1130
	; Send it.
1131
	pop	ebx
1196 hidnplayr 1132
;;;        call    queue
1159 hidnplayr 1133
 
1134
  .exit:
1135
	ret
1136
endp
1137
 
1138
 
1139
proc stateTCB_CLOSE_WAIT stdcall, sockAddr:DWORD
1140
	; Intentionally left empty
1141
	; socket_close_tcp handles this
1142
	ret
1143
endp
1144
 
1145
 
1146
proc stateTCB_CLOSING stdcall, sockAddr:DWORD
1147
	; We can either receive an ACK of a fin, or a fin
1148
	test	[edx + 20 + TCP_Packet.Flags], TH_ACK
1149
	jz	.exit
1150
 
1151
	mov	[ebx + SOCKET.TCBState], TCB_TIMED_WAIT
1152
 
1153
  .exit:
1154
	ret
1155
endp
1156
 
1157
 
1158
proc stateTCB_LAST_ACK stdcall, sockAddr:DWORD
1159
	; Look at control flags - expecting an ACK
1160
	test	[edx + 20 + TCP_Packet.Flags], TH_ACK
1161
	jz	.exit
1162
 
1163
	; delete the socket
1164
	stdcall net_socket_free, ebx
1165
 
1166
  .exit:
1167
	ret
1168
endp
1169
 
1170
 
1171
proc stateTCB_TIME_WAIT stdcall, sockAddr:DWORD
1172
	ret
1173
endp
1174
 
1175
 
1176
proc stateTCB_CLOSED stdcall, sockAddr:DWORD
1177
	ret
1178
endp
1179
 
1180
 
1181
 
1182
;; [53.7] Send data through STREAM socket
1183
;
1184
; @param EBX is socket number
1185
; @param ECX is application data size (number of bytes to send)
1186
; @param EDX is pointer to application data buffer
1187
; @return 0 (sent successfully) or -1 (error) in EAX
1188
;;
1196 hidnplayr 1189
;proc socket_write_tcp stdcall
1190
;local sockAddr dd ?
1159 hidnplayr 1191
 
1192
;        DEBUGF  1, "socket_write_tcp(0x%x)\n", ebx
1193
	stdcall net_socket_num_to_addr, ebx
1194
	or	eax, eax
1195
	jz	.error
1196
 
1197
	mov	ebx, eax
1196 hidnplayr 1198
;        mov     [sockAddr], ebx
1159 hidnplayr 1199
 
1200
	; If the sockets window timer is nonzero, do not queue Packet
1201
	cmp	[ebx + SOCKET.wndsizeTimer], 0
1202
	jne	.error
1203
 
1196 hidnplayr 1204
;        mov     eax, EMPTY_QUEUE
1205
;        call    dequeue
1206
;        cmp     ax, NO_BUFFER
1207
 ;       je      .error
1159 hidnplayr 1208
 
1209
	push	eax
1210
 
1211
	; Get the address of the callers data
1212
	mov	edi, [TASK_BASE]
1213
	add	edi, TASKDATA.mem_start
1214
	add	edx, [edi]
1215
	mov	esi, edx
1216
 
1217
	pop	eax
1218
	push	eax
1219
 
1220
	push	ecx
1221
	mov	bl, TH_ACK
1196 hidnplayr 1222
;        stdcall build_tcp_Packet, [sockAddr]
1159 hidnplayr 1223
	pop	ecx
1224
 
1225
	; Check destination IP address.
1226
	; If it is the local host IP, route it back to IP_RX
1227
 
1228
	pop	ebx
1229
	push	ecx
1230
 
1196 hidnplayr 1231
;        mov     eax, NET1OUT_QUEUE
1159 hidnplayr 1232
;;; TODO: get device id in edx
1233
	xor	edx, edx
1234
 
1235
	shl	edx, 2
1236
	mov	edx, [IP_LIST+edx]
1196 hidnplayr 1237
;        mov     ecx, [sockAddr]
1238
 ;       cmp     edx, [ecx + SOCKET.RemoteIP]
1239
  ;      jne     .not_local
1240
   ;     mov     eax, IPIN_QUEUE
1159 hidnplayr 1241
 
1242
  .not_local:
1243
	pop	ecx
1244
	push	ebx		    ; save ipbuffer number
1245
 
1196 hidnplayr 1246
;;;;        call    queue
1159 hidnplayr 1247
 
1196 hidnplayr 1248
;        mov     esi, [sockAddr]
1159 hidnplayr 1249
 
1250
	; increament SND.NXT in socket
1251
	; Amount to increment by is in ecx
1252
	add	esi, SOCKET.SND_NXT
1253
	call	add_inet_esi
1254
 
1255
	pop	ebx
1256
 
1257
	; Copy the IP buffer to a resend queue
1258
	; If there isn't one, dont worry about it for now
1259
	mov	esi, resendQ
1260
	mov	ecx, 0
1261
 
1262
  .next_resendq:
1196 hidnplayr 1263
;        cmp     ecx, NUMRESENDENTRIES
1159 hidnplayr 1264
	je	.exit		   ; None found
1265
	cmp	dword[esi + 4], 0
1266
	je	@f		   ; found one
1267
	inc	ecx
1268
	add	esi, 8
1269
	jmp	.next_resendq
1270
 
1271
    @@: push	ebx
1272
 
1273
	; OK, we have a buffer descriptor ptr in esi.
1274
	; resend entry # in ecx
1275
	;  Populate it
1276
	;  socket #
1277
	;  retries count
1278
	;  retry time
1279
	;  fill IP buffer associated with this descriptor
1280
 
1196 hidnplayr 1281
;        stdcall net_socket_addr_to_num, [sockAddr]
1159 hidnplayr 1282
	mov	[esi + 4], eax
1283
	mov	byte[esi + 1], TCP_RETRIES
1284
	mov	word[esi + 2], TCP_TIMEOUT
1285
 
1286
	inc	ecx
1287
	; Now get buffer location, and copy buffer across. argh! more copying,,
1196 hidnplayr 1288
;        mov     edi, resendBuffer - IPBUFFSIZE
1159 hidnplayr 1289
 
1196 hidnplayr 1290
;    @@: add     edi, IPBUFFSIZE
1159 hidnplayr 1291
	loop	@b
1292
 
1293
	; we have dest buffer location in edi
1294
	pop	eax
1295
	; convert source buffer pointer eax to the absolute address
1196 hidnplayr 1296
;        mov     ecx, IPBUFFSIZE
1297
;        mul     ecx
1298
;        add     eax, IPbuffs
1299
;        mov     esi, eax
1159 hidnplayr 1300
 
1301
	; do copy
1196 hidnplayr 1302
;        mov     ecx, IPBUFFSIZE
1159 hidnplayr 1303
;        cld
1304
	rep	movsb
1305
 
1306
  .exit:
1307
	xor	eax, eax
1308
	ret
1309
 
1310
  .error:
1311
	or	eax, -1
1312
	ret
1196 hidnplayr 1313
;endp
1159 hidnplayr 1314
 
1315
 
1316
 
1317
;***************************************************************************
1318
;   Function
1319
;      checksum
1320
;
1321
;   Description
1322
;       checkAdd1,checkAdd2, checkSize1, checkSize2, checkResult
1323
;       Dont break anything; Most registers are used by the caller
1324
;       This code is derived from the 'C' source, cksum.c, in the book
1325
;       Internetworking with TCP/IP Volume II by D.E. Comer
1326
;
1327
;***************************************************************************
1328
 
1329
 
1330
checksum:
1331
    pusha
1196 hidnplayr 1332
;    mov     eax, [checkAdd1]
1159 hidnplayr 1333
    xor     edx, edx		      ; edx is the accumulative checksum
1334
    xor     ebx, ebx
1196 hidnplayr 1335
;    mov     cx, [checkSize1]
1159 hidnplayr 1336
    shr     cx, 1
1337
    jz	    cs1_1
1338
 
1339
cs1:
1340
    mov     bh, [eax]
1341
    mov     bl, [eax + 1]
1342
 
1343
    add     eax, 2
1344
    add     edx, ebx
1345
 
1346
    loopw   cs1
1347
 
1348
cs1_1:
1196 hidnplayr 1349
;    and     word [checkSize1], 0x01
1159 hidnplayr 1350
    jz	    cs_test2
1351
 
1352
    mov     bh, [eax]
1353
    xor     bl, bl
1354
 
1355
    add     edx, ebx
1356
 
1357
cs_test2:
1196 hidnplayr 1358
;    mov     cx, [checkSize2]
1159 hidnplayr 1359
    cmp     cx, 0
1360
    jz	    cs_exit			; Finished if no 2nd buffer
1361
 
1196 hidnplayr 1362
;    mov     eax, [checkAdd2]
1159 hidnplayr 1363
 
1364
    shr     cx, 1
1365
    jz	    cs2_1
1366
 
1367
cs2:
1368
    mov     bh, [eax]
1369
    mov     bl, [eax + 1]
1370
 
1371
    add     eax, 2
1372
    add     edx, ebx
1373
 
1374
    loopw   cs2
1375
 
1376
cs2_1:
1196 hidnplayr 1377
;    and     word [checkSize2], 0x01
1159 hidnplayr 1378
    jz	    cs_exit
1379
 
1380
    mov     bh, [eax]
1381
    xor     bl, bl
1382
 
1383
    add     edx, ebx
1384
 
1385
cs_exit:
1386
    mov     ebx, edx
1387
 
1388
    shr     ebx, 16
1389
    and     edx, 0xffff
1390
    add     edx, ebx
1391
    mov     eax, edx
1392
    shr     eax, 16
1393
    add     edx, eax
1394
    not     dx
1395
 
1196 hidnplayr 1396
;    mov     [checkResult], dx
1159 hidnplayr 1397
    popa
1398
    ret
1399