Subversion Repositories Kolibri OS

Rev

Rev 1281 | 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                           ;;
1318 hidnplayr 11
;;    Inspired by the TCP code of Mike Hibbit for MenuetOS         ;;
1196 hidnplayr 12
;;                                                                 ;;
13
;;          GNU GENERAL PUBLIC LICENSE                             ;;
14
;;             Version 2, June 1991                                ;;
15
;;                                                                 ;;
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1159 hidnplayr 17
 
1196 hidnplayr 18
 
1206 hidnplayr 19
$Revision: 1318 $
1159 hidnplayr 20
 
1196 hidnplayr 21
TCP_RETRIES		equ 5		; Number of times to resend a Packet
1254 hidnplayr 22
TCP_PACKET_TTL		equ 50		; resend if not replied to in 1/100 s
23
TCP_SOCKET_TTL		equ 10		; # of secs to wait before closing socket
1196 hidnplayr 24
TCP_QUEUE_SIZE		equ 16
25
 
1318 hidnplayr 26
TCP_MAX_ACKS		equ 16
1249 hidnplayr 27
 
1318 hidnplayr 28
 
1159 hidnplayr 29
struct	TCP_Packet
30
	.SourcePort		dw ?
31
	.DestinationPort	dw ?
32
	.SequenceNumber 	dd ?
33
	.AckNumber		dd ?
1196 hidnplayr 34
	.DataOffset		db ?	; DataOffset[0-3 bits] and Reserved[4-7]
35
	.Flags			db ?	; Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN
1159 hidnplayr 36
	.Window 		dw ?
37
	.Checksum		dw ?
38
	.UrgentPointer		dw ?
1274 hidnplayr 39
;        .Options                rb 3
40
;        .Padding                db ?
1159 hidnplayr 41
	.Data:
42
ends
43
 
1274 hidnplayr 44
struct	tcp_in_queue_entry
45
	.data_ptr	dd ?
46
	.data_size	dd ?
1281 hidnplayr 47
	.offset 	dd ?	; TODO: replace this in code by absolute address isntead of relative offset
1274 hidnplayr 48
	.size:
49
ends
50
 
51
struct	tcp_out_queue_entry
52
	.data_ptr	dd ?
53
	.data_size	dd ?
54
	.ttl		dd ?
55
	.retries	dd ?
56
	.owner		dd ?
57
	.sendproc	dd ?
58
	.seq_num	dd ?
59
	.socket 	dd ?
60
	.size:
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
 
1249 hidnplayr 68
	TCP_IN_QUEUE		rd  (tcp_in_queue_entry.size*TCP_QUEUE_SIZE+queue.data)/4
1318 hidnplayr 69
	TCP_OUT_QUEUE		dd  ?, ?
1249 hidnplayr 70
				rd  (tcp_out_queue_entry.size*TCP_QUEUE_SIZE)/4
1318 hidnplayr 71
 
72
	TCP_ACKS		dd  ?
73
	TCP_ACK_LIST		rd  3*TCP_MAX_ACKS
1196 hidnplayr 74
endg
75
 
1249 hidnplayr 76
align 4
77
iglobal
1318 hidnplayr 78
TCPstateHandler:
1196 hidnplayr 79
 
1249 hidnplayr 80
  dd  stateTCB_LISTEN
81
  dd  stateTCB_SYN_SENT
82
  dd  stateTCB_SYN_RECEIVED
83
  dd  stateTCB_ESTABLISHED
84
  dd  stateTCB_FIN_WAIT_1
85
  dd  stateTCB_FIN_WAIT_2
86
  dd  stateTCB_CLOSE_WAIT
87
  dd  stateTCB_CLOSING
88
  dd  stateTCB_LAST_ACK
89
  dd  stateTCB_TIME_WAIT
90
  dd  stateTCB_CLOSED
1196 hidnplayr 91
 
1249 hidnplayr 92
endg
1196 hidnplayr 93
 
1249 hidnplayr 94
 
1196 hidnplayr 95
;-----------------------------------------------------------------
96
;
97
; TCP_init
98
;
99
;  This function resets all TCP variables
100
;
101
;  IN:  /
102
;  OUT: /
103
;
104
;-----------------------------------------------------------------
105
align 4
106
TCP_init:
107
 
108
	xor	eax, eax
109
	mov	edi, TCP_PACKETS_TX
110
	mov	ecx, 2*MAX_IP
111
	rep	stosd
112
 
1249 hidnplayr 113
	init_queue TCP_IN_QUEUE
1196 hidnplayr 114
 
1274 hidnplayr 115
; tcp_out_queue is a special type of queue:
116
; The first dword is a counter of total packets queued.
117
; The remaining bytes are socket 'slots' wich use tcp_out_queue_entry data structure.
118
; An empty slot is know by the fact that tcp_out_queue_entry.data_ptr (first dword of the slot) is set to 0
119
; There are TCP_OUT_QUEUE_SIZE number of slots
1257 hidnplayr 120
 
1254 hidnplayr 121
	xor	eax, eax
122
	mov	esi, TCP_OUT_QUEUE
1318 hidnplayr 123
	mov	ecx, TCP_QUEUE_SIZE*tcp_out_queue_entry/4+2+2+3*TCP_MAX_ACKS
1254 hidnplayr 124
	rep	stosd
125
 
1196 hidnplayr 126
	ret
127
 
128
 
129
;-----------------------------------------------------------------
130
;
1249 hidnplayr 131
;  TCP_decrease_socket_ttls
1159 hidnplayr 132
;
1249 hidnplayr 133
;  IN:  /
134
;  OUT: /
1159 hidnplayr 135
;
1196 hidnplayr 136
;-----------------------------------------------------------------
137
align 4
1249 hidnplayr 138
TCP_decrease_socket_ttls:
1274 hidnplayr 139
; scan through all the sockets, decrementing active timers
1159 hidnplayr 140
 
141
	mov	ebx, net_sockets
142
 
1249 hidnplayr 143
	cmp	[ebx + SOCKET_head.NextPtr], 0
1159 hidnplayr 144
	je	.exit
145
 
146
  .next_socket:
1249 hidnplayr 147
	mov	ebx, [ebx + SOCKET_head.NextPtr]
1159 hidnplayr 148
	or	ebx, ebx
149
	jz	.exit
150
 
1249 hidnplayr 151
	cmp	[ebx + SOCKET_head.Type], IP_PROTO_TCP
152
	jne	.next_socket
153
 
1254 hidnplayr 154
;        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.state]
1159 hidnplayr 155
 
1254 hidnplayr 156
	cmp	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer], 0
1159 hidnplayr 157
	jne	.decrement_tcb
1249 hidnplayr 158
	cmp	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 0
1159 hidnplayr 159
	jne	.decrement_wnd
160
	jmp	.next_socket
161
 
162
  .decrement_tcb:
1274 hidnplayr 163
; decrement it, delete socket if TCB timer = 0 & socket in timewait state
1254 hidnplayr 164
	dec	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer]
1159 hidnplayr 165
	jnz	.next_socket
166
 
1254 hidnplayr 167
	cmp	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
1159 hidnplayr 168
	jne	.next_socket
169
 
1249 hidnplayr 170
	push	[ebx + SOCKET_head.PrevPtr]
1159 hidnplayr 171
	stdcall net_socket_free, ebx
172
	pop	ebx
173
	jmp	.next_socket
174
 
175
  .decrement_wnd:
1249 hidnplayr 176
	dec	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer]
1159 hidnplayr 177
	jmp	.next_socket
178
 
179
  .exit:
180
	ret
181
 
182
 
1249 hidnplayr 183
 
184
;-----------------------------------------------------------------
1159 hidnplayr 185
;
1249 hidnplayr 186
; TCP_send_queued:
1159 hidnplayr 187
;
1249 hidnplayr 188
;  Decreases 'ttl' of tcp packets queued.
189
;  if 'ttl' reaches 0, resend the packet and decrease 'retries'
190
;  if 'retries' reaches zero, remove the queued packet
191
;
192
;  IN:  /
193
;  OUT: /
194
;
195
;-----------------------------------------------------------------
1196 hidnplayr 196
align 4
1249 hidnplayr 197
TCP_send_queued:
1159 hidnplayr 198
 
1249 hidnplayr 199
	cmp	[TCP_OUT_QUEUE], 0
200
	je	.exit
1159 hidnplayr 201
 
1318 hidnplayr 202
	mov	ebx, TCP_OUT_QUEUE+4
203
	call	wait_mutex
204
 
1249 hidnplayr 205
	mov	eax, TCP_QUEUE_SIZE
206
	mov	ecx, [TCP_OUT_QUEUE]
1318 hidnplayr 207
	mov	esi, TCP_OUT_QUEUE+8
1159 hidnplayr 208
 
1249 hidnplayr 209
  .loop:
210
	cmp	[esi + tcp_out_queue_entry.data_ptr], 0
211
	jnz	.found_one
212
	add	esi, tcp_out_queue_entry.size
213
	loop	.loop
214
  .exit:
1318 hidnplayr 215
	mov	[TCP_OUT_QUEUE+4], 0
1249 hidnplayr 216
	ret
1159 hidnplayr 217
 
1249 hidnplayr 218
  .found_one:
219
	dec	[esi + tcp_out_queue_entry.ttl]
220
	jz	.send_it
1318 hidnplayr 221
	cmp	[esi + tcp_out_queue_entry.data_ptr], -1
222
	jz	.is_ack
1249 hidnplayr 223
  .find_next:
1254 hidnplayr 224
	add	esi, tcp_out_queue_entry.size
1249 hidnplayr 225
	dec	eax
226
	jz	.exit
1254 hidnplayr 227
	test	ecx, ecx
228
	jnz	.loop
1318 hidnplayr 229
	mov	[TCP_OUT_QUEUE+4], 0
1254 hidnplayr 230
	ret
1159 hidnplayr 231
 
1249 hidnplayr 232
  .send_it:
1318 hidnplayr 233
	pusha
1254 hidnplayr 234
	mov	ebx, [esi + tcp_out_queue_entry.owner]
1318 hidnplayr 235
	pushd	[esi + tcp_out_queue_entry.data_size]
236
	pushd	[esi + tcp_out_queue_entry.data_ptr]
1254 hidnplayr 237
	DEBUGF 1,"Now sending TCP packet %x, size: %u, owner: %x, sendproc %x\n", [esp], [esp+4], ebx, [esi + tcp_out_queue_entry.sendproc]
1257 hidnplayr 238
	inc	[TCP_PACKETS_TX]
1249 hidnplayr 239
	call	[esi + tcp_out_queue_entry.sendproc]
1254 hidnplayr 240
	add	esp, 8
1318 hidnplayr 241
	popa
1159 hidnplayr 242
 
1249 hidnplayr 243
	dec	[esi + tcp_out_queue_entry.retries]
244
	jz	.remove_it
1254 hidnplayr 245
 
246
	mov	[esi + tcp_out_queue_entry.ttl], TCP_PACKET_TTL
1249 hidnplayr 247
	jmp	.find_next
1159 hidnplayr 248
 
1249 hidnplayr 249
  .remove_it:
250
	push	[esi + tcp_out_queue_entry.data_ptr]
251
	mov	[esi + tcp_out_queue_entry.data_ptr], 0
252
	call	kernel_free
1281 hidnplayr 253
	dec	[TCP_OUT_QUEUE]
1249 hidnplayr 254
	jmp	.find_next
1159 hidnplayr 255
 
1318 hidnplayr 256
  .is_ack:
257
	pusha
258
	mov	eax, [esi + tcp_out_queue_entry.socket]
259
	mov	ebx, [esi + tcp_out_queue_entry.owner]
260
	mov	ecx, [esi + tcp_out_queue_entry.size]
261
	call	TCP_send_ack
262
	popa
263
	mov	[esi + tcp_out_queue_entry.data_ptr], 0
264
	dec	[TCP_OUT_QUEUE]
265
	jmp	.find_next
1159 hidnplayr 266
 
267
 
1318 hidnplayr 268
 
1249 hidnplayr 269
;-----------------------------------------------------------------
270
;
271
; TCP_handler:
1159 hidnplayr 272
;
1196 hidnplayr 273
;  Called by IPv4_handler,
274
;  this procedure will inject the tcp data diagrams in the application sockets.
275
;
276
;  IN:  Pointer to buffer in [esp]
277
;       size of buffer in [esp+4]
278
;       pointer to device struct in ebx
279
;       TCP Packet size in ecx
1274 hidnplayr 280
;       pointer to TCP Packet in edx
281
;       SourceAddres (IPv4) in esi
1196 hidnplayr 282
;  OUT: /
283
;
284
;-----------------------------------------------------------------
1249 hidnplayr 285
align 4
286
TCP_handler :
1159 hidnplayr 287
 
1196 hidnplayr 288
       DEBUGF 1,"TCP_Handler\n"
289
 
1274 hidnplayr 290
; TODO: validate checksum
1254 hidnplayr 291
 
1318 hidnplayr 292
; Find a matching socket for received packet, all following expressions must be valid:
293
;
1274 hidnplayr 294
; IP Packet TCP Destination Port = local Port
1318 hidnplayr 295
; (IP Packet SA = Remote IP)  OR  (Remote IP = 0)
296
; (IP Packet TCP Source Port = remote Port)  OR (remote Port = 0)
1159 hidnplayr 297
 
298
	mov	ebx, net_sockets
299
 
1249 hidnplayr 300
  .socket_loop:
301
	mov	ebx, [ebx + SOCKET_head.NextPtr]
1159 hidnplayr 302
	or	ebx, ebx
1249 hidnplayr 303
	jz	.dump
1159 hidnplayr 304
 
1249 hidnplayr 305
	mov	ax, [edx + TCP_Packet.DestinationPort]
306
	cmp	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort], ax
307
	jne	.socket_loop
1159 hidnplayr 308
 
1249 hidnplayr 309
	mov	eax, [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
310
	cmp	eax, esi
311
	je	@f
312
	test	eax, eax
313
	jne	.socket_loop
314
       @@:
1159 hidnplayr 315
 
1249 hidnplayr 316
	mov	ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort]
317
	cmp	[edx + TCP_Packet.SourcePort] , ax
1274 hidnplayr 318
	je	.found_socket
1249 hidnplayr 319
	test	ax, ax
1254 hidnplayr 320
	jnz	.socket_loop
1274 hidnplayr 321
  .found_socket:
1254 hidnplayr 322
       DEBUGF 1,"Found valid socket for packet\n"
323
 
1257 hidnplayr 324
	inc	[TCP_PACKETS_RX]
325
 
1274 hidnplayr 326
	add	ebx, SOCKET_head.lock
1249 hidnplayr 327
	call	wait_mutex
1274 hidnplayr 328
	sub	ebx, SOCKET_head.lock
1159 hidnplayr 329
 
1274 hidnplayr 330
;-------------------------------
1249 hidnplayr 331
; ebx is pointer to socket
332
; ecx is size of tcp packet
333
; edx is pointer to tcp packet
1159 hidnplayr 334
 
1274 hidnplayr 335
; calculate header length
336
	movzx	eax, [edx + TCP_Packet.DataOffset]
337
	and	eax, 11110000b
338
	shr	eax, 2
339
       DEBUGF 1,"TCP header size: %u\n", eax
340
	sub	ecx, eax
341
 
342
;-------------------------------
343
; ecx is size of tcp data
344
 
345
; as a Packet has been received, update the TCB timer
1159 hidnplayr 346
 
1274 hidnplayr 347
; If the received Packet has an ACK bit set, remove any Packets in the resend queue that this received Packet acknowledges
1249 hidnplayr 348
	test	[edx + TCP_Packet.Flags], TH_ACK
1274 hidnplayr 349
	jz	.no_ack 				 ; No ACK, so no data yet
1159 hidnplayr 350
 
1318 hidnplayr 351
; Calculate ACK number, in intel byte order
1274 hidnplayr 352
	mov	edi, [edx + TCP_Packet.AckNumber]
353
	bswap	edi
354
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.last_ack_number], edi
1318 hidnplayr 355
	DEBUGF 1,"Setting last_ack_number to %u\n", edi
1159 hidnplayr 356
 
1274 hidnplayr 357
; Dequeue all acknowledged packets
358
	cmp	[TCP_OUT_QUEUE], 0		; first, check if any packets are queued at all
359
	je	.no_ack
1254 hidnplayr 360
 
1318 hidnplayr 361
	push	ebx
362
	mov	ebx, TCP_OUT_QUEUE+4
363
	call	wait_mutex
364
	pop	ebx
365
 
1254 hidnplayr 366
	push	ecx
1318 hidnplayr 367
	DEBUGF 1,"Removing all queued packets with smaller ACK\n"
1249 hidnplayr 368
	mov	ecx, TCP_QUEUE_SIZE
1318 hidnplayr 369
	mov	esi, TCP_OUT_QUEUE+8
1249 hidnplayr 370
  .loop:
371
	cmp	[esi + tcp_out_queue_entry.data_ptr], 0
1254 hidnplayr 372
	je	.maybe_next
1274 hidnplayr 373
 
374
	cmp	[esi + tcp_out_queue_entry.socket], ebx
375
	jne	.maybe_next
376
 
377
	cmp	[esi + tcp_out_queue_entry.seq_num], edi
1249 hidnplayr 378
	jg	.maybe_next
1159 hidnplayr 379
 
1318 hidnplayr 380
	DEBUGF 1,"Removing a queued packet\n"
1254 hidnplayr 381
 
1249 hidnplayr 382
	push	[esi + tcp_out_queue_entry.data_ptr]
383
	mov	[esi + tcp_out_queue_entry.data_ptr], 0
384
	dec	[TCP_OUT_QUEUE]
385
	call	kernel_free
1159 hidnplayr 386
 
1249 hidnplayr 387
  .maybe_next:
388
	add	esi, tcp_out_queue_entry.size
389
	loop	.loop
1318 hidnplayr 390
 
391
	mov	[TCP_OUT_QUEUE+4], 0
1274 hidnplayr 392
	pop	ecx
1254 hidnplayr 393
 
1274 hidnplayr 394
; Now call the correct handler, depending on the socket state
395
  .no_ack:
1254 hidnplayr 396
	mov	eax, [ebx +  SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state]
397
 
1249 hidnplayr 398
	cmp	eax, TCB_LISTEN
1254 hidnplayr 399
	jb	.dump
1249 hidnplayr 400
	cmp	eax, TCB_CLOSED
1254 hidnplayr 401
	ja	.dump
1159 hidnplayr 402
 
1318 hidnplayr 403
	call	dword [TCPstateHandler+eax*4-4]
1159 hidnplayr 404
 
1249 hidnplayr 405
  .dump:
406
	DEBUGF 1,"Dumping TCP packet\n"
1196 hidnplayr 407
	call	kernel_free
408
	add	esp, 4 ; pop (balance stack)
1159 hidnplayr 409
 
1249 hidnplayr 410
	ret
1196 hidnplayr 411
 
412
 
413
 
414
;-----------------------------------------------------------------
415
;
1274 hidnplayr 416
; TCP_send  (Assumes socket mutex set)
1196 hidnplayr 417
;
1249 hidnplayr 418
; IN: eax = socket pointer
1274 hidnplayr 419
;      bl = flags
1281 hidnplayr 420
;      ecx = number of bytes to send, may be set to 0  (single ACK)
1274 hidnplayr 421
;      esi = pointer to data
1249 hidnplayr 422
;
1196 hidnplayr 423
;-----------------------------------------------------------------
1249 hidnplayr 424
align 4
1274 hidnplayr 425
TCP_send:
1196 hidnplayr 426
 
1274 hidnplayr 427
	DEBUGF 1,"Creating TCP packet, socket: %x, flags: %x\n",eax, bl
1159 hidnplayr 428
 
1249 hidnplayr 429
	mov	di , IP_PROTO_TCP
1274 hidnplayr 430
	add	ecx, TCP_Packet.Data
1159 hidnplayr 431
 
1281 hidnplayr 432
	push	ecx bx eax esi
1249 hidnplayr 433
; Create an IPv4 Packet of the correct size
434
	mov	ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
435
	mov	eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
1159 hidnplayr 436
 
1249 hidnplayr 437
	call	IPv4_create_packet
438
	cmp	edi, -1
439
	je	.fail
1159 hidnplayr 440
 
1274 hidnplayr 441
; If there is any data, copy it first
1249 hidnplayr 442
	pop	esi
1274 hidnplayr 443
	push	edi
444
	add	edi, TCP_Packet.Data
445
	sub	ecx, TCP_Packet.Data
1159 hidnplayr 446
 
1249 hidnplayr 447
	shr	ecx, 1
448
	jnc	.nb
449
	movsb
450
.nb:	shr	ecx, 1
451
	jnc	.nw
452
	movsw
1274 hidnplayr 453
.nw:	test	ecx, ecx
454
	jz	.nd
455
	rep	movsd
456
.nd:
457
	pop	edi
1159 hidnplayr 458
 
1249 hidnplayr 459
; Fill in the TCP header
460
	pop	esi
1159 hidnplayr 461
 
1274 hidnplayr 462
; fill in tcp sequence number
1249 hidnplayr 463
	push	[esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
464
	pop	[edi + TCP_Packet.SequenceNumber]
1159 hidnplayr 465
 
1274 hidnplayr 466
; Fill in local and remote ports
467
	push	dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort]
1249 hidnplayr 468
	pop	dword [edi + TCP_Packet.SourcePort]
1159 hidnplayr 469
 
1274 hidnplayr 470
; Acknumber
1254 hidnplayr 471
	push	[esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
1249 hidnplayr 472
	pop	[edi + TCP_Packet.AckNumber]
1159 hidnplayr 473
 
1274 hidnplayr 474
; Fill  in other tcp options
1249 hidnplayr 475
	pop	cx
476
	mov	[edi + TCP_Packet.Flags], cl
477
	mov	[edi + TCP_Packet.Window], 0x0005	   ; 1280 bytes
478
	mov	[edi + TCP_Packet.UrgentPointer], 0
479
	mov	[edi + TCP_Packet.DataOffset], 0x50
1254 hidnplayr 480
	mov	[edi + TCP_Packet.Checksum], 0
1159 hidnplayr 481
 
1281 hidnplayr 482
; Get size of total packet back in ecx
483
	pop	ecx
1274 hidnplayr 484
; Push pointer to and size of total packet (needed for send procedure)
1254 hidnplayr 485
	push	edx eax
1274 hidnplayr 486
; push socket number (for TCP_add_to_queue)
487
	push	esi
1159 hidnplayr 488
 
1281 hidnplayr 489
; Now, calculate the checksum
490
	xchg	cl, ch
491
	pushw	cx
492
	xchg	cl, ch
1254 hidnplayr 493
	pushw	IP_PROTO_TCP shl 8
1318 hidnplayr 494
	pushd	[edi-4] ; destination address           ; TODO: fix this, IPv4 packet could have options..
1254 hidnplayr 495
	pushd	[edi-8] ; source address
496
 
1249 hidnplayr 497
	xor	edx, edx
1254 hidnplayr 498
	mov	esi, edi
499
	call	checksum_1
1249 hidnplayr 500
	mov	ecx, 12
501
	mov	esi, esp
502
	call	checksum_1
1254 hidnplayr 503
; and store it in TCP header
1249 hidnplayr 504
	call	checksum_2
505
	mov	[edi + TCP_Packet.Checksum], dx
1281 hidnplayr 506
	add	esp, 10 				   ; remove the pseudoheader from stack
1159 hidnplayr 507
 
1249 hidnplayr 508
	DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
1274 hidnplayr 509
	mov	edx, [edi + TCP_Packet.SequenceNumber]
510
	bswap	edx
1254 hidnplayr 511
	mov	esi, [ebx + ETH_DEVICE.transmit]
1281 hidnplayr 512
 
513
	pop	cx					   ; get the length from packet, back from pseudoheader
1274 hidnplayr 514
	pop	edi
1159 hidnplayr 515
 
1281 hidnplayr 516
	cmp	cx, TCP_Packet.Data shl 8		   ; if the packet has no data
517
	je	.only_one				   ; send it only once
518
 
519
	and	ecx, 0x0000ffff
520
	xchg	cl, ch
521
	sub	cx, TCP_Packet.Data
522
 
1318 hidnplayr 523
	add_INET (edi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT)     ; todo: this should only happen when packet was queued successful
1281 hidnplayr 524
	mov	ecx, TCP_RETRIES
525
 
526
	jmp	.go_for_it
527
 
528
  .only_one:
529
	mov	ecx, 1
530
  .go_for_it:
531
 
532
	mov	[edi + SOCKET_head.lock], 0
533
	jmp	TCP_queue				; At last send the packet!
534
 
1249 hidnplayr 535
  .fail:
1254 hidnplayr 536
	add	esp, 2+4
1274 hidnplayr 537
	or	eax, -1
1249 hidnplayr 538
	ret
1159 hidnplayr 539
 
540
 
1274 hidnplayr 541
;-----------------------------------------------------------------
542
;
543
;  Queue a TCP packet for sending
544
;
545
;  IN:  [esp] pointer to buffer
546
;       [esp + 4] size of buffer
547
;       ebx = driver struct
1318 hidnplayr 548
;       edx = sequence number of this packet in intel byte order
1274 hidnplayr 549
;       esi = sender proc
550
;       edi = socket number
1318 hidnplayr 551
 
1274 hidnplayr 552
;  OUT: /
553
;
554
;-----------------------------------------------------------------
555
align 4
556
TCP_queue:
1159 hidnplayr 557
 
1274 hidnplayr 558
	DEBUGF 1,"Adding packet to TCP queue, buffer: %x, size: %u, driver: %x, acknum: %u\n", [esp], [esp+4], ebx, edx
1159 hidnplayr 559
 
1274 hidnplayr 560
	cmp	[TCP_OUT_QUEUE], TCP_QUEUE_SIZE
561
	jge	.full
1159 hidnplayr 562
 
1318 hidnplayr 563
	push	ebx
564
	mov	ebx, TCP_OUT_QUEUE+4
565
	call	wait_mutex
566
	pop	ebx
567
 
1274 hidnplayr 568
	mov	ecx, TCP_QUEUE_SIZE
1318 hidnplayr 569
	mov	eax, TCP_OUT_QUEUE+8
1274 hidnplayr 570
  .loop:
571
	cmp	[eax + tcp_out_queue_entry.data_ptr], 0
572
	je	.found_it
573
	add	eax, tcp_out_queue_entry.size
574
	loop	.loop
575
 
1318 hidnplayr 576
	add	esp, 4
1274 hidnplayr 577
  .full:			; silently discard the packet
578
	DEBUGF 1,"TCP queue is full!\n"
579
	call	kernel_free
580
	add	esp, 4
581
 
582
	ret
583
 
584
  .found_it:			; eax points to empty queue entry
585
 
1318 hidnplayr 586
	mov	[eax + tcp_out_queue_entry.retries], TCP_RETRIES
1274 hidnplayr 587
	pop	[eax + tcp_out_queue_entry.data_ptr]
588
	pop	[eax + tcp_out_queue_entry.data_size]
589
	mov	[eax + tcp_out_queue_entry.ttl], 1			; send immediately
590
	mov	[eax + tcp_out_queue_entry.owner], ebx
591
	mov	[eax + tcp_out_queue_entry.sendproc], esi
592
	mov	[eax + tcp_out_queue_entry.seq_num], edx
593
	mov	[eax + tcp_out_queue_entry.socket], edi
594
 
595
	inc	[TCP_OUT_QUEUE]
596
 
1318 hidnplayr 597
	sub	eax, TCP_OUT_QUEUE+8
598
	shr	eax, 5
599
	DEBUGF 1,"Added to queue in pos %u, total queued packets: %u\n", eax, [TCP_OUT_QUEUE+8]
1274 hidnplayr 600
 
1318 hidnplayr 601
	mov	[TCP_OUT_QUEUE+4], 0
602
 
1274 hidnplayr 603
	ret
604
 
605
 
1318 hidnplayr 606
;-----------------------------------------------------------------
607
;
608
;  IN:  ebx = socket
609
;       ecx = ack number
610
;
611
;  OUT: /
612
;
613
;-----------------------------------------------------------------
614
align 4
615
TCP_queue_ack:
1274 hidnplayr 616
 
1318 hidnplayr 617
	DEBUGF 1,"Adding ACK to TCP queue, socket: %x, acknum: %u\n", ebx, ecx
1274 hidnplayr 618
 
1318 hidnplayr 619
	cmp	[TCP_OUT_QUEUE], TCP_QUEUE_SIZE
620
	jge	.full
1274 hidnplayr 621
 
1318 hidnplayr 622
	push	ebx ecx
623
	mov	ebx, TCP_OUT_QUEUE+4
624
	call	wait_mutex
625
 
626
	mov	ecx, TCP_QUEUE_SIZE
627
	mov	eax, TCP_OUT_QUEUE+8
628
  .loop:
629
	cmp	[eax + tcp_out_queue_entry.data_ptr], 0
630
	je	.found_it
631
	add	eax, tcp_out_queue_entry.size
632
	loop	.loop
633
 
634
	add	esp, 8
635
  .full:			; silently discard the packet
636
	DEBUGF 1,"TCP queue is full!\n"
637
	ret
638
 
639
  .found_it:			; eax points to empty queue entry
640
 
641
	pop	[eax + tcp_out_queue_entry.data_size]			; ACK number
642
	mov	[eax + tcp_out_queue_entry.data_ptr], -1		; ACK packet
643
	pop	[eax + tcp_out_queue_entry.socket]
644
	mov	[eax + tcp_out_queue_entry.retries], 1
645
	mov	[eax + tcp_out_queue_entry.ttl], 20			; 200 ms
646
 
647
	inc	[TCP_OUT_QUEUE]
648
 
649
	sub	eax, TCP_OUT_QUEUE+8
650
	shr	eax, 5
651
	DEBUGF 1,"Added to queue in pos %u, total queued packets: %u\n", eax, [TCP_OUT_QUEUE+8]
652
 
653
	mov	[TCP_OUT_QUEUE+4], 0
654
 
655
	ret
656
 
657
 
658
; IN: eax = socket pointer
659
;     ebx = device structure
660
;     ecx = ack number
661
 
662
align 4
663
TCP_send_ack:
664
 
665
	DEBUGF 1,"Creating TCP ACK packet, socket: %x, acknum: %x\n", eax, ecx
666
 
667
	push	ecx eax
668
 
669
	mov	di , IP_PROTO_TCP
670
	mov	ecx, TCP_Packet.Data
671
; Create an IPv4 Packet of the correct size
672
	mov	ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
673
	mov	eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
674
 
675
	call	IPv4_create_packet
676
	cmp	edi, -1
677
	je	.fail
678
 
679
	pop	ecx
680
 
681
; fill in tcp sequence number
682
	push	[ecx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
683
	pop	[edi + TCP_Packet.SequenceNumber]
684
 
685
; Fill in local and remote ports
686
	push	dword [ecx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort]
687
	pop	dword [edi + TCP_Packet.SourcePort]
688
 
689
; Acknumber
690
	pop	[edi + TCP_Packet.AckNumber]
691
 
692
; Fill  in other tcp options
693
	mov	[edi + TCP_Packet.Flags], TH_ACK
694
	mov	[edi + TCP_Packet.Window], 0x0005	   ; 1280 bytes
695
	mov	[edi + TCP_Packet.UrgentPointer], 0
696
	mov	[edi + TCP_Packet.DataOffset], 0x50
697
	mov	[edi + TCP_Packet.Checksum], 0
698
 
699
; Push pointer to and size of total packet (needed for send procedure)
700
	push	edx eax esi
701
 
702
; Now, calculate the checksum
703
	pushw	TCP_Packet.Data shl 8
704
	pushw	IP_PROTO_TCP shl 8
705
	pushd	[edi-4] ; destination address           ; TODO: fix this, IPv4 packet could have options..
706
	pushd	[edi-8] ; source address
707
 
708
	xor	edx, edx
709
	mov	ecx, 12
710
	mov	esi, esp
711
	call	checksum_1
712
	call	checksum_2
713
	mov	[edi + TCP_Packet.Checksum], dx
714
	add	esp, 12 				; remove the pseudoheader from stack
715
 
716
	pop	eax
717
	call	eax
718
	call	kernel_free
719
	add	esp, 4 ; pop (balance stack)
720
	ret
721
 
722
  .fail:
723
	add	esp, 8
724
	ret
725
 
726
 
727
 
728
 
729
;-----------------------------------------------------------------
730
;
731
; Remove all queued TCP packets for a specified socket
732
;
733
; IN: eax = socket number
734
; OUT: /
735
;
736
; destoys esi and ecx
737
;
738
;-----------------------------------------------------------------
739
 
740
align 4
741
TCP_remove_socket:
742
 
743
	cmp	[TCP_OUT_QUEUE], 0
744
	je	.skip
745
 
746
	mov	ebx, TCP_OUT_QUEUE+4
747
	call	wait_mutex
748
 
749
	mov	eax, TCP_QUEUE_SIZE
750
	mov	ecx, [TCP_OUT_QUEUE]
751
	mov	esi, TCP_OUT_QUEUE+8
752
 
753
  .loop:
754
	cmp	[esi + tcp_out_queue_entry.data_ptr], 0
755
	jz	.maybenext
756
	cmp	[esi + tcp_out_queue_entry.socket], eax
757
	jnz	.maybenext
758
 
759
	push	[esi + tcp_out_queue_entry.data_ptr]
760
	mov	[esi + tcp_out_queue_entry.data_ptr], 0
761
	dec	[TCP_OUT_QUEUE]
762
	call	kernel_free
763
 
764
  .maybenext:
765
	add	esi, tcp_out_queue_entry.size
766
	loop	.loop
767
 
768
	mov	[TCP_OUT_QUEUE+4], 0
769
  .skip:
770
	ret
771
 
772
 
773
 
774
 
775
 
1255 hidnplayr 776
;---------- TCB state handlers start here
777
 
778
 
779
 
780
 
1249 hidnplayr 781
align 4
782
stateTCB_LISTEN:
1254 hidnplayr 783
 
784
	DEBUGF	1,"TCBStateHandler: Listen\n"
785
 
1274 hidnplayr 786
	test	[edx + TCP_Packet.Flags], TH_SYN	; SYN packet? => send syn+ack, open new socket and set connection to established
1159 hidnplayr 787
	jz	.exit
1274 hidnplayr 788
; Exit if backlog queue is full
1256 clevermous 789
	mov	ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
790
	cmp	ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog]
791
	jae	.exit
1274 hidnplayr 792
; Allocate new socket
793
	push	esi edi
1256 clevermous 794
	call	net_socket_alloc
795
	test	eax, eax
1274 hidnplayr 796
	jz	.fail
797
; Copy structure from current socket to new, including lock
798
	lea	esi, [ebx + SOCKET_head.PID]		; yes, PID must also be copied
1256 clevermous 799
	lea	edi, [eax + SOCKET_head.PID]
800
	mov	ecx, ((SOCKET_head.end - SOCKET_head.PID) + IPv4_SOCKET.end + TCP_SOCKET.end + 3)/4
801
	rep	movsd
802
	pop	edi esi
1274 hidnplayr 803
; Push pointer to new socket to queue
1256 clevermous 804
	movzx	ecx, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
805
	inc	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
806
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.end + ecx*4], eax
1159 hidnplayr 807
 
1256 clevermous 808
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], esi ; IP source address
809
	mov	cx, [edx + TCP_Packet.SourcePort]
810
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], cx
811
	mov	ecx, [edx + TCP_Packet.SequenceNumber]
812
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.IRS], ecx
813
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], ecx
814
	lea	esi, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
1249 hidnplayr 815
	inc_INET esi ; RCV.NXT
1256 clevermous 816
	mov	ecx, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.ISS]
817
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT], ecx
1159 hidnplayr 818
 
1254 hidnplayr 819
	mov	[ebx + SOCKET_head.lock], 0
820
 
1256 clevermous 821
	push	eax
1274 hidnplayr 822
; Now construct the response
1159 hidnplayr 823
	mov	bl, TH_SYN + TH_ACK
1274 hidnplayr 824
	xor	ecx, ecx
825
	call	TCP_send
1256 clevermous 826
	pop	eax
1159 hidnplayr 827
 
1274 hidnplayr 828
	mov	[eax + SOCKET_head.lock], 0
1256 clevermous 829
	mov	[eax +	SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
830
	call	notify_network_event
831
	ret
1159 hidnplayr 832
 
833
  .exit:
1254 hidnplayr 834
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 835
	ret
836
 
1274 hidnplayr 837
  .fail:
838
	add	esp, 8
839
	mov	[ebx + SOCKET_head.lock], 0
840
	ret
1159 hidnplayr 841
 
1274 hidnplayr 842
 
1249 hidnplayr 843
align 4
844
stateTCB_SYN_SENT:
1254 hidnplayr 845
 
846
	DEBUGF	1,"TCBStateHandler: Syn_Sent\n"
847
 
1159 hidnplayr 848
	; We are awaiting an ACK to our SYN, with a SYM
849
	; Look at control flags - expecting an ACK
850
 
1249 hidnplayr 851
	mov	al, [edx + TCP_Packet.Flags]
1274 hidnplayr 852
 
853
	test	al, TH_RST
854
	jnz	.reset			; jump if RST bit set
855
 
856
	push	[edx + TCP_Packet.SequenceNumber]				     ;;
857
	pop	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]	     ;;
858
	inc_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT)      ;;
859
 
860
 
861
	push	[edx + TCP_Packet.AckNumber]					    ;;;;;;
862
	pop	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]	    ;;;;;;
863
 
1159 hidnplayr 864
	and	al, TH_SYN + TH_ACK
1274 hidnplayr 865
	jz	.exit			; jump if none of the following is set: RST, SYN, ACK
1159 hidnplayr 866
 
1274 hidnplayr 867
	test	al, TH_ACK
868
	jz     .onlysyn 		; jump if only SYN bit is set
1159 hidnplayr 869
 
1274 hidnplayr 870
	; If we arrived here, SYN and ACK are set
1159 hidnplayr 871
 
1254 hidnplayr 872
	mov	[ebx +	SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
1274 hidnplayr 873
	pushw	TH_ACK
1159 hidnplayr 874
 
1274 hidnplayr 875
  .send:	; Send an ACK
1254 hidnplayr 876
	mov	eax, ebx
1274 hidnplayr 877
	pop	bx
878
	push	eax
879
	xor	ecx, ecx
880
	call	TCP_send
1159 hidnplayr 881
	pop	ebx
882
 
883
  .exit:
1254 hidnplayr 884
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 885
	ret
886
 
1274 hidnplayr 887
  .reset:
888
	; TODO: ....
1159 hidnplayr 889
 
1274 hidnplayr 890
	; remove all queued TCP packets for this connection !
1249 hidnplayr 891
 
1274 hidnplayr 892
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSED
893
	mov	[ebx + SOCKET_head.lock], 0
894
	ret
895
 
896
  .onlysyn:
897
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
898
	pushw	TH_SYN + TH_ACK
899
	jmp	.send
900
 
901
 
902
 
1249 hidnplayr 903
align 4
904
stateTCB_SYN_RECEIVED:
1254 hidnplayr 905
 
906
	DEBUGF	1,"TCBStateHandler: Syn_received\n"
907
 
1274 hidnplayr 908
	test	[edx + TCP_Packet.Flags], TH_RST	; reset connection? => LISTEN
1159 hidnplayr 909
	jz	.check_ack
910
 
1274 hidnplayr 911
	push	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemotePort]
912
	pop	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort]
913
	push	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemoteIP]
914
	pop	[ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
1159 hidnplayr 915
 
1254 hidnplayr 916
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN
1159 hidnplayr 917
	jmp	.exit
918
 
919
  .check_ack:
1274 hidnplayr 920
	test	[edx + TCP_Packet.Flags], TH_ACK	; ACK? => connection established!
1159 hidnplayr 921
	jz	.exit
922
 
1254 hidnplayr 923
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
1256 clevermous 924
	mov	eax, ebx
925
	call	notify_network_event
1159 hidnplayr 926
 
927
  .exit:
1254 hidnplayr 928
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 929
	ret
930
 
931
 
1318 hidnplayr 932
if 0
1249 hidnplayr 933
 
1318 hidnplayr 934
 
1249 hidnplayr 935
align 4
936
stateTCB_ESTABLISHED:
1254 hidnplayr 937
 
938
	DEBUGF	1,"TCBStateHandler: Established\n"
939
 
1255 hidnplayr 940
	mov	eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
1274 hidnplayr 941
	bswap	eax
942
	DEBUGF	1,"RCV_NXT is set to:%u\n", eax
943
	bswap	eax
1255 hidnplayr 944
	cmp	eax, [edx + TCP_Packet.SequenceNumber]
1318 hidnplayr 945
	jne	.exit					;;;;;;
946
 
947
; check if we received an ACK
948
	test	[edx + TCP_Packet.Flags], TH_ACK
949
	jz	.no_ack
950
 
951
	mov	ax, [edx + TCP_Packet.Window]
952
	xchg	al, ah
953
	cmp	ax, 1024
954
	ja	@f
955
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 1
956
      @@:
957
  .no_ack:
958
 
959
; Now, see if we received any data
960
	test	ecx, ecx
961
	jz	.nodata
962
 
963
; Calculate next sequencenumber
964
	add_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT)
965
 
966
	push	edx
967
	DEBUGF	1,"Got %u bytes data!\n", ecx
968
; calculate header length
969
	movzx	eax, [edx + TCP_Packet.DataOffset]
970
	and	eax, 11110000b
971
	shr	eax, 2
972
	DEBUGF	1,"TCP header size: %u\n", eax
973
	add	edx, eax	; now edx points to data
974
 
975
	add	esp, 4
976
	pop	esi		; pointer to buffer
977
	add	esp, 4
978
 
979
	sub	edx, esi
980
	mov	edi, edx	; offset
981
	mov	eax, ebx	; socket ptr
982
 
983
	call	socket_internal_receiver	; Place the data from packet into socket
984
 
985
;        lea     ebx, [eax + SOCKET_head.lock]
986
;        call    wait_mutex
987
	mov	ebx, eax
988
	pop	edx
989
 
990
	test	[edx + TCP_Packet.Flags], TH_FIN + TH_RST
991
	jz	.ack
992
 
993
  .nodata:
994
	test	[edx + TCP_Packet.Flags], TH_FIN + TH_RST
995
	jz	.exit
996
 
997
; Send an ACK to that fin, and enter closewait state
998
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT
999
; Remove all resend entries from the queue
1000
	mov	eax, ebx
1001
	call	TCP_remove_socket
1002
 
1003
  .ack:
1004
	push	ebx
1005
	mov	ecx, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
1006
	call	TCP_queue_ack
1007
	pop	ebx
1008
 
1009
  .exit:
1010
	mov	[ebx + SOCKET_head.lock], 0
1011
	ret
1012
 
1013
 
1014
end if
1015
 
1016
 
1017
align 4
1018
stateTCB_ESTABLISHED:
1019
 
1020
	DEBUGF	1,"TCBStateHandler: Established\n"
1021
 
1022
	mov	eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
1023
	bswap	eax
1024
	DEBUGF	1,"RCV_NXT is set to:%u\n", eax
1025
	bswap	eax
1026
	cmp	eax, [edx + TCP_Packet.SequenceNumber]
1255 hidnplayr 1027
	jne	.exit
1028
 
1274 hidnplayr 1029
; Calculate next sequencenumber
1030
	add_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT)
1159 hidnplayr 1031
 
1318 hidnplayr 1032
	test	[edx + TCP_Packet.Flags], TH_FIN + TH_RST
1274 hidnplayr 1033
	jnz	.fin
1159 hidnplayr 1034
 
1035
  .check_ack:
1249 hidnplayr 1036
	test	[edx + TCP_Packet.Flags], TH_ACK
1159 hidnplayr 1037
	jz	.exit
1038
 
1254 hidnplayr 1039
	DEBUGF	1,"Received ACK\n"
1274 hidnplayr 1040
; First, look at the incoming window. If this is less than or equal to 1024,
1041
; Set the socket window timer to 1. This will stop an additional Packets being queued.
1042
; ** I may need to tweak this value, since I do not know how many Packets are already queued
1255 hidnplayr 1043
	push	ecx
1249 hidnplayr 1044
	mov	cx, [edx + TCP_Packet.Window]
1159 hidnplayr 1045
	xchg	cl, ch
1046
	cmp	cx, 1024
1047
	ja	@f
1249 hidnplayr 1048
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 1
1255 hidnplayr 1049
      @@:
1050
	pop	ecx
1159 hidnplayr 1051
 
1274 hidnplayr 1052
; Now, see if we received any data
1255 hidnplayr 1053
	test	ecx, ecx
1281 hidnplayr 1054
	jz	.exit
1159 hidnplayr 1055
 
1274 hidnplayr 1056
	DEBUGF	1,"Got %u bytes data!\n", ecx
1057
; calculate header length
1058
	movzx	eax, [edx + TCP_Packet.DataOffset]
1059
	and	eax, 11110000b
1060
	shr	eax, 2
1061
       DEBUGF 1,"TCP header size: %u\n", eax
1281 hidnplayr 1062
	add	edx, eax	; now edx points to data
1063
 
1274 hidnplayr 1064
	add	esp, 4
1281 hidnplayr 1065
	pop	esi		; pointer to buffer
1274 hidnplayr 1066
	add	esp, 4
1281 hidnplayr 1067
 
1249 hidnplayr 1068
	sub	edx, esi
1281 hidnplayr 1069
	mov	edi, edx	; offset
1070
	mov	eax, ebx	; socket ptr
1159 hidnplayr 1071
 
1281 hidnplayr 1072
	call	socket_internal_receiver	; Place the data from packet into socket
1073
 
1318 hidnplayr 1074
	lea	ebx, [eax + SOCKET_head.lock]
1075
	call	wait_mutex
1076
	mov	ebx, eax
1281 hidnplayr 1077
 
1159 hidnplayr 1078
  .ack:
1254 hidnplayr 1079
	mov	eax, ebx
1159 hidnplayr 1080
	mov	bl, TH_ACK
1274 hidnplayr 1081
	push	eax
1082
	xor	ecx, ecx
1083
	call	TCP_send		    ; send the ack
1084
	pop	ebx
1159 hidnplayr 1085
  .exit:
1254 hidnplayr 1086
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 1087
	ret
1088
 
1318 hidnplayr 1089
  .fin:        ; we received a FIN or RESET
1274 hidnplayr 1090
; Remove all resend entries from the queue
1091
	mov	ecx, TCP_QUEUE_SIZE
1092
	mov	esi, TCP_OUT_QUEUE+4
1159 hidnplayr 1093
 
1274 hidnplayr 1094
  .removeloop:
1095
	cmp	[esi + tcp_out_queue_entry.data_ptr], 0
1096
	je	.maybe_next
1249 hidnplayr 1097
 
1274 hidnplayr 1098
	; TODO: check if the packets belong to the same tcp connection !
1099
 
1100
       DEBUGF 1,"Removing a queued packet\n"
1101
 
1102
	push	[esi + tcp_out_queue_entry.data_ptr]
1103
	mov	[esi + tcp_out_queue_entry.data_ptr], 0
1104
	dec	[TCP_OUT_QUEUE]
1105
	call	kernel_free
1106
 
1107
  .maybe_next:
1108
	add	esi, tcp_out_queue_entry.size
1109
	loop	.removeloop
1110
 
1111
; Send an ACK to that fin, and enter closewait state
1318 hidnplayr 1112
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSING
1274 hidnplayr 1113
	jmp	.check_ack
1114
 
1115
 
1249 hidnplayr 1116
align 4
1117
stateTCB_FIN_WAIT_1:
1254 hidnplayr 1118
 
1119
	DEBUGF	1,"TCBStateHandler: Fin_wait_1\n"
1120
 
1159 hidnplayr 1121
	; We can either receive an ACK of a fin, or a fin
1249 hidnplayr 1122
	mov	al, [edx + TCP_Packet.Flags]
1159 hidnplayr 1123
	and	al, TH_FIN + TH_ACK
1124
 
1125
	cmp	al, TH_ACK
1126
	jne	@f
1127
 
1128
	; It was an ACK
1254 hidnplayr 1129
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_FIN_WAIT_2
1159 hidnplayr 1130
	jmp	.exit
1131
 
1254 hidnplayr 1132
    @@: mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSING
1159 hidnplayr 1133
	cmp	al, TH_FIN
1134
	je	@f
1254 hidnplayr 1135
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
1159 hidnplayr 1136
 
1274 hidnplayr 1137
    @@:
1159 hidnplayr 1138
	; Send an ACK
1254 hidnplayr 1139
	mov	eax, ebx
1159 hidnplayr 1140
	mov	bl, TH_ACK
1274 hidnplayr 1141
	push	eax
1142
	xor	ecx, ecx
1143
	call	TCP_send
1144
	pop	ebx
1159 hidnplayr 1145
 
1146
  .exit:
1254 hidnplayr 1147
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 1148
	ret
1149
 
1150
 
1249 hidnplayr 1151
 
1152
align 4
1153
stateTCB_FIN_WAIT_2:
1254 hidnplayr 1154
 
1155
	DEBUGF	1,"TCBStateHandler: Fin_wait_2\n"
1156
 
1249 hidnplayr 1157
	test	[edx + TCP_Packet.Flags], TH_FIN
1159 hidnplayr 1158
	jz	.exit
1159
 
1160
	; Change state, as we have a fin
1254 hidnplayr 1161
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
1159 hidnplayr 1162
 
1163
	; Send an ACK
1254 hidnplayr 1164
	mov	eax, ebx
1159 hidnplayr 1165
	mov	bl, TH_ACK
1274 hidnplayr 1166
	push	eax
1167
	xor	ecx, ecx
1168
	call	TCP_send
1169
	pop	ebx
1159 hidnplayr 1170
 
1171
  .exit:
1254 hidnplayr 1172
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 1173
	ret
1174
 
1175
 
1249 hidnplayr 1176
 
1177
align 4
1178
stateTCB_CLOSE_WAIT:
1254 hidnplayr 1179
 
1180
	DEBUGF	1,"TCBStateHandler: close_wait\n"
1159 hidnplayr 1181
	; Intentionally left empty
1182
	; socket_close_tcp handles this
1254 hidnplayr 1183
 
1184
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 1185
	ret
1186
 
1187
 
1249 hidnplayr 1188
 
1189
align 4
1190
stateTCB_CLOSING:
1254 hidnplayr 1191
 
1192
	DEBUGF	1,"TCBStateHandler: closingn\n"
1193
 
1159 hidnplayr 1194
	; We can either receive an ACK of a fin, or a fin
1249 hidnplayr 1195
	test	[edx + TCP_Packet.Flags], TH_ACK
1159 hidnplayr 1196
	jz	.exit
1197
 
1254 hidnplayr 1198
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
1159 hidnplayr 1199
 
1200
  .exit:
1254 hidnplayr 1201
 
1202
	mov	[ebx + SOCKET_head.lock], 0
1159 hidnplayr 1203
	ret
1204
 
1205
 
1249 hidnplayr 1206
align 4
1207
stateTCB_LAST_ACK:
1254 hidnplayr 1208
 
1209
	DEBUGF	1,"TCBStateHandler: last_ackn\n"
1210
 
1159 hidnplayr 1211
	; Look at control flags - expecting an ACK
1249 hidnplayr 1212
	test	[edx + TCP_Packet.Flags], TH_ACK
1159 hidnplayr 1213
	jz	.exit
1214
 
1254 hidnplayr 1215
	mov	[ebx + SOCKET_head.lock], 0
1216
 
1159 hidnplayr 1217
	; delete the socket
1218
	stdcall net_socket_free, ebx
1219
 
1220
  .exit:
1221
	ret
1222
 
1223
 
1249 hidnplayr 1224
align 4
1225
stateTCB_TIME_WAIT:
1254 hidnplayr 1226
 
1227
	DEBUGF	1,"TCBStateHandler: time_wait\n"
1228
 
1229
	mov	[ebx + SOCKET_head.lock], 0
1230
 
1159 hidnplayr 1231
	ret
1232
 
1233
 
1249 hidnplayr 1234
align 4
1235
stateTCB_CLOSED:
1254 hidnplayr 1236
 
1237
	DEBUGF	1,"TCBStateHandler: closed\n"
1238
 
1239
	mov	[ebx + SOCKET_head.lock], 0
1240
 
1159 hidnplayr 1241
	ret
1242
 
1243
 
1244
 
1254 hidnplayr 1245
;---------------------------------------------------------------------------
1246
;
1247
; TCP_API
1248
;
1249
; This function is called by system function 75
1250
;
1251
; IN:  subfunction number in bl
1252
;      device number in bh
1253
;      ecx, edx, .. depends on subfunction
1254
;
1255
; OUT:
1256
;
1257
;---------------------------------------------------------------------------
1258
align 4
1259
TCP_API:
1260
 
1261
	movzx	eax, bh
1262
	shl	eax, 2
1263
 
1264
	test	bl, bl
1265
	jz	.packets_tx	; 0
1266
	dec	bl
1267
	jz	.packets_rx	; 1
1268
 
1269
.error:
1270
	mov	eax, -1
1271
	ret
1272
 
1273
.packets_tx:
1274
	add	eax, TCP_PACKETS_TX
1275
	mov	eax, [eax]
1276
	ret
1277
 
1278
.packets_rx:
1279
	add	eax, TCP_PACKETS_RX
1280
	mov	eax, [eax]
1281
	ret