Subversion Repositories Kolibri OS

Rev

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