Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1763 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2362 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved.    ;;
1763 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  Part of the tcp/ip network stack for KolibriOS                 ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org                            ;;
9
;;                                                                 ;;
10
;;    Based on the code of 4.4BSD                                  ;;
11
;;                                                                 ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
13
;;             Version 2, June 1991                                ;;
14
;;                                                                 ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
 
17
$Revision: 2362 $
18
 
1733 hidnplayr 19
;-----------------------------------------------------------------
20
;
21
; TCP_input:
22
;
23
;  IN:  [esp] = ptr to buffer
24
;       [esp+4] = buffer size
25
;       ebx = ptr to device struct
26
;       ecx = segment size
2310 hidnplayr 27
;       esi = ptr to TCP segment
2308 hidnplayr 28
;       edi = ptr to ipv4 source address, followed by ipv4 dest address
1733 hidnplayr 29
;
30
;  OUT: /
31
;
32
;-----------------------------------------------------------------
1830 hidnplayr 33
 
1733 hidnplayr 34
align 4
35
TCP_input:
36
 
2362 hidnplayr 37
	DEBUGF	1,"TCP_input size=%u\n", ecx
1733 hidnplayr 38
 
2362 hidnplayr 39
	and	[esi + TCP_header.DataOffset], 0xf0			; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
40
	shr	[esi + TCP_header.DataOffset], 2
41
	cmp	[esi + TCP_header.DataOffset], sizeof.TCP_header	; Now see if it's at least the size of a standard TCP header
42
	jb	.drop_not_locked					; If not, drop the packet
1733 hidnplayr 43
 
44
;-------------------------------
45
; Now, re-calculate the checksum
46
 
2362 hidnplayr 47
	push	ecx esi
48
	pushw	[esi + TCP_header.Checksum]
49
	mov	[esi + TCP_header.Checksum], 0
50
	TCP_checksum (edi), (edi+4)
51
	pop	cx		; previous checksum
52
	cmp	cx, dx
53
	pop	edx ecx
54
	jnz	.drop_not_locked
1733 hidnplayr 55
 
2362 hidnplayr 56
	DEBUGF	1,"Checksum ok\n"
1733 hidnplayr 57
 
2362 hidnplayr 58
	movzx	eax, [edx + TCP_header.DataOffset]
59
	sub	ecx, eax						; substract TCP header size from total segment size
60
	jb	.drop_not_locked					; If total segment size is less then the advertised header size, drop packet
61
	DEBUGF	1,"we got %u bytes of data\n", ecx
1733 hidnplayr 62
 
63
;-----------------------------------------------------------------------------------------
64
; Check if this packet has a timestamp option (We do it here so we can process it quickly)
65
 
2362 hidnplayr 66
	cmp	eax, sizeof.TCP_header + 12				; Timestamp option is 12 bytes
67
	jb	.no_timestamp
68
	je	.is_ok
1733 hidnplayr 69
 
2362 hidnplayr 70
	cmp	byte [edx + sizeof.TCP_header + 12], TCP_OPT_EOL		; end of option list
71
	jne	.no_timestamp
1733 hidnplayr 72
 
73
  .is_ok:
2362 hidnplayr 74
	test	[edx + TCP_header.Flags], TH_SYN				; SYN flag must not be set
75
	jnz	.no_timestamp
1733 hidnplayr 76
 
2362 hidnplayr 77
	cmp	dword [edx + sizeof.TCP_header], 0x0101080a			; Timestamp header
78
	jne	.no_timestamp
1733 hidnplayr 79
 
2362 hidnplayr 80
	DEBUGF	1,"timestamp ok\n"
1733 hidnplayr 81
 
2362 hidnplayr 82
	; TODO: Parse the option
83
	; TODO: Set a Bit in the TCP to tell all options are parsed
1733 hidnplayr 84
 
85
  .no_timestamp:
86
 
87
;-------------------------------------------
88
; Convert Big-endian values to little endian
89
 
2362 hidnplayr 90
	ntohd	[edx + TCP_header.SequenceNumber]
91
	ntohd	[edx + TCP_header.AckNumber]
1733 hidnplayr 92
 
2362 hidnplayr 93
	ntohw	[edx + TCP_header.Window]
94
	ntohw	[edx + TCP_header.UrgentPointer]
95
	ntohw	[edx + TCP_header.SourcePort]
96
	ntohw	[edx + TCP_header.DestinationPort]
1733 hidnplayr 97
 
98
;------------------------------------------------------------
1831 hidnplayr 99
; Next thing to do is find the TCPS (thus, the socket pointer)
1733 hidnplayr 100
 
101
; IP Packet TCP Destination Port = local Port
102
; (IP Packet SenderAddress = Remote IP)  OR  (Remote IP = 0)
2309 hidnplayr 103
; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0)
1733 hidnplayr 104
 
2362 hidnplayr 105
	mov	ebx, net_sockets
106
	mov	si, [edx + TCP_header.DestinationPort]
1733 hidnplayr 107
 
108
  .socket_loop:
2362 hidnplayr 109
	mov	ebx, [ebx + SOCKET.NextPtr]
110
	or	ebx, ebx
111
	jz	.drop_with_reset_not_locked
1733 hidnplayr 112
 
2362 hidnplayr 113
	cmp	[ebx + SOCKET.Domain], AF_INET4
114
	jne	.socket_loop
1733 hidnplayr 115
 
2362 hidnplayr 116
	cmp	[ebx + SOCKET.Protocol], IP_PROTO_TCP
117
	jne	.socket_loop
1733 hidnplayr 118
 
2362 hidnplayr 119
	cmp	[ebx + TCP_SOCKET.LocalPort], si
120
	jne	.socket_loop
1733 hidnplayr 121
 
2362 hidnplayr 122
	mov	eax, [ebx + IP_SOCKET.RemoteIP]
123
	cmp	eax, [edi]				; Ipv4 source addres
124
	je	@f
125
	test	eax, eax
126
	jnz	.socket_loop
1733 hidnplayr 127
       @@:
128
 
2362 hidnplayr 129
	mov	ax, [ebx + TCP_SOCKET.RemotePort]
130
	cmp	[edx + TCP_header.SourcePort] , ax
131
	je	.found_socket
132
	test	ax, ax
133
	jnz	.socket_loop
134
  .found_socket:					; ebx now contains the socketpointer
135
	DEBUGF	1,"Socket ptr: %x\n", ebx
1733 hidnplayr 136
 
137
 
138
;----------------------------
139
; Check if socket isnt closed
140
 
2362 hidnplayr 141
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_CLOSED
142
	je	.drop_not_locked
1733 hidnplayr 143
 
144
;----------------
145
; Lock the socket
146
 
2362 hidnplayr 147
	cmp	[ebx + SOCKET.lock], 0
148
	jne	.drop_not_locked     ;;; HACK ! HACK ! dirty fucking HACK !   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1830 hidnplayr 149
 
2362 hidnplayr 150
	add	ebx, SOCKET.lock
151
	DEBUGF	1,"lock: %x\n", [ebx]
152
	call	wait_mutex
153
	sub	ebx, SOCKET.lock
1733 hidnplayr 154
 
2362 hidnplayr 155
	DEBUGF	1,"Socket locked\n"
1733 hidnplayr 156
 
157
;---------------------------------------
158
; unscale the window into a 32 bit value
159
 
2362 hidnplayr 160
	movzx	eax, [edx + TCP_header.Window]
161
	push	ecx
162
	mov	cl, [ebx + TCP_SOCKET.SND_SCALE]
163
	shl	eax, cl
164
	mov	dword [edx + TCP_header.Window], eax	; word after window is checksum, we dont need checksum anymore
165
	pop	ecx
1733 hidnplayr 166
 
167
;-----------------------------------
168
; Is this socket a listening socket?
169
 
2362 hidnplayr 170
	test	[ebx + SOCKET.options], SO_ACCEPTCON
171
	jz	.no_listening_socket
1733 hidnplayr 172
 
2362 hidnplayr 173
	DEBUGF	1,"Accepting new connection\n"
1838 hidnplayr 174
 
2362 hidnplayr 175
	mov	[ebx + SOCKET.lock], 0
176
	push	ecx edx esi edi 	;;;
177
	call	SOCKET_fork
178
	pop	edi esi edx ecx
1838 hidnplayr 179
 
2362 hidnplayr 180
	test	eax, eax
181
	jz	.drop
1733 hidnplayr 182
 
2362 hidnplayr 183
	push	dword [edi + 4] 			; Ipv4 destination addres
184
	pop	[eax + IP_SOCKET.LocalIP]
1733 hidnplayr 185
 
2362 hidnplayr 186
	push	[edx + TCP_header.DestinationPort]
187
	pop	[eax + TCP_SOCKET.LocalPort]
1733 hidnplayr 188
 
2362 hidnplayr 189
	mov	[eax + TCP_SOCKET.t_state], TCPS_LISTEN
1733 hidnplayr 190
 
1838 hidnplayr 191
;        mov     [ebx + SOCKET.lock], 0
2362 hidnplayr 192
	mov	ebx, eax
1733 hidnplayr 193
 
2362 hidnplayr 194
	jmp	.LISTEN
1838 hidnplayr 195
 
1733 hidnplayr 196
  .no_listening_socket:
197
 
198
;-------------------------------------
199
; Reset idle timer and keepalive timer
200
 
2362 hidnplayr 201
	mov	[ebx + TCP_SOCKET.t_idle], 0
202
	mov	[ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
1733 hidnplayr 203
 
204
;--------------------
205
; Process TCP options
206
 
2362 hidnplayr 207
	movzx	eax, [edx + TCP_header.DataOffset]
208
	cmp	eax, sizeof.TCP_header			; Does header contain any options?
209
	je	.no_options
1733 hidnplayr 210
 
2362 hidnplayr 211
	DEBUGF	1,"Segment has options\n"
1733 hidnplayr 212
 
2362 hidnplayr 213
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
214
	jz	.not_uni_xfer				; also no header prediction
1733 hidnplayr 215
 
2362 hidnplayr 216
	add	eax, edx
217
	lea	esi, [edx + sizeof.TCP_header]
1733 hidnplayr 218
 
219
  .opt_loop:
2362 hidnplayr 220
	cmp	esi, eax			; are we scanning outside of header?
221
	jae	.no_options
1733 hidnplayr 222
 
2362 hidnplayr 223
	cmp	byte [esi], TCP_OPT_EOL 	; end of option list?
224
	jz	.no_options
1733 hidnplayr 225
 
2362 hidnplayr 226
	cmp	byte [esi], TCP_OPT_NOP 	; nop ?
227
	jz	.opt_nop
1733 hidnplayr 228
 
2362 hidnplayr 229
	cmp	byte [esi], TCP_OPT_MAXSEG
230
	je	.opt_maxseg
1733 hidnplayr 231
 
2362 hidnplayr 232
	cmp	byte [esi], TCP_OPT_WINDOW
233
	je	.opt_window
1733 hidnplayr 234
 
2362 hidnplayr 235
	cmp	byte [esi], TCP_OPT_TIMESTAMP
236
	je	.opt_timestamp
1733 hidnplayr 237
 
2362 hidnplayr 238
	jmp	.no_options	; If we reach here, some unknown options were received, skip them all!
1733 hidnplayr 239
 
240
  .opt_nop:
2362 hidnplayr 241
	inc	edi
242
	jmp	.opt_loop
1733 hidnplayr 243
 
244
  .opt_maxseg:
2362 hidnplayr 245
	cmp	byte [esi+1], 4
246
	jne	.no_options		; error occured, ignore all options!
1733 hidnplayr 247
 
2362 hidnplayr 248
	test	[edx + TCP_header.Flags], TH_SYN
249
	jz	@f
1733 hidnplayr 250
 
2362 hidnplayr 251
	movzx	eax, word[esi+2]
252
	rol	ax, 8
253
	DEBUGF	1,"Maxseg: %u\n", ax
1733 hidnplayr 254
 
2362 hidnplayr 255
	mov	[ebx + TCP_SOCKET.t_maxseg], eax
1733 hidnplayr 256
 
257
       @@:
2362 hidnplayr 258
	add	edi, 4
259
	jmp	.opt_loop
1733 hidnplayr 260
 
261
 
262
  .opt_window:
2362 hidnplayr 263
	cmp	byte [esi+1], 3
264
	jne	.no_options
1733 hidnplayr 265
 
2362 hidnplayr 266
	test	[edx + TCP_header.Flags], TH_SYN
267
	jz	@f
1733 hidnplayr 268
 
2362 hidnplayr 269
	DEBUGF	1,"Got window option\n"
1733 hidnplayr 270
 
2362 hidnplayr 271
	;;;;;
1733 hidnplayr 272
       @@:
2362 hidnplayr 273
	add	edi, 3
274
	jmp	.opt_loop
1733 hidnplayr 275
 
276
 
277
  .opt_timestamp:
2362 hidnplayr 278
	cmp	byte [esi+1], 10
279
	jne	.no_options
1733 hidnplayr 280
 
2362 hidnplayr 281
	DEBUGF	1,"Got timestamp option\n"
1733 hidnplayr 282
 
2362 hidnplayr 283
	;;;;;
1733 hidnplayr 284
 
2362 hidnplayr 285
	add	esi, 10
286
	jmp	.opt_loop
1733 hidnplayr 287
 
288
  .no_options:
289
 
290
 
291
 
292
 
293
 
294
 
295
;-----------------------------------------------------------------------
296
; Time to do some header prediction (Original Principle by Van Jacobson)
297
 
298
; There are two common cases for an uni-directional data transfer.
299
;
300
; General rule: the packets has no control flags, is in-sequence,
301
;   window width didnt change and we're not retransmitting.
302
;
303
; Second rules:
304
;  -  If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
305
;      In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
306
;
307
;  -  If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
308
;      If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
309
 
2362 hidnplayr 310
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
311
	jnz	.not_uni_xfer
1733 hidnplayr 312
 
2362 hidnplayr 313
	test	[edx + TCP_header.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
314
	jnz	.not_uni_xfer
1733 hidnplayr 315
 
2362 hidnplayr 316
	test	[edx + TCP_header.Flags], TH_ACK
317
	jz	.not_uni_xfer
1733 hidnplayr 318
 
2362 hidnplayr 319
	mov	eax, [edx + TCP_header.SequenceNumber]
320
	cmp	eax, [ebx + TCP_SOCKET.RCV_NXT]
321
	jne	.not_uni_xfer
1733 hidnplayr 322
 
2362 hidnplayr 323
	mov	eax, dword [edx + TCP_header.Window]
324
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
325
	jne	.not_uni_xfer
1733 hidnplayr 326
 
2362 hidnplayr 327
	mov	eax, [ebx + TCP_SOCKET.SND_NXT]
328
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
329
	jne	.not_uni_xfer
1733 hidnplayr 330
 
331
;---------------------------------------
332
; check if we are sender in the uni-xfer
333
 
334
; If the following 4 conditions are all true, this segment is a pure ACK.
335
;
336
; - The segment contains no data.
2362 hidnplayr 337
	test	ecx, ecx
338
	jnz	.not_sender
1733 hidnplayr 339
 
340
; - The congestion window is greater than or equal to the current send window.
341
;     This test is true only if the window is fully open, that is, the connection is not in the middle of slow start or congestion avoidance.
2362 hidnplayr 342
	mov	eax, [ebx + TCP_SOCKET.SND_CWND]
343
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
344
	jb	.not_uni_xfer
1733 hidnplayr 345
 
346
; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
2362 hidnplayr 347
	mov	eax, [edx + TCP_header.AckNumber]
348
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
349
	ja	.not_uni_xfer
1733 hidnplayr 350
 
351
; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
2362 hidnplayr 352
	sub	eax, [ebx + TCP_SOCKET.SND_UNA]
353
	jbe	.not_uni_xfer
1733 hidnplayr 354
 
2362 hidnplayr 355
	DEBUGF	1,"Header prediction: we are sender\n"
1733 hidnplayr 356
 
357
;---------------------------------
358
; Packet is a pure ACK, process it
359
 
360
; Update RTT estimators
361
 
1763 hidnplayr 362
;;; TODO
363
 
1733 hidnplayr 364
; Delete acknowledged bytes from send buffer
2362 hidnplayr 365
	pusha
366
	mov	ecx, eax
367
	lea	eax, [ebx + STREAM_SOCKET.snd]
368
	call	SOCKET_ring_free
369
	popa
1733 hidnplayr 370
 
371
; update window pointers
2362 hidnplayr 372
	mov	eax, [edx + TCP_header.AckNumber]
373
	mov	[ebx + TCP_SOCKET.SND_UNA], eax
1733 hidnplayr 374
 
375
; Stop retransmit timer
2362 hidnplayr 376
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0
1733 hidnplayr 377
 
378
; Awaken waiting processes
2362 hidnplayr 379
	mov	[ebx + SOCKET.lock], 0
380
	mov	eax, ebx
381
	call	SOCKET_notify_owner
1733 hidnplayr 382
 
1763 hidnplayr 383
; Generate more output
2362 hidnplayr 384
	call	TCP_output
1733 hidnplayr 385
 
2362 hidnplayr 386
	jmp	.drop_not_locked
1763 hidnplayr 387
 
1733 hidnplayr 388
;-------------------------------------------------
389
; maybe we are the receiver in the uni-xfer then..
390
 
391
  .not_sender:
392
; - The amount of data in the segment is greater than 0 (data count is in ecx)
393
 
394
; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
2362 hidnplayr 395
	mov	eax, [edx + TCP_header.AckNumber]
396
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
397
	jne	.not_uni_xfer
1733 hidnplayr 398
 
399
; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp).
400
 
401
;;; TODO
402
 
2362 hidnplayr 403
	jnz	.not_uni_xfer
1733 hidnplayr 404
 
405
; Complete processing of received data
406
 
2362 hidnplayr 407
	DEBUGF	1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx
1733 hidnplayr 408
 
2362 hidnplayr 409
	add	[ebx + TCP_SOCKET.RCV_NXT], ecx 	; Update sequence number with number of bytes we have copied
1763 hidnplayr 410
 
2362 hidnplayr 411
	movzx	esi, [edx + TCP_header.DataOffset]
412
	add	esi, edx
413
	lea	eax, [ebx + STREAM_SOCKET.rcv]
414
	call	SOCKET_ring_write			; Add the data to the socket buffer
1733 hidnplayr 415
 
2362 hidnplayr 416
	mov	eax, ebx
417
	call	SOCKET_notify_owner
1733 hidnplayr 418
 
2362 hidnplayr 419
	or	[ebx + TCP_SOCKET.t_flags], TF_DELACK	; Set delayed ack flag
1733 hidnplayr 420
 
2362 hidnplayr 421
	jmp	.drop
1733 hidnplayr 422
 
423
 
424
 
425
 
426
 
427
 
428
;--------------------------------------------------
429
; Header prediction failed, do it the slow way
430
 
431
  .not_uni_xfer:
432
 
2362 hidnplayr 433
	DEBUGF	1,"Header prediction failed\n"
1733 hidnplayr 434
 
435
; Calculate receive window size
436
 
2362 hidnplayr 437
;        mov     eax, [ebx + STREAM_SOCKET.rcv.size]
2305 hidnplayr 438
;        neg     eax
439
;        add     eax, SOCKETBUFFSIZE
440
;        mov     edx, [ebx + TCP_SOCKET.RCV_ADV]
441
;        sub     edx, [ebx + TCP_SOCKET.RCV_NXT]
442
;        cmp     eax, edx
443
;        jae     @f
444
;        mov     eax, edx
445
;       @@:
1733 hidnplayr 446
 
2362 hidnplayr 447
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_LISTEN
448
	je	.LISTEN
1733 hidnplayr 449
 
2362 hidnplayr 450
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT
451
	je	.SYN_SENT
1733 hidnplayr 452
 
2362 hidnplayr 453
	jmp	.NOT_LISTEN_OR_SYN_SENT
1733 hidnplayr 454
 
455
 
456
 
457
;-------------
458
; Passive Open
459
 
460
align 4
461
.LISTEN:
462
 
2362 hidnplayr 463
	DEBUGF	1,"TCP state: listen\n"
1733 hidnplayr 464
 
2362 hidnplayr 465
	test	[edx + TCP_header.Flags], TH_RST	;;; TODO: kill new socket on error
466
	jnz	.drop
1733 hidnplayr 467
 
2362 hidnplayr 468
	test	[edx + TCP_header.Flags], TH_ACK
469
	jnz	.drop_with_reset
1733 hidnplayr 470
 
2362 hidnplayr 471
	test	[edx + TCP_header.Flags], TH_SYN
472
	jz	.drop
1733 hidnplayr 473
 
474
;;; TODO: check if it's a broadcast or multicast, and drop if so
475
 
2362 hidnplayr 476
	push	dword [edi + 4] 			; Ipv4 destination addres
477
	pop	[ebx + IP_SOCKET.RemoteIP]
1733 hidnplayr 478
 
2362 hidnplayr 479
	push	[edx + TCP_header.SourcePort]
480
	pop	[ebx + TCP_SOCKET.RemotePort]
1733 hidnplayr 481
 
2362 hidnplayr 482
	push	[edx + TCP_header.SequenceNumber]
483
	pop	[ebx + TCP_SOCKET.IRS]
1733 hidnplayr 484
 
2362 hidnplayr 485
	push	[TCP_sequence_num]			;;;;;
486
	add	[TCP_sequence_num], 64000 / 2
487
	pop	[ebx + TCP_SOCKET.ISS]
1733 hidnplayr 488
 
2362 hidnplayr 489
	push	[ebx + TCP_SOCKET.ISS]
490
	pop	[ebx + TCP_SOCKET.SND_NXT]
1733 hidnplayr 491
 
2362 hidnplayr 492
	TCP_sendseqinit ebx
493
	TCP_rcvseqinit ebx
1733 hidnplayr 494
 
2362 hidnplayr 495
	mov	[ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
496
	mov	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
497
	mov	[ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval  ;;;; macro
1838 hidnplayr 498
 
2362 hidnplayr 499
	lea	eax, [ebx + STREAM_SOCKET.snd]
500
	call	SOCKET_ring_create
1733 hidnplayr 501
 
2362 hidnplayr 502
	lea	eax, [ebx + STREAM_SOCKET.rcv]
503
	call	SOCKET_ring_create
1733 hidnplayr 504
 
1838 hidnplayr 505
;;;        call    SOCKET_notify_owner
1733 hidnplayr 506
 
2362 hidnplayr 507
	jmp	.trim_then_step6
508
 
1733 hidnplayr 509
 
510
 
511
 
512
 
513
 
514
 
515
 
516
 
1838 hidnplayr 517
 
1733 hidnplayr 518
;------------
519
; Active Open
520
 
521
align 4
522
.SYN_SENT:
523
 
2362 hidnplayr 524
	DEBUGF	1,"TCP state: syn_sent\n"
1733 hidnplayr 525
 
2362 hidnplayr 526
	test	[edx + TCP_header.Flags], TH_ACK
527
	jz	@f
1733 hidnplayr 528
 
2362 hidnplayr 529
	mov	eax, [edx + TCP_header.AckNumber]
530
	cmp	eax, [ebx + TCP_SOCKET.ISS]
531
	jbe	.drop_with_reset
1733 hidnplayr 532
 
2362 hidnplayr 533
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
534
	ja	.drop_with_reset
1733 hidnplayr 535
       @@:
536
 
2362 hidnplayr 537
	test	[edx + TCP_header.Flags], TH_RST
538
	jz	@f
1733 hidnplayr 539
 
2362 hidnplayr 540
	test	[edx + TCP_header.Flags], TH_ACK
541
	jz	.drop
1733 hidnplayr 542
 
2362 hidnplayr 543
	mov	eax, ebx
544
	mov	ebx, ECONNREFUSED
545
	call	TCP_drop
1733 hidnplayr 546
 
2362 hidnplayr 547
	jmp	.drop
1733 hidnplayr 548
       @@:
549
 
2362 hidnplayr 550
	test	[edx + TCP_header.Flags], TH_SYN
551
	jz	.drop
1733 hidnplayr 552
 
553
; at this point, segment seems to be valid
554
 
2362 hidnplayr 555
	test	[edx + TCP_header.Flags], TH_ACK
556
	jz	.no_syn_ack
1733 hidnplayr 557
 
558
; now, process received SYN in response to an active open
559
 
2362 hidnplayr 560
	mov	eax, [edx + TCP_header.AckNumber]
561
	mov	[ebx + TCP_SOCKET.SND_UNA], eax
562
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
563
	jbe	@f
564
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
1733 hidnplayr 565
       @@:
566
 
567
  .no_syn_ack:
568
 
2362 hidnplayr 569
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0	; disable retransmission
1733 hidnplayr 570
 
2362 hidnplayr 571
	push	[edx + TCP_header.SequenceNumber]
572
	pop	[ebx + TCP_SOCKET.IRS]
1733 hidnplayr 573
 
2362 hidnplayr 574
	TCP_rcvseqinit ebx
1733 hidnplayr 575
 
2362 hidnplayr 576
	or	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1733 hidnplayr 577
 
2362 hidnplayr 578
	mov	eax, [ebx + TCP_SOCKET.SND_UNA]
579
	cmp	eax, [ebx + TCP_SOCKET.ISS]
580
	jbe	.simultaneous_open
1733 hidnplayr 581
 
2362 hidnplayr 582
	test	[edx + TCP_header.Flags], TH_ACK
583
	jz	.simultaneous_open
1733 hidnplayr 584
 
2362 hidnplayr 585
	DEBUGF	1,"TCP: active open\n"
1733 hidnplayr 586
 
587
;;; TODO: update stats
588
 
589
; set socket state to connected
590
 
2362 hidnplayr 591
	mov	[ebx + SOCKET.state],1	;;;; FIXME
1733 hidnplayr 592
 
2362 hidnplayr 593
	mov	[ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1733 hidnplayr 594
 
595
;;; TODO: check if we should scale the connection (567-572)
596
;;; TODO: update RTT estimators
597
 
2362 hidnplayr 598
	jmp	.trim_then_step6
1733 hidnplayr 599
 
600
  .simultaneous_open:
601
 
2362 hidnplayr 602
	DEBUGF	1,"TCP: simultaneous open\n"
1733 hidnplayr 603
; We have received a syn but no ACK, so we are having a simultaneous open..
2362 hidnplayr 604
	mov	[ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
1733 hidnplayr 605
 
606
 
607
 
608
 
609
 
610
 
611
 
612
;-------------------------------------
613
; Common processing for receipt of SYN
614
 
615
  .trim_then_step6:
616
 
2362 hidnplayr 617
	inc	[edx + TCP_header.SequenceNumber]
1733 hidnplayr 618
 
619
;;; TODO: Drop any received data that follows receive window (590)
620
 
2362 hidnplayr 621
	mov	eax, [edx + TCP_header.SequenceNumber]
622
	mov	[ebx + TCP_SOCKET.RCV_UP], eax
623
	dec	eax
624
	mov	[ebx + TCP_SOCKET.SND_WL1], eax
1733 hidnplayr 625
 
2362 hidnplayr 626
	jmp	.ack_processed
1733 hidnplayr 627
 
628
 
629
 
630
 
631
 
632
 
633
 
634
 
635
  .NOT_LISTEN_OR_SYN_SENT:
636
 
2362 hidnplayr 637
	DEBUGF	1,"Slow TCP input: not listen or syn_sent state\n"
1733 hidnplayr 638
 
639
;--------------------------------------------
640
; Protection Against Wrapped Sequence Numbers
641
 
642
; First, check if timestamp is present
643
 
1763 hidnplayr 644
;;;; TODO 602
1733 hidnplayr 645
 
646
; Then, check if at least some bytes of data are within window
647
 
648
;;;; TODO
649
 
650
 
651
 
652
 
653
 
654
 
655
 
656
 
657
;----------------------------
658
; trim any data not in window
659
 
660
; check for duplicate data at beginning of segment
661
 
2362 hidnplayr 662
	mov	eax, [ebx + TCP_SOCKET.RCV_NXT]
663
	sub	eax, [edx + TCP_header.SequenceNumber]
664
	jbe	.no_duplicate
1733 hidnplayr 665
 
2362 hidnplayr 666
	DEBUGF	1,"Uh oh.. %u bytes of duplicate data!\n", eax
1763 hidnplayr 667
 
2362 hidnplayr 668
	test	[edx + TCP_header.Flags], TH_SYN
669
	jz	.no_dup_syn
1733 hidnplayr 670
 
671
; remove duplicate syn
672
 
2362 hidnplayr 673
	and	[edx + TCP_header.Flags], not (TH_SYN)
674
	inc	[edx + TCP_header.SequenceNumber]
1733 hidnplayr 675
 
2362 hidnplayr 676
	cmp	[edx + TCP_header.UrgentPointer], 1
677
	jbe	@f
678
	dec	[edx + TCP_header.UrgentPointer]
679
	jmp	.dup_syn
1733 hidnplayr 680
       @@:
2362 hidnplayr 681
	and	[edx + TCP_header.Flags], not (TH_URG)
1838 hidnplayr 682
  .dup_syn:
2362 hidnplayr 683
	dec	eax
1763 hidnplayr 684
  .no_dup_syn:
1733 hidnplayr 685
 
686
; eax holds number of bytes to drop
687
 
688
; Check for entire duplicate packet
689
 
2362 hidnplayr 690
	cmp	eax, ecx
691
	jae	.duplicate
1733 hidnplayr 692
 
2362 hidnplayr 693
	DEBUGF	1,"Going to drop %u out of %u bytes\n", eax, ecx
1830 hidnplayr 694
 
1733 hidnplayr 695
;;; TODO: apply figure 28.30
696
 
697
; Check for duplicate FIN
698
 
2362 hidnplayr 699
	test	[edx + TCP_header.Flags], TH_FIN
700
	jz	@f
701
	inc	ecx
702
	cmp	eax, ecx
703
	dec	ecx
704
	jne	@f
1733 hidnplayr 705
 
2362 hidnplayr 706
	mov	eax, ecx
707
	and	[edx + TCP_header.Flags], not TH_FIN
708
	or	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
709
	jmp	.no_duplicate
1733 hidnplayr 710
       @@:
711
 
712
; Handle the case when a bound socket connects to itself
713
; Allow packets with a SYN and an ACKto continue with the processing
714
 
715
;-------------------------------------
716
; Generate duplicate ACK if nescessary
717
 
718
; This code also handles simultaneous half-open or self-connects
719
 
2362 hidnplayr 720
	test	eax, eax
721
	jnz	.drop_after_ack
1733 hidnplayr 722
 
2362 hidnplayr 723
	cmp	[edx + TCP_header.Flags], TH_ACK
724
	jz	.drop_after_ack
1733 hidnplayr 725
 
726
  .duplicate:
727
 
2362 hidnplayr 728
	DEBUGF	1,"Duplicate received\n"
1733 hidnplayr 729
 
730
;----------------------------------------
731
; Update statistics for duplicate packets
732
 
733
;;; TODO
734
 
2362 hidnplayr 735
	jmp	.drop_after_ack
1733 hidnplayr 736
 
737
  .no_duplicate:
738
 
739
;-----------------------------------------------
740
; Remove duplicate data and update urgent offset
741
 
2362 hidnplayr 742
	add	[edx + TCP_header.SequenceNumber], eax
1733 hidnplayr 743
 
744
;;; TODO
745
 
2362 hidnplayr 746
	sub	[edx + TCP_header.UrgentPointer], ax
747
	ja	@f
1733 hidnplayr 748
 
2362 hidnplayr 749
	and	[edx + TCP_header.Flags], not (TH_URG)
750
	mov	[edx + TCP_header.UrgentPointer], 0
1733 hidnplayr 751
       @@:
752
 
753
;--------------------------------------------------
754
; Handle data that arrives after process terminates
755
 
2362 hidnplayr 756
	cmp	[ebx + SOCKET.PID], 0
757
	ja	@f
1733 hidnplayr 758
 
2362 hidnplayr 759
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
760
	jbe	@f
1733 hidnplayr 761
 
2362 hidnplayr 762
	test	ecx, ecx
763
	jz	@f
1733 hidnplayr 764
 
765
;;; Close the socket
766
;;; update stats
767
 
2362 hidnplayr 768
	jmp	.drop_with_reset
1733 hidnplayr 769
       @@:
770
 
771
;----------------------------------------
772
; Remove data beyond right edge of window
773
 
2362 hidnplayr 774
	mov	eax, [edx + TCP_header.SequenceNumber]
775
	add	eax, ecx
776
	sub	eax, [ebx + TCP_SOCKET.RCV_NXT]
777
	sub	ax, [ebx + TCP_SOCKET.RCV_WND]
1733 hidnplayr 778
 
779
; eax now holds the number of bytes to drop
780
 
2362 hidnplayr 781
	jbe	.no_excess_data
1733 hidnplayr 782
 
783
;;; TODO: update stats
784
 
2362 hidnplayr 785
	cmp	eax, ecx
786
	jb	.dont_drop_all
1733 hidnplayr 787
 
788
;;; TODO 700-736
789
 
790
  .dont_drop_all:
791
 
792
  .no_excess_data:
793
 
794
 
795
 
796
 
797
 
798
 
799
 
800
 
801
;-----------------
802
; Record timestamp
803
 
804
;;; TODO 737-746
805
 
806
 
807
 
808
 
809
 
810
;------------------
811
; Process RST flags
812
 
2362 hidnplayr 813
	test	[edx + TCP_header.Flags], TH_RST
814
	jz	.rst_skip
1733 hidnplayr 815
 
2362 hidnplayr 816
	DEBUGF	1,"Got an RST flag"
1733 hidnplayr 817
 
2362 hidnplayr 818
	mov	eax, [ebx + TCP_SOCKET.t_state]
819
	shl	eax, 2
820
	jmp	dword [eax + .rst_sw_list]
1733 hidnplayr 821
 
822
  .rst_sw_list:
2362 hidnplayr 823
	dd	.rst_skip	;TCPS_CLOSED
824
	dd	.rst_skip	;TCPS_LISTEN
825
	dd	.rst_skip	;TCPS_SYN_SENT
826
	dd	.econnrefused	;TCPS_SYN_RECEIVED
827
	dd	.econnreset	;TCPS_ESTABLISHED
828
	dd	.econnreset	;TCPS_CLOSE_WAIT
829
	dd	.econnreset	;TCPS_FIN_WAIT_1
830
	dd	.rst_close	;TCPS_CLOSING
831
	dd	.rst_close	;TCPS_LAST_ACK
832
	dd	.econnreset	;TCPS_FIN_WAIT_2
833
	dd	.rst_close	;TCPS_TIMED_WAIT
1733 hidnplayr 834
 
835
  .econnrefused:
2362 hidnplayr 836
	DEBUGF	1,"Connection refused"
1733 hidnplayr 837
 
2362 hidnplayr 838
	mov	[ebx + SOCKET.errorcode], ECONNREFUSED
839
	jmp	.close
1733 hidnplayr 840
 
841
  .econnreset:
2362 hidnplayr 842
	DEBUGF	1,"Connection reset"
1733 hidnplayr 843
 
2362 hidnplayr 844
	mov	[ebx + SOCKET.errorcode], ECONNRESET
1733 hidnplayr 845
 
1831 hidnplayr 846
    .close:
2362 hidnplayr 847
	DEBUGF	1,"Closing connection"
1733 hidnplayr 848
 
2362 hidnplayr 849
	mov	[ebx + TCP_SOCKET.t_state], TCPS_CLOSED
850
	;;; TODO: update stats
851
	mov	eax, ebx
852
	call	TCP_close
853
	jmp	.drop
1733 hidnplayr 854
 
855
  .rst_close:
2362 hidnplayr 856
	DEBUGF	1,"Closing with reset\n"
1733 hidnplayr 857
 
2362 hidnplayr 858
	mov	eax, ebx
859
	call	TCP_close
860
	jmp	.drop
1733 hidnplayr 861
 
862
 
863
 
864
 
865
 
866
 
867
 
1763 hidnplayr 868
  .rst_skip:
1733 hidnplayr 869
 
1763 hidnplayr 870
 
1733 hidnplayr 871
;--------------------------------------
872
; handle SYN-full and ACK-less segments
873
 
2362 hidnplayr 874
	test	[edx + TCP_header.Flags], TH_SYN
875
	jz	@f
1733 hidnplayr 876
 
2362 hidnplayr 877
	mov	eax, ebx
878
	mov	ebx, ECONNRESET
879
	call	TCP_drop
880
	jmp	.drop_with_reset
1733 hidnplayr 881
 
2362 hidnplayr 882
	test	[edx + TCP_header.Flags], TH_ACK
883
	jz	.drop
1733 hidnplayr 884
      @@:
885
 
886
 
887
 
888
 
889
 
890
 
891
 
892
;---------------
893
; ACK processing
894
 
2362 hidnplayr 895
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
896
	jnz	.no_syn_rcv
1733 hidnplayr 897
 
2362 hidnplayr 898
	DEBUGF	1,"TCP state = syn received\n"
1733 hidnplayr 899
 
2362 hidnplayr 900
	mov	eax, [edx + TCP_header.AckNumber]
901
	cmp	[ebx + TCP_SOCKET.SND_UNA], eax
902
	ja	.drop_with_reset
903
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
904
	ja	.drop_with_reset
1733 hidnplayr 905
 
2309 hidnplayr 906
;;; TODO: update stats
907
 
2362 hidnplayr 908
	mov	eax, ebx
909
	call	SOCKET_is_connected
910
	mov	[ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
1831 hidnplayr 911
 
912
; Do window scaling?
913
 
2362 hidnplayr 914
	test	[ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
915
	jz	@f
916
	test	[ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE
917
	jz	@f
1831 hidnplayr 918
 
2362 hidnplayr 919
	push	word [ebx + TCP_SOCKET.requested_s_scale]	; Set send and receive scale factors to the received values
920
	pop	word [ebx + TCP_SOCKET.SND_SCALE]
1831 hidnplayr 921
       @@:
922
 
2309 hidnplayr 923
;;; TODO: copy the data (if any) into the socket
1831 hidnplayr 924
 
2362 hidnplayr 925
	mov	eax, [edx + TCP_header.SequenceNumber]
926
	dec	eax
927
	mov	[ebx + TCP_SOCKET.SND_WL1], eax
928
	jmp	.not_dup_ack
1831 hidnplayr 929
 
1733 hidnplayr 930
  .no_syn_rcv:
931
 
932
; check for duplicate ACK
933
 
2362 hidnplayr 934
	mov	eax, [edx + TCP_header.AckNumber]
935
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
936
	ja	.not_dup_ack
1733 hidnplayr 937
 
2362 hidnplayr 938
	test	ecx, ecx
939
	jnz	.reset_dupacks
1733 hidnplayr 940
 
2362 hidnplayr 941
	mov	eax, dword [edx + TCP_header.Window]
942
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
943
	jne	.reset_dupacks
1733 hidnplayr 944
 
2362 hidnplayr 945
	DEBUGF	1,"Processing a duplicate ACK..\n"
1733 hidnplayr 946
 
2362 hidnplayr 947
	cmp	[ebx + TCP_SOCKET.timer_retransmission], 10000 ;;;;  FIXME
948
	ja	@f
1733 hidnplayr 949
 
2362 hidnplayr 950
	mov	eax, [edx + TCP_header.AckNumber]
951
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
952
	je	.dup_ack
1763 hidnplayr 953
 
954
       @@:
2362 hidnplayr 955
	mov	[ebx + TCP_SOCKET.t_dupacks], 0
956
	jmp	.not_dup_ack
1763 hidnplayr 957
 
958
  .dup_ack:
2362 hidnplayr 959
	inc	[ebx + TCP_SOCKET.t_dupacks]
960
	cmp	[ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
961
	jne	.no_re_xmit
1763 hidnplayr 962
 
2362 hidnplayr 963
	push	[ebx + TCP_SOCKET.SND_NXT]		; >>>>
1763 hidnplayr 964
 
2362 hidnplayr 965
	mov	eax, [ebx + TCP_SOCKET.SND_WND]
966
	cmp	eax, [ebx + TCP_SOCKET.SND_CWND]
967
	cmovg	eax, [ebx + TCP_SOCKET.SND_CWND]
968
	shr	eax, 1
969
	push	edx
970
	xor	edx, edx
971
	div	[ebx + TCP_SOCKET.t_maxseg]
972
	cmp	eax, 2
973
	jae	@f
974
	mov	ax, 2
1763 hidnplayr 975
       @@:
2362 hidnplayr 976
	mul	[ebx + TCP_SOCKET.t_maxseg]
977
	pop	edx
978
	mov	[ebx + TCP_SOCKET.SND_SSTHRESH], eax
1763 hidnplayr 979
 
2362 hidnplayr 980
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0	; turn off retransmission timer
981
	mov	[ebx + TCP_SOCKET.t_rtt], 0
982
	mov	eax, [edx + TCP_header.AckNumber]
983
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
984
	mov	eax, [ebx + TCP_SOCKET.t_maxseg]
985
	mov	[ebx + TCP_SOCKET.SND_CWND], eax
1763 hidnplayr 986
 
2362 hidnplayr 987
	mov	eax, ebx
988
	call	TCP_output					; retransmit missing segment
1763 hidnplayr 989
 
2362 hidnplayr 990
	push	edx
991
	xor	edx, edx
992
	mov	eax, [ebx + TCP_SOCKET.t_maxseg]
993
	mul	[ebx + TCP_SOCKET.t_dupacks]
994
	pop	edx
995
	add	eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
996
	mov	[ebx + TCP_SOCKET.SND_CWND], eax
1763 hidnplayr 997
 
2362 hidnplayr 998
	pop	eax					; <<<<
999
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
1000
	jb	@f
1001
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
1763 hidnplayr 1002
       @@:
1003
 
2362 hidnplayr 1004
	jmp	.drop
1733 hidnplayr 1005
 
1006
 
1763 hidnplayr 1007
  .no_re_xmit:
2362 hidnplayr 1008
	jbe	.not_dup_ack
1733 hidnplayr 1009
 
2362 hidnplayr 1010
	DEBUGF	1,"Increasing congestion window\n"
1733 hidnplayr 1011
 
2362 hidnplayr 1012
	mov	eax, [ebx + TCP_SOCKET.t_maxseg]
1013
	add	[ebx + TCP_SOCKET.SND_CWND], eax
1733 hidnplayr 1014
 
2362 hidnplayr 1015
	mov	eax, ebx
1016
	call	TCP_output
1733 hidnplayr 1017
 
2362 hidnplayr 1018
	jmp	.drop
1733 hidnplayr 1019
 
1020
 
1021
 
1763 hidnplayr 1022
 
1023
 
1024
 
1025
  .not_dup_ack:
1026
 
1733 hidnplayr 1027
;-------------------------------------------------
1028
; If the congestion window was inflated to account
1029
; for the other side's cached packets, retract it
1030
 
2362 hidnplayr 1031
	mov	eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
1032
	cmp	eax, [ebx + TCP_SOCKET.SND_CWND]
1033
	ja	@f
1034
	cmp	[ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
1035
	jbe	@f
1036
	mov	[ebx + TCP_SOCKET.SND_CWND], eax
1763 hidnplayr 1037
       @@:
1733 hidnplayr 1038
 
2362 hidnplayr 1039
	mov	[ebx + TCP_SOCKET.t_dupacks], 0
1733 hidnplayr 1040
 
2362 hidnplayr 1041
	mov	eax, [edx + TCP_header.AckNumber]
1042
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
1043
	jbe	@f
1733 hidnplayr 1044
 
2362 hidnplayr 1045
	;;; TODO: update stats
1046
	jmp	.drop_after_ack
1733 hidnplayr 1047
 
1763 hidnplayr 1048
       @@:
1733 hidnplayr 1049
 
2362 hidnplayr 1050
	mov	edi, [edx + TCP_header.AckNumber]
1051
	sub	edi, [ebx + TCP_SOCKET.SND_UNA] 	; now we got the number of acked bytes in edi
1733 hidnplayr 1052
 
2362 hidnplayr 1053
	;;; TODO: update stats
1733 hidnplayr 1054
 
1055
 
2362 hidnplayr 1056
	DEBUGF	1,"We have an acceptable ACK of %x bytes\n", esi
1763 hidnplayr 1057
 
1058
 
1059
 
1060
 
1061
 
1062
 
1733 hidnplayr 1063
;------------------------------------------
1064
; RTT measurements and retransmission timer
1065
 
2362 hidnplayr 1066
	;;;;; 912 - 926
1733 hidnplayr 1067
 
2362 hidnplayr 1068
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0
1733 hidnplayr 1069
 
2362 hidnplayr 1070
	mov	eax, [ebx + TCP_SOCKET.SND_MAX]
1071
	cmp	eax, [edx + TCP_header.AckNumber]
1072
	je	.all_outstanding
1073
	mov	[ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value (use a macro for it)
1733 hidnplayr 1074
  .all_outstanding:
1075
 
1076
 
1077
 
1078
 
1079
 
1080
 
1081
 
1082
;-------------------------------------------
1083
; Open congestion window in response to ACKs
1084
 
2362 hidnplayr 1085
	mov	esi, [ebx + TCP_SOCKET.SND_CWND]
1086
	mov	eax, [ebx + TCP_SOCKET.t_maxseg]
1733 hidnplayr 1087
 
2362 hidnplayr 1088
	cmp	esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
1089
	jbe	@f
1090
	push	edx
1091
	push	eax
1092
	mul	eax
1093
	div	esi
1094
	pop	edx
1095
	shr	edx, 3
1096
	add	eax, edx
1097
	pop	edx
1763 hidnplayr 1098
       @@:
1733 hidnplayr 1099
 
2362 hidnplayr 1100
	add	esi, eax
1733 hidnplayr 1101
 
2362 hidnplayr 1102
	push	ecx
1103
	mov	cl, [ebx + TCP_SOCKET.SND_SCALE]
1104
	mov	eax, TCP_max_win
1105
	shl	eax, cl
1106
	pop	ecx
1733 hidnplayr 1107
 
2362 hidnplayr 1108
	cmp	esi, eax
1109
	cmovg	esi, eax
1110
	mov	[ebx + TCP_SOCKET.SND_CWND], esi
1733 hidnplayr 1111
 
1112
 
1113
 
1114
 
1763 hidnplayr 1115
 
1116
 
1117
 
1733 hidnplayr 1118
;------------------------------------------
1119
; Remove acknowledged data from send buffer
1120
 
2362 hidnplayr 1121
	push	ecx edx ebx
1122
	mov	ecx, edi
1123
	lea	eax, [ebx + STREAM_SOCKET.snd]
1124
	call	SOCKET_ring_free
1125
	pop	ebx
1126
	sub	[ebx + TCP_SOCKET.SND_WND], ecx
1127
	pop	edx ecx
1733 hidnplayr 1128
 
1129
; Wake up process waiting on send buffer
1130
 
2362 hidnplayr 1131
	mov	eax, ebx
1132
	call	SOCKET_notify_owner
1733 hidnplayr 1133
 
1831 hidnplayr 1134
; Update TCPS
1733 hidnplayr 1135
 
2362 hidnplayr 1136
	mov	eax, [edx + TCP_header.AckNumber]
1137
	mov	[ebx + TCP_SOCKET.SND_UNA], eax
1733 hidnplayr 1138
 
2362 hidnplayr 1139
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
1140
	jb	@f
1141
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
1733 hidnplayr 1142
       @@:
1143
 
1144
 
2362 hidnplayr 1145
	;; TODO: use zero flag as 'ourfinisacked'
1733 hidnplayr 1146
 
1147
 
1148
 
1149
 
1150
; General ACK handling complete
1151
; Now do the state-specific ones
1152
 
2362 hidnplayr 1153
	mov	eax, [ebx + TCP_SOCKET.t_state]
1154
	jmp	dword [eax*4 + .ACK_sw_list]
1733 hidnplayr 1155
 
1156
  .ACK_sw_list:
2362 hidnplayr 1157
	dd	.ack_processed	;TCPS_CLOSED
1158
	dd	.ack_processed	;TCPS_LISTEN
1159
	dd	.ack_processed	;TCPS_SYN_SENT
1160
	dd	.ack_processed	;TCPS_SYN_RECEIVED
1161
	dd	.ack_processed	;TCPS_ESTABLISHED
1162
	dd	.ack_processed	;TCPS_CLOSE_WAIT
1163
	dd	.ack_fw1	;TCPS_FIN_WAIT_1
1164
	dd	.ack_c		;TCPS_CLOSING
1165
	dd	.ack_la 	;TCPS_LAST_ACK
1166
	dd	.ack_processed	;TCPS_FIN_WAIT_2
1167
	dd	.ack_tw 	;TCPS_TIMED_WAIT
1733 hidnplayr 1168
 
1169
 
1772 hidnplayr 1170
  .ack_fw1:
2362 hidnplayr 1171
	jz	.ack_processed
1733 hidnplayr 1172
 
2362 hidnplayr 1173
	test	[ebx + SOCKET.state], SS_CANTRCVMORE
1174
	jnz	@f
1175
	mov	eax, ebx
1176
	call	SOCKET_is_disconnected
1773 hidnplayr 1177
;;;        mov     [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle
1772 hidnplayr 1178
       @@:
1733 hidnplayr 1179
 
2362 hidnplayr 1180
	mov	[ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
1181
	jmp	.ack_processed
1733 hidnplayr 1182
 
1183
 
1772 hidnplayr 1184
  .ack_c:
2362 hidnplayr 1185
	jz	.ack_processed
1772 hidnplayr 1186
 
2362 hidnplayr 1187
	mov	[ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1188
	mov	eax, ebx
1189
	call	TCP_cancel_timers
1190
	mov	[ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1191
	mov	eax, ebx
1192
	call	SOCKET_is_disconnected
1193
	jmp	.ack_processed
1733 hidnplayr 1194
 
1195
 
1772 hidnplayr 1196
  .ack_la:
2362 hidnplayr 1197
	jz	.ack_processed
1733 hidnplayr 1198
 
1773 hidnplayr 1199
 
2362 hidnplayr 1200
	mov	eax, ebx
1201
	call	TCP_close
1202
	jmp	.drop
1733 hidnplayr 1203
 
1204
 
1772 hidnplayr 1205
  .ack_tw:
2362 hidnplayr 1206
	mov	[ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1207
	jmp	.drop_after_ack
1733 hidnplayr 1208
 
1209
 
1772 hidnplayr 1210
 
1211
 
1212
 
1213
 
1214
 
2362 hidnplayr 1215
  .reset_dupacks:		; We got a new ACK, reset duplicate ACK counter
1733 hidnplayr 1216
 
2362 hidnplayr 1217
	mov	[ebx + TCP_SOCKET.t_dupacks], 0
1733 hidnplayr 1218
 
2362 hidnplayr 1219
  .ack_processed:	; (step 6)
1733 hidnplayr 1220
 
2362 hidnplayr 1221
	DEBUGF	1,"ACK processed\n"
1733 hidnplayr 1222
 
1223
;----------------------------------------------
1224
; check if we need to update window information
1225
 
2362 hidnplayr 1226
	test	[edx + TCP_header.Flags], TH_ACK
1227
	jz	.no_window_update
1733 hidnplayr 1228
 
2362 hidnplayr 1229
	mov	eax, [ebx + TCP_SOCKET.SND_WL1]
1230
	cmp	eax, [edx + TCP_header.SequenceNumber]
1231
	jb	.update_window
1232
	ja	@f
1733 hidnplayr 1233
 
2362 hidnplayr 1234
	mov	eax, [ebx + TCP_SOCKET.SND_WL2]
1235
	cmp	eax, [edx + TCP_header.AckNumber]
1236
	jb	.update_window
1237
	ja	.no_window_update
1733 hidnplayr 1238
       @@:
1239
 
2362 hidnplayr 1240
	mov	eax, [ebx + TCP_SOCKET.SND_WL2]
1241
	cmp	eax, [edx + TCP_header.AckNumber]
1242
	jne	.no_window_update
1733 hidnplayr 1243
 
2362 hidnplayr 1244
	mov	eax, dword [edx + TCP_header.Window]
1245
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
1246
	jbe	.no_window_update
1733 hidnplayr 1247
 
1248
  .update_window:
1249
 
2362 hidnplayr 1250
	DEBUGF	1,"Updating window\n"
1733 hidnplayr 1251
 
1252
; Keep track of pure window updates
1253
 
1254
;        test    ecx, ecx
1255
;        jz      @f
1256
;
1257
;        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
2305 hidnplayr 1258
;        cmp     eax, [edx + TCP_header.AckNumber]
1733 hidnplayr 1259
;        jne     @f
1260
;
1261
;        ;; mov eax, tiwin
1262
;        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
2300 hidnplayr 1263
;        jbe     @f
1733 hidnplayr 1264
;
1265
;        ;;; update stats
1266
;
1267
;       @@:
1268
 
2362 hidnplayr 1269
	mov	eax, dword [edx + TCP_header.Window]
1270
	cmp	eax, [ebx + TCP_SOCKET.max_sndwnd]
1271
	jbe	@f
1272
	mov	[ebx + TCP_SOCKET.max_sndwnd], eax
1733 hidnplayr 1273
       @@:
2362 hidnplayr 1274
	mov	[ebx + TCP_SOCKET.SND_WND], eax
1733 hidnplayr 1275
 
2362 hidnplayr 1276
	push	[edx + TCP_header.SequenceNumber]
1277
	pop	[ebx + TCP_SOCKET.SND_WL1]
1733 hidnplayr 1278
 
2362 hidnplayr 1279
	push	[edx + TCP_header.AckNumber]
1280
	pop	[ebx + TCP_SOCKET.SND_WL2]
1733 hidnplayr 1281
 
2362 hidnplayr 1282
	;;; needoutput = 1
1733 hidnplayr 1283
 
1284
  .no_window_update:
1285
 
1286
 
1287
 
1288
 
1289
 
1290
 
1291
 
1292
;-----------------
1293
; process URG flag
1294
 
2362 hidnplayr 1295
	test	[edx + TCP_header.Flags], TH_URG
1296
	jz	.not_urgent
1733 hidnplayr 1297
 
2362 hidnplayr 1298
	cmp	[edx + TCP_header.UrgentPointer], 0
1299
	jz	.not_urgent
1733 hidnplayr 1300
 
2362 hidnplayr 1301
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1302
	je	.not_urgent
1733 hidnplayr 1303
 
1304
; Ignore bogus urgent offsets
1305
 
2362 hidnplayr 1306
	;;; 1040-1050
1733 hidnplayr 1307
 
2362 hidnplayr 1308
	movzx	eax, [edx + TCP_header.UrgentPointer]
1309
	add	eax, [ebx + STREAM_SOCKET.rcv.size]
1310
	cmp	eax, SOCKET_MAXDATA
1311
	jbe	.not_urgent
1733 hidnplayr 1312
 
2362 hidnplayr 1313
	mov	[edx + TCP_header.UrgentPointer], 0
1314
	and	[edx + TCP_header.Flags], not (TH_URG)
1315
	jmp	.do_data
1733 hidnplayr 1316
 
1317
  .not_urgent:
1318
 
1319
; processing of received urgent pointer
1320
 
2362 hidnplayr 1321
	;;; TODO (1051-1093)
1733 hidnplayr 1322
 
1323
 
1324
 
1325
 
1326
 
1327
 
1328
 
1329
 
1330
;--------------------------------
1331
; process the data in the segment
1332
 
1333
  .do_data:
1334
 
2362 hidnplayr 1335
	DEBUGF	1,"TCP: do data (%u)\n", ecx
1733 hidnplayr 1336
 
2362 hidnplayr 1337
	test	[edx + TCP_header.Flags], TH_FIN
1338
	jnz	.process_fin
1733 hidnplayr 1339
 
2362 hidnplayr 1340
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_1
1341
	jae	.dont_do_data
1733 hidnplayr 1342
 
2362 hidnplayr 1343
	test	ecx, ecx
1344
	jz	.final_processing
1733 hidnplayr 1345
 
2362 hidnplayr 1346
	DEBUGF	1,"Processing data in segment\n"
1733 hidnplayr 1347
 
1348
;; TODO: check if data is in sequence !
1349
 
2362 hidnplayr 1350
	movzx	esi, [edx + TCP_header.DataOffset]
1351
	add	esi, edx
1733 hidnplayr 1352
 
2362 hidnplayr 1353
	or	[ebx + TCP_SOCKET.t_flags], TF_DELACK
1354
	add	[ebx + TCP_SOCKET.RCV_NXT], ecx
1733 hidnplayr 1355
 
2362 hidnplayr 1356
	lea	eax, [ebx + STREAM_SOCKET.rcv]
1357
	call	SOCKET_ring_write
1733 hidnplayr 1358
 
2362 hidnplayr 1359
	mov	eax, ebx
1360
	call	SOCKET_notify_owner
1733 hidnplayr 1361
 
2362 hidnplayr 1362
	jmp	.final_processing
1733 hidnplayr 1363
 
1364
 
1365
  .dont_do_data:
1366
 
1367
 
1368
 
1369
 
1370
 
1371
 
1372
 
1373
;---------------
1374
; FIN processing
1375
 
1376
  .process_fin:
1377
 
2362 hidnplayr 1378
	DEBUGF	1,"Processing FIN\n"
1733 hidnplayr 1379
 
2362 hidnplayr 1380
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
1381
	je	.not_first_fin
1382
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_CLOSING
1383
	je	.not_first_fin
1384
	cmp	[ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
1385
	je	.not_first_fin
1774 hidnplayr 1386
 
2362 hidnplayr 1387
	DEBUGF	1,"First FIN for this connection\n"
1774 hidnplayr 1388
 
2362 hidnplayr 1389
	mov	eax, ebx
1390
	call	SOCKET_cant_recv_more
1774 hidnplayr 1391
 
2362 hidnplayr 1392
	mov	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1393
	inc	[ebx + TCP_SOCKET.RCV_NXT]
1774 hidnplayr 1394
 
1395
  .not_first_fin:
2362 hidnplayr 1396
	mov	eax, [ebx + TCP_SOCKET.t_state]
1397
	shl	eax, 2
1398
	jmp	dword [eax + .FIN_sw_list]
1733 hidnplayr 1399
 
1400
  .FIN_sw_list:
2362 hidnplayr 1401
	dd	.no_fin 	;TCPS_CLOSED
1402
	dd	.no_fin 	;TCPS_LISTEN
1403
	dd	.no_fin 	;TCPS_SYN_SENT
1404
	dd	.fin_syn_est	;TCPS_SYN_RECEIVED
1405
	dd	.fin_syn_est	;TCPS_ESTABLISHED
1406
	dd	.no_fin 	;TCPS_CLOSE_WAIT
1407
	dd	.fin_wait1	;TCPS_FIN_WAIT_1
1408
	dd	.no_fin 	;TCPS_CLOSING
1409
	dd	.no_fin 	;TCPS_LAST_ACK
1410
	dd	.fin_wait2	;TCPS_FIN_WAIT_2
1411
	dd	.fin_timed	;TCPS_TIMED_WAIT
1733 hidnplayr 1412
 
1413
  .fin_syn_est:
1414
 
2362 hidnplayr 1415
	mov	[ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
1416
	jmp	.no_fin
1733 hidnplayr 1417
 
1418
  .fin_wait1:
1419
 
2362 hidnplayr 1420
	mov	[ebx + TCP_SOCKET.t_state], TCPS_CLOSING
1421
	jmp	.no_fin
1733 hidnplayr 1422
 
1423
  .fin_wait2:
1424
 
2362 hidnplayr 1425
	mov	[ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
1426
	mov	eax, ebx
1427
	call	TCP_cancel_timers
1428
	mov	[ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1429
	call	SOCKET_is_disconnected
1430
	jmp	.no_fin
1733 hidnplayr 1431
 
1432
  .fin_timed:
2362 hidnplayr 1433
	mov	[ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
1434
	jmp	.no_fin
1733 hidnplayr 1435
 
1436
  .no_fin:
1437
 
1438
 
1439
 
1440
 
1441
 
1442
 
1443
 
1444
 
1445
;-----------------
1446
; Final processing
1447
 
1448
  .final_processing:
1449
 
2362 hidnplayr 1450
	DEBUGF	1,"Final processing\n"
1733 hidnplayr 1451
 
2362 hidnplayr 1452
	;;; if debug enabled, output packet
1733 hidnplayr 1453
 
2362 hidnplayr 1454
	;test    needoutput, needoutput
1455
	;jz      .dumpit
1733 hidnplayr 1456
 
2362 hidnplayr 1457
	test	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1458
	jz	.dumpit
1733 hidnplayr 1459
 
2362 hidnplayr 1460
	DEBUGF	1,"ACK now!\n"
1733 hidnplayr 1461
 
2362 hidnplayr 1462
	push	ebx
1463
	mov	eax, ebx
1464
	call	TCP_output
1465
	pop	ebx
1733 hidnplayr 1466
 
1467
  .dumpit:
1468
 
2362 hidnplayr 1469
	mov	[ebx + SOCKET.lock], 0
1733 hidnplayr 1470
 
2362 hidnplayr 1471
	call	kernel_free
1472
	add	esp, 4
1473
	ret
1733 hidnplayr 1474
 
1475
 
1476
 
1477
 
1478
 
1479
 
1480
 
1481
;------------------------------------------
1482
; Generate an ACK, droping incoming segment
1483
 
1484
align 4
1485
.drop_after_ack:
1486
 
2362 hidnplayr 1487
	DEBUGF	1,"Drop after ACK\n"
1733 hidnplayr 1488
 
2362 hidnplayr 1489
	test	[edx + TCP_header.Flags], TH_RST
1490
	jnz	.drop
1733 hidnplayr 1491
 
2362 hidnplayr 1492
	and	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
1733 hidnplayr 1493
 
2362 hidnplayr 1494
	mov	[ebx + SOCKET.lock], 0
1733 hidnplayr 1495
 
2362 hidnplayr 1496
	push	ebx
1838 hidnplayr 1497
;        mov     cl, TH_ACK
1498
;        call    TCP_respond_socket
2362 hidnplayr 1499
	mov	eax, ebx
1500
	call	TCP_output
1501
	pop	ebx
1733 hidnplayr 1502
 
2362 hidnplayr 1503
	call	kernel_free
1504
	add	esp, 4
1505
	ret
1733 hidnplayr 1506
 
1507
 
1508
 
1509
 
1510
 
1511
 
1512
 
1513
 
1514
;-------------------------------------------
1515
; Generate an RST, dropping incoming segment
1516
 
1517
align 4
1518
.drop_with_reset:
1519
 
2362 hidnplayr 1520
	mov	[ebx + SOCKET.lock], 0
1733 hidnplayr 1521
 
1522
.drop_with_reset_not_locked:
1523
 
2362 hidnplayr 1524
	DEBUGF	1,"Drop with reset\n"
1733 hidnplayr 1525
 
2362 hidnplayr 1526
	test	[edx + TCP_header.Flags], TH_RST
1527
	jnz	.drop
1733 hidnplayr 1528
 
2362 hidnplayr 1529
	;;; if its a multicast/broadcast, also drop
1733 hidnplayr 1530
 
2362 hidnplayr 1531
	test	[edx + TCP_header.Flags], TH_ACK
1532
	jnz	.respond_ack
1733 hidnplayr 1533
 
2362 hidnplayr 1534
	test	[edx + TCP_header.Flags], TH_SYN
1535
	jnz	.respond_syn
1733 hidnplayr 1536
 
2362 hidnplayr 1537
	call	kernel_free
1538
	add	esp, 4
1539
	ret
1733 hidnplayr 1540
 
1541
  .respond_ack:
1542
 
2362 hidnplayr 1543
	push	ebx
1544
	mov	cl, TH_RST
1545
	call	TCP_respond_socket
1546
	pop	ebx
1733 hidnplayr 1547
 
2362 hidnplayr 1548
	jmp	.destroy_new_socket
1733 hidnplayr 1549
 
1550
 
1551
  .respond_syn:
1552
 
2362 hidnplayr 1553
	push	ebx
1554
	mov	cl, TH_RST + TH_ACK
1555
	call	TCP_respond_socket
1556
	pop	ebx
1733 hidnplayr 1557
 
2362 hidnplayr 1558
	jmp	.destroy_new_socket
1733 hidnplayr 1559
 
1560
 
1561
 
1562
 
1563
 
1564
 
1565
 
1566
;-----
1567
; Drop
1568
 
1569
align 4
1570
.drop:
1571
 
2362 hidnplayr 1572
	mov	[ebx + SOCKET.lock], 0
1733 hidnplayr 1573
 
1574
.drop_not_locked:
1575
 
2362 hidnplayr 1576
	DEBUGF	1,"Dropping packet\n"
1733 hidnplayr 1577
 
2362 hidnplayr 1578
	;;;; If debugging options are enabled, output the packet somwhere
1733 hidnplayr 1579
 
1580
  .destroy_new_socket:
1581
 
2362 hidnplayr 1582
	;;;; kill the newly created socket
1733 hidnplayr 1583
 
2362 hidnplayr 1584
	call	kernel_free
1585
	add	esp, 4
1586
	ret