Subversion Repositories Kolibri OS

Rev

Rev 1719 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1719 Rev 1733
Line 14... Line 14...
14
;;          GNU GENERAL PUBLIC LICENSE                             ;;
14
;;          GNU GENERAL PUBLIC LICENSE                             ;;
15
;;             Version 2, June 1991                                ;;
15
;;             Version 2, June 1991                                ;;
16
;;                                                                 ;;
16
;;                                                                 ;;
17
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Line 18... Line 18...
18
 
18
 
Line 19... Line 19...
19
$Revision: 1719 $
19
$Revision: 1733 $
20
 
20
 
21
; Socket states
21
; Socket states
22
TCB_CLOSED		equ 0
22
TCB_CLOSED		equ 0
Line 118... Line 118...
118
	mov	[TCP_sequence_num], eax
118
	mov	[TCP_sequence_num], eax
Line 119... Line 119...
119
 
119
 
Line 120... Line -...
120
}
-
 
121
 
-
 
122
 
-
 
123
;----------------------
-
 
124
;
-
 
125
;
-
 
126
;----------------------
-
 
127
macro	TCP_timer_160ms {
-
 
128
 
-
 
129
local	.loop
-
 
130
local	.exit
-
 
131
 
-
 
132
	mov	eax, net_sockets
-
 
133
  .loop:
-
 
134
	mov	eax, [eax + SOCKET.NextPtr]
-
 
135
	or	eax, eax
-
 
136
	jz	.exit
-
 
137
 
-
 
138
	cmp	[eax + SOCKET.Protocol], IP_PROTO_TCP		;;; We should also check if family is AF_INET
-
 
139
	jne	.loop
-
 
140
 
-
 
141
	dec	[eax + TCP_SOCKET.timer_ack]
-
 
142
	jnz	.loop
-
 
143
 
-
 
144
	DEBUGF	1,"TCP ack for socket %x expired, time to piggyback!\n", eax
-
 
145
 
-
 
146
	push	eax
-
 
147
	call	TCP_respond_socket
-
 
148
	pop	eax
-
 
149
 
-
 
150
	jmp	.loop
-
 
151
 
-
 
152
  .exit:
-
 
153
 
-
 
154
}
-
 
155
 
-
 
156
 
-
 
157
;-----------------------------------------------------------------
-
 
158
;
-
 
159
;
-
 
160
;-----------------------------------------------------------------
-
 
161
macro	TCP_timer_640ms {
-
 
162
 
-
 
163
local	.loop
-
 
164
local	.exit
-
 
165
 
-
 
166
; Update TCP sequence number
-
 
167
 
-
 
168
	add	[TCP_sequence_num], 64000
-
 
169
 
-
 
170
; scan through all the active TCP sockets, decrementing ALL timers
-
 
171
; timers do not have the chance to wrap because of the keepalive timer will kill the socket when it expires
-
 
172
 
-
 
173
	mov	eax, net_sockets
-
 
174
  .loop:
-
 
175
	mov	eax, [eax + SOCKET.NextPtr]
-
 
176
  .check_only:
-
 
177
	or	eax, eax
-
 
178
	jz	.exit
-
 
179
 
-
 
180
	cmp	[eax + SOCKET.Protocol], IP_PROTO_TCP	  ;;; We should also check if family is AF_INET
-
 
181
	jne	.loop
-
 
182
 
-
 
183
	inc	[eax + TCP_SOCKET.t_idle]
-
 
184
	dec	[eax + TCP_SOCKET.timer_retransmission]
-
 
185
	jnz	.check_more2
-
 
186
 
-
 
187
	DEBUGF	1,"socket %x: Retransmission timer expired\n", eax
-
 
188
 
-
 
189
	push	eax
-
 
190
	call	TCP_output
-
 
191
	pop	eax
-
 
192
 
-
 
193
  .check_more2:
-
 
194
	dec	[eax + TCP_SOCKET.timer_keepalive]
-
 
195
	jnz	.check_more3
-
 
196
 
-
 
197
	DEBUGF	1,"socket %x: Keepalive expired\n", eax
-
 
198
 
-
 
199
	;;; TODO: check socket state and handle accordingly
-
 
200
 
-
 
201
  .check_more3:
-
 
202
	dec	[eax + TCP_SOCKET.timer_timed_wait]
-
 
203
	jnz	.check_more5
-
 
204
 
-
 
205
	DEBUGF	1,"socket %x: 2MSL timer expired\n", eax
-
 
206
 
-
 
207
  .check_more5:
-
 
208
	dec	[eax + TCP_SOCKET.timer_persist]
-
 
209
	jnz	.loop
-
 
210
 
-
 
211
	DEBUGF	1,"socket %x: persist timer expired\n", eax
-
 
212
 
-
 
213
	jmp	.loop
-
 
214
  .exit:
-
 
215
}
-
 
216
 
-
 
217
 
-
 
218
 
-
 
219
 
-
 
220
macro	TCP_checksum IP1, IP2 {
-
 
221
 
-
 
222
;-------------
-
 
223
; Pseudoheader
-
 
224
 
-
 
225
	; protocol type
-
 
226
	mov	edx, IP_PROTO_TCP
-
 
227
 
-
 
228
	; source address
-
 
229
	add	dl, byte [IP1+1]
-
 
230
	adc	dh, byte [IP1+0]
-
 
231
	adc	dl, byte [IP1+3]
-
 
232
	adc	dh, byte [IP1+2]
-
 
233
 
-
 
234
	; destination address
-
 
235
	adc	dl, byte [IP2+1]
-
 
236
	adc	dh, byte [IP2+0]
-
 
237
	adc	dl, byte [IP2+3]
-
 
238
	adc	dh, byte [IP2+2]
-
 
239
 
-
 
240
	; size
-
 
241
	adc	dl, cl
-
 
242
	adc	dh, ch
-
 
243
 
-
 
244
;---------------------
-
 
245
; Real header and data
-
 
246
 
-
 
247
	push	esi
-
 
248
	call	checksum_1
-
 
249
	call	checksum_2
-
 
250
	pop	esi
-
 
251
 
-
 
252
}	; returns in dx only
-
 
253
 
-
 
254
 
-
 
255
macro	TCP_sendseqinit ptr {
-
 
256
 
-
 
257
	push	edi			;;;; i dont like this static use of edi
-
 
258
	mov	edi, [ptr + TCP_SOCKET.ISS]
-
 
259
	mov	[ptr + TCP_SOCKET.SND_UP], edi
-
 
260
	mov	[ptr + TCP_SOCKET.SND_MAX], edi
-
 
261
	mov	[ptr + TCP_SOCKET.SND_NXT], edi
-
 
262
	mov	[ptr + TCP_SOCKET.SND_UNA], edi
-
 
263
	pop	edi
-
 
264
 
-
 
265
}
-
 
266
 
-
 
267
macro	TCP_rcvseqinit ptr {
-
 
268
 
-
 
269
	push	edi
-
 
270
	mov	edi, [ptr + TCP_SOCKET.IRS]
-
 
271
	inc	edi
-
 
272
	mov	[ptr + TCP_SOCKET.RCV_NXT], edi
-
 
273
	mov	[ptr + TCP_SOCKET.RCV_ADV], edi
-
 
274
	pop	edi
-
 
275
 
-
 
276
}
-
 
277
 
-
 
278
 
-
 
279
 
-
 
280
;-----------------------------------------------------------------
-
 
281
;
-
 
282
; TCP_input:
-
 
283
;
-
 
284
;  IN:  [esp] = ptr to buffer
-
 
285
;       [esp+4] = buffer size
-
 
286
;       ebx = ptr to device struct
-
 
287
;       ecx = segment size
-
 
288
;       edx = ptr to TCP segment
-
 
289
;
-
 
290
;       esi = ipv4 source address
-
 
291
;       edi = ipv4 dest   address
-
 
292
;
-
 
293
;  OUT: /
-
 
294
;
-
 
295
;-----------------------------------------------------------------
-
 
296
align 4
-
 
297
TCP_input:
-
 
298
 
-
 
299
       DEBUGF  1,"TCP_input size=%u\n", ecx
-
 
300
; Offset must be greater than or equal to the size of the standard TCP header (20) and less than or equal to the TCP length.
-
 
301
 
-
 
302
	movzx	eax, [edx + TCP_segment.DataOffset]
-
 
303
	and	eax, 0xf0
-
 
304
	shr	al, 2
-
 
305
 
-
 
306
	DEBUGF	1,"headersize=%u\n", eax
-
 
307
 
-
 
308
	cmp	eax, 20
-
 
309
	jl	.drop
-
 
310
 
-
 
311
;-------------------------------
-
 
312
; Now, re-calculate the checksum
-
 
313
 
-
 
314
	push	eax ecx edx
-
 
315
	pushw	[edx + TCP_segment.Checksum]
-
 
316
	mov	[edx + TCP_segment.Checksum], 0
-
 
317
	push	esi edi
-
 
318
	mov	esi, edx
-
 
319
	TCP_checksum (esp), (esp+4)
-
 
320
	pop	esi edi ; yes, swap them (we dont need dest addr)
-
 
321
	pop	cx	; previous checksum
-
 
322
	cmp	cx, dx
-
 
323
	pop	edx ecx esi
-
 
324
	jnz	.drop
-
 
325
 
-
 
326
	DEBUGF	1,"Checksum is correct\n"
-
 
327
 
-
 
328
	sub	ecx, esi	; update packet size
-
 
329
	jl	.drop
-
 
330
	DEBUGF	1,"we got %u bytes of data\n", ecx
-
 
331
 
-
 
332
;-----------------------------------------------------------------------------------------
-
 
333
; Check if this packet has a timestamp option (We do it here so we can process it quickly)
-
 
334
 
-
 
335
	cmp	esi, 20 + 12					; Timestamp option is 12 bytes
-
 
336
	jl	.no_timestamp
-
 
337
	je	.is_ok
-
 
338
 
-
 
339
	cmp	byte [edx + TCP_segment.Data + 12], TCP_OPT_EOL ; end of option list
-
 
340
	jne	.no_timestamp
-
 
341
 
-
 
342
  .is_ok:
-
 
343
	test	[edx + TCP_segment.Flags], TH_SYN		; SYN flag must not be set
-
 
344
	jnz	.no_timestamp
-
 
345
 
-
 
346
	cmp	dword [edx + TCP_segment.Data], 0x0101080a	; Timestamp header
-
 
347
	jne	.no_timestamp
-
 
348
 
-
 
349
	DEBUGF	1,"timestamp ok\n"
-
 
350
 
-
 
351
	; TODO: Parse the option
-
 
352
	; TODO: Set a Bit in the TCP to tell all options are parsed
-
 
353
 
-
 
354
  .no_timestamp:
-
 
355
 
-
 
356
;-------------------------------------------
-
 
357
; Convert Big-endian values to little endian
-
 
358
 
-
 
359
	ntohd	[edx + TCP_segment.SequenceNumber]
-
 
360
	ntohd	[edx + TCP_segment.AckNumber]
-
 
361
 
-
 
362
	ntohw	[edx + TCP_segment.Window]
-
 
363
	ntohw	[edx + TCP_segment.UrgentPointer]
-
 
364
	ntohw	[edx + TCP_segment.SourcePort]
-
 
365
	ntohw	[edx + TCP_segment.DestinationPort]
-
 
366
 
-
 
367
;------------------------------------------------------------
-
 
368
; Next thing to do is find the TCB (thus, the socket pointer)
-
 
369
 
-
 
370
; IP Packet TCP Destination Port = local Port
-
 
371
; (IP Packet SenderAddress = Remote IP)  OR  (Remote IP = 0)
-
 
372
; (IP Packet TCP Source Port = remote Port)  OR (remote Port = 0)
-
 
373
 
-
 
374
	mov	ebx, net_sockets
-
 
375
 
-
 
376
  .socket_loop:
-
 
377
	mov	ebx, [ebx + SOCKET.NextPtr]
-
 
378
	or	ebx, ebx
-
 
379
	jz	.drop_with_reset
-
 
380
 
-
 
381
	cmp	[ebx + SOCKET.Domain], AF_INET4
-
 
382
	jne	.socket_loop
-
 
383
 
-
 
384
	cmp	[ebx + SOCKET.Protocol], IP_PROTO_TCP
-
 
385
	jne	.socket_loop
-
 
386
 
-
 
387
	mov	ax, [edx + TCP_segment.DestinationPort]
-
 
388
	cmp	[ebx + TCP_SOCKET.LocalPort], ax
-
 
389
	jne	.socket_loop
-
 
390
 
-
 
391
	mov	eax, [ebx + IP_SOCKET.RemoteIP]
-
 
392
	cmp	eax, edi			; edi is source ip from packet
-
 
393
	je	@f
-
 
394
	test	eax, eax
-
 
395
	jnz	.socket_loop
-
 
396
       @@:
-
 
397
 
-
 
398
	mov	ax, [ebx + TCP_SOCKET.RemotePort]
-
 
399
	cmp	[edx + TCP_segment.SourcePort] , ax
-
 
400
	je	.found_socket
-
 
401
	test	ax, ax
-
 
402
	jnz	.socket_loop
-
 
403
  .found_socket:
-
 
404
	DEBUGF	1,"Socket ptr: %x\n", ebx
-
 
405
 
-
 
406
; ebx now contains the pointer to the socket
-
 
407
 
-
 
408
;----------------------------
-
 
409
; Check if socket isnt closed
-
 
410
 
-
 
411
	cmp	[ebx + TCP_SOCKET.t_state], TCB_CLOSED
-
 
412
	je	.drop
-
 
413
 
-
 
414
;----------------
-
 
415
; Lock the socket
-
 
416
 
-
 
417
;;        add     ebx, SOCKET.lock ; TODO: figure out if we should lock now already
-
 
418
;;        call    wait_mutex
-
 
419
;;        sub     ebx, SOCKET.lock
-
 
420
 
-
 
421
	DEBUGF	1,"Socket locked\n"
-
 
422
 
-
 
423
;---------------------------------------
-
 
424
; unscale the window into a 32 bit value
-
 
425
 
-
 
426
	movzx	eax, [edx + TCP_segment.Window]
-
 
427
	push	ecx
-
 
428
	mov	cl, [ebx + TCP_SOCKET.SND_SCALE]
-
 
429
	shl	eax, cl
-
 
430
	mov	dword [edx + TCP_segment.Window], eax	; word after window is checksum, we dont need checksum anymore
-
 
431
	pop	ecx
-
 
432
 
-
 
433
;-----------------------------------
-
 
434
; Is this socket a listening socket?
-
 
435
 
-
 
436
	test	[ebx + SOCKET.options], SO_ACCEPTCON
-
 
437
	jz	.no_listening_socket
-
 
438
 
-
 
439
	call	SOCKET_fork
-
 
440
	jz	.drop
-
 
441
 
-
 
442
	push	[edx + TCP_segment.DestinationPort]
-
 
443
	pop	[eax + TCP_SOCKET.LocalPort]
-
 
444
 
-
 
445
	push	[edx - IPv4_Packet.DataOrOptional + IPv4_Packet.DestinationAddress]	;;; FIXME
-
 
446
	pop	[eax + IP_SOCKET.LocalIP]
-
 
447
 
-
 
448
	push	[edx - IPv4_Packet.DataOrOptional + IPv4_Packet.SourceAddress]	   ;;; FIXME
-
 
449
	pop	[eax + IP_SOCKET.RemoteIP]
-
 
450
 
-
 
451
	mov	[eax + TCP_SOCKET.t_state], TCB_LISTEN
-
 
452
 
-
 
453
	jmp	.not_uni_xfer
-
 
454
 
-
 
455
  .no_listening_socket:
-
 
456
 
-
 
457
;-------------------------------------
-
 
458
; Reset idle timer and keepalive timer
-
 
459
 
-
 
460
	mov	[ebx + TCP_SOCKET.t_idle], 0
-
 
461
	mov	[ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
-
 
462
 
-
 
463
;--------------------
-
 
464
; Process TCP options
-
 
465
 
-
 
466
	cmp	esi, 20 			; esi is headersize
-
 
467
	je	.no_options
-
 
468
 
-
 
469
	DEBUGF	1,"Segment has options\n"
-
 
470
 
-
 
471
	cmp	[ebx + TCP_SOCKET.t_state], TCB_LISTEN		; no options when in listen state
-
 
472
	jz	.not_uni_xfer					; also no header prediction
-
 
473
 
-
 
474
	lea	edi, [edx + TCP_segment.Data]
-
 
475
	lea	eax, [edx + esi]
-
 
476
 
-
 
477
  .opt_loop:
-
 
478
	cmp	edi, eax
-
 
479
	jge	.no_options
-
 
480
 
-
 
481
	cmp	byte [edi], TCP_OPT_EOL 	; end of option list?
-
 
482
	jz	.no_options
-
 
483
 
-
 
484
	cmp	byte [edi], TCP_OPT_NOP 	; nop ?
-
 
485
	jz	.opt_nop
-
 
486
 
-
 
487
	cmp	byte [edi], TCP_OPT_MAXSEG
-
 
488
	je	.opt_maxseg
-
 
489
 
-
 
490
	cmp	byte [edi], TCP_OPT_WINDOW
-
 
491
	je	.opt_window
-
 
492
 
-
 
493
	cmp	byte [edi], TCP_OPT_TIMESTAMP
-
 
494
	je	.opt_timestamp
-
 
495
 
-
 
496
	jmp	.no_options	; If we reach here, some unknown options were received, skip them all!
-
 
497
 
-
 
498
  .opt_nop:
-
 
499
	inc	edi
-
 
500
	jmp	.opt_loop
-
 
501
 
-
 
502
  .opt_maxseg:
-
 
503
	cmp	byte [edi+1], 4
-
 
504
	jne	.no_options		; error occured, ignore all options!
-
 
505
 
-
 
506
	test	[edx + TCP_segment.Flags], TH_SYN
-
 
507
	jz	@f
-
 
508
 
-
 
509
	movzx	eax, word[edi+2]
-
 
510
	rol	ax, 8
-
 
511
	DEBUGF	1,"Maxseg: %u\n", ax
-
 
512
 
-
 
513
	mov	[ebx + TCP_SOCKET.t_maxseg], eax
-
 
514
 
-
 
515
       @@:
-
 
516
	add	edi, 4
-
 
517
	jmp	.opt_loop
-
 
518
 
-
 
519
 
-
 
520
  .opt_window:
-
 
521
	cmp	byte [edi+1], 3
-
 
522
	jne	.no_options
-
 
523
 
-
 
524
	test	[edx + TCP_segment.Flags], TH_SYN
-
 
525
	jz	@f
-
 
526
 
-
 
527
	DEBUGF	1,"Got window option\n"
-
 
528
 
-
 
529
	;;;;;
-
 
530
       @@:
-
 
531
	add	edi, 3
-
 
532
	jmp	.opt_loop
-
 
533
 
-
 
534
 
-
 
535
  .opt_timestamp:
-
 
536
	cmp	byte [edi+1], 10
-
 
537
	jne	.no_options
-
 
538
 
-
 
539
	DEBUGF	1,"Got timestamp option\n"
-
 
540
 
-
 
541
	;;;;;
-
 
542
 
-
 
543
	add	edi, 10
-
 
544
	jmp	.opt_loop
-
 
545
 
-
 
546
  .no_options:
-
 
547
 
-
 
548
;-----------------------------------------------------------------------
-
 
549
; Time to do some header prediction (Original Principle by Van Jacobson)
-
 
550
 
-
 
551
; There are two common cases for an uni-directional data transfer.
-
 
552
;
-
 
553
; General rule: the packets has no control flags, is in-sequence,
-
 
554
;   window width didnt change and we're not retransmitting.
-
 
555
;
-
 
556
; Second rules:
-
 
557
;  -  If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
-
 
558
;      In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
-
 
559
;
-
 
560
;  -  If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
-
 
561
;      If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
-
 
562
 
-
 
563
	cmp	[ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED
-
 
564
	jnz	.not_uni_xfer
-
 
565
 
-
 
566
	test	[edx + TCP_segment.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
-
 
567
	jnz	.not_uni_xfer
-
 
568
 
-
 
569
	test	[edx + TCP_segment.Flags], TH_ACK
-
 
570
	jz	.not_uni_xfer
-
 
571
 
-
 
572
	mov	eax, [edx + TCP_segment.SequenceNumber]
-
 
573
	cmp	eax, [ebx + TCP_SOCKET.RCV_NXT]
-
 
574
	jne	.not_uni_xfer
-
 
575
	DEBUGF	1,"TCP_segment.window=%u\n", [edx + TCP_segment.Window]:4
-
 
576
	DEBUGF	1,"TCP_SOCKET.SND_WND=%u\n", [ebx + TCP_SOCKET.SND_WND]:4
-
 
577
	mov	eax, dword [edx + TCP_segment.Window]
-
 
578
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
-
 
579
	jne	.not_uni_xfer
-
 
580
 
-
 
581
	mov	eax, [ebx + TCP_SOCKET.SND_NXT]
-
 
582
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
-
 
583
	jne	.not_uni_xfer
-
 
584
 
-
 
585
;---------------------------------------
-
 
586
; check if we are sender in the uni-xfer
-
 
587
 
-
 
588
; If the following 4 conditions are all true, this segment is a pure ACK.
-
 
589
;
-
 
590
; - The segment contains no data.
-
 
591
	test	ecx, ecx
-
 
592
	jnz	.not_sender
-
 
593
 
-
 
594
; - The congestion window is greater than or equal to the current send window.
-
 
595
;     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.
-
 
596
	mov	eax, [ebx + TCP_SOCKET.SND_CWND]
-
 
597
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
-
 
598
	jl	.not_uni_xfer
-
 
599
 
-
 
600
; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
-
 
601
	mov	eax, [edx + TCP_segment.AckNumber]
-
 
602
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
-
 
603
	jg	.not_uni_xfer
-
 
604
 
-
 
605
; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
-
 
606
	sub	eax, [ebx + TCP_SOCKET.SND_UNA]
-
 
607
	jle	.not_uni_xfer
-
 
608
 
-
 
609
	DEBUGF	1,"Header prediction: we are sender\n"
-
 
610
 
-
 
611
;---------------------------------
-
 
612
; Packet is a pure ACK, process it
-
 
613
 
-
 
614
; Update RTT estimators
-
 
615
 
-
 
616
; Delete acknowledged bytes from send buffer
-
 
617
	pusha
-
 
618
	mov	ecx, eax
-
 
619
	lea	eax, [ebx + STREAM_SOCKET.snd]
-
 
620
	call	SOCKET_ring_free
-
 
621
	popa
-
 
622
 
-
 
623
; update window pointers
-
 
624
	mov	eax, [edx + TCP_segment.AckNumber]
-
 
625
	dec	eax
-
 
626
	mov	[ebx + TCP_SOCKET.SND_WL1], eax
-
 
627
 
-
 
628
; Stop retransmit timer
-
 
629
	mov	[ebx + TCP_SOCKET.timer_ack], 0
-
 
630
 
-
 
631
; Awaken waiting processes
-
 
632
	mov	eax, ebx
-
 
633
	call	SOCKET_notify_owner
-
 
634
 
-
 
635
;; Generate more output                  FIXME
-
 
636
;;        mov     eax, ebx
-
 
637
;;        call    TCP_output
-
 
638
;;
-
 
639
;;        jmp     .drop
-
 
640
	jmp	.ack_processed
-
 
641
 
-
 
642
;-------------------------------------------------
-
 
643
; maybe we are the receiver in the uni-xfer then..
-
 
644
 
-
 
645
  .not_sender:
-
 
646
; - The amount of data in the segment is greater than 0 (data count is in ecx)
-
 
647
 
-
 
648
; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
-
 
649
	mov	eax, [edx + TCP_segment.AckNumber]
-
 
650
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
-
 
651
	jne	.not_uni_xfer
-
 
652
 
-
 
653
; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp).
-
 
654
 
-
 
655
;;;;;;;     TODO
-
 
656
 
-
 
657
	jnz	.not_uni_xfer
-
 
658
 
-
 
659
;-------------------------------------
-
 
660
; Complete processing of received data
-
 
661
 
-
 
662
	DEBUGF	1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx
-
 
663
 
-
 
664
	pusha
-
 
665
	add	esi, edx
-
 
666
	lea	eax, [ebx + STREAM_SOCKET.rcv]
-
 
667
	call	SOCKET_ring_write			; Add the data to the socket buffer
-
 
668
 
-
 
669
	mov	eax, ebx
-
 
670
	call	SOCKET_notify_owner
-
 
671
	popa
-
 
672
 
-
 
673
	add	[ebx + TCP_SOCKET.RCV_NXT], ecx 	; Update sequence number with number of bytes we have copied
-
 
674
	or	[ebx + TCP_SOCKET.t_flags], TF_DELACK	; Set delayed ack flag
-
 
675
 
-
 
676
	jmp	.drop
-
 
677
 
-
 
678
;----------------------------------------------------
-
 
679
; Header prediction failed, doing it the slow way..     ;;;;; current implementation of header prediction destroys some regs (ecx) !!
-
 
680
 
-
 
681
  .not_uni_xfer:
-
 
682
 
-
 
683
	DEBUGF	1,"Header prediction failed\n"		; time to do it the "slow" way :)
-
 
684
 
-
 
685
;------------------------------
-
 
686
; Calculate receive window size
-
 
687
 
-
 
688
	;;;;
-
 
689
 
-
 
690
	cmp	[ebx + TCP_SOCKET.t_state], TCB_LISTEN
-
 
691
	je	.LISTEN
-
 
692
 
-
 
693
	cmp	[ebx + TCP_SOCKET.t_state], TCB_SYN_SENT
-
 
694
	je	.SYN_SENT
-
 
695
 
-
 
696
;--------------------------------------------
-
 
697
; Protection Against Wrapped Sequence Numbers
-
 
698
 
-
 
699
; First, check if timestamp is present
-
 
700
 
-
 
701
;;;; TODO
-
 
702
 
-
 
703
; Then, check if at least some bytes of data are within window
-
 
704
 
-
 
705
;;;; TODO
-
 
706
 
-
 
707
	jmp	.trim_then_step6
-
 
708
 
-
 
709
;-------------
-
 
710
; Passive Open
-
 
711
 
-
 
712
align 4
-
 
713
.LISTEN:
-
 
714
 
-
 
715
	DEBUGF	1,"TCP state: listen\n"
-
 
716
 
-
 
717
	test	[edx + TCP_segment.Flags], TH_RST	;;; TODO: kill new socket on error
-
 
718
	jnz	.drop
-
 
719
 
-
 
720
	test	[edx + TCP_segment.Flags], TH_ACK
-
 
721
	jnz	.drop_with_reset
-
 
722
 
-
 
723
	test	[edx + TCP_segment.Flags], TH_SYN
-
 
724
	jz	.drop
-
 
725
 
-
 
726
 
-
 
727
	; TODO: check if it's a broadcast or multicast, and drop if so
-
 
728
 
-
 
729
;-----------------------
-
 
730
; Fill in some variables
-
 
731
 
-
 
732
	add	[TCP_sequence_num], 64000
-
 
733
 
-
 
734
	push	[edx + TCP_segment.SourcePort]
-
 
735
	pop	[eax + TCP_SOCKET.RemotePort]
-
 
736
 
-
 
737
	push	[edx + TCP_segment.SequenceNumber]
-
 
738
	pop	[eax + TCP_SOCKET.IRS]
-
 
739
 
-
 
740
	push	[eax + TCP_SOCKET.ISS]
-
 
741
	pop	[eax + TCP_SOCKET.SND_NXT]
-
 
742
 
-
 
743
	TCP_sendseqinit eax
-
 
744
	TCP_rcvseqinit eax
-
 
745
 
-
 
746
	mov	[eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
-
 
747
	mov	[eax + TCP_SOCKET.t_flags], TF_ACKNOW
-
 
748
	mov	[eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval  ;;;; macro
-
 
749
 
-
 
750
	add	eax, STREAM_SOCKET.snd
-
 
751
	call	SOCKET_ring_create
-
 
752
 
-
 
753
	add	eax, STREAM_SOCKET.rcv - STREAM_SOCKET.snd
-
 
754
	call	SOCKET_ring_create
-
 
755
 
-
 
756
	sub	eax, STREAM_SOCKET.rcv
-
 
757
 
-
 
758
	mov	[eax + SOCKET.lock], 0
-
 
759
	mov	ebx, eax	; if there is data, it must arrive in this new socket!
-
 
760
	jmp	.trim_then_step6
-
 
761
 
-
 
762
 
-
 
763
;------------
-
 
764
; Active Open
-
 
765
 
-
 
766
align 4
-
 
767
.SYN_SENT:
-
 
768
 
-
 
769
	DEBUGF	1,"TCP state: syn_sent\n"
-
 
770
 
-
 
771
	test	[edx + TCP_segment.Flags], TH_ACK
-
 
772
	jz	@f
-
 
773
 
-
 
774
	mov	eax, [edx + TCP_segment.AckNumber]
-
 
775
	cmp	eax, [ebx + TCP_SOCKET.ISS]
-
 
776
	jle	.drop_with_reset
-
 
777
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
-
 
778
	jg	.drop_with_reset
-
 
779
       @@:
-
 
780
 
-
 
781
	test	[edx + TCP_segment.Flags], TH_RST
-
 
782
	jz	@f
-
 
783
 
-
 
784
	test	[edx + TCP_segment.Flags], TH_ACK
-
 
785
	jz	.drop
-
 
786
 
-
 
787
	mov	eax, ebx
-
 
788
	mov	ebx, ECONNREFUSED
-
 
789
	call	TCP_drop
-
 
790
 
-
 
791
	jmp	.drop
-
 
792
       @@:
-
 
793
 
-
 
794
	test	[edx + TCP_segment.Flags], TH_SYN
-
 
795
	jz	.drop
-
 
796
 
-
 
797
; at this point, segment seems to be valid
-
 
798
 
-
 
799
	test	[edx + TCP_segment.Flags], TH_ACK
-
 
800
	jz	.no_syn_ack
-
 
801
 
-
 
802
; now, process received SYN in response to an active open
-
 
803
 
-
 
804
	mov	eax, [edx + TCP_segment.AckNumber]
-
 
805
	mov	[ebx + TCP_SOCKET.SND_UNA], eax
-
 
806
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
-
 
807
	jle	@f
-
 
808
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
-
 
809
       @@:
-
 
810
 
-
 
811
  .no_syn_ack:
-
 
812
 
-
 
813
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0	; disable retransmission
-
 
814
 
-
 
815
	push	[edx + TCP_segment.SequenceNumber]
-
 
816
	pop	[ebx + TCP_SOCKET.IRS]
-
 
817
 
-
 
818
	TCP_rcvseqinit ebx
-
 
819
 
-
 
820
	mov	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
-
 
821
 
-
 
822
	mov	eax, [ebx + TCP_SOCKET.SND_UNA]
-
 
823
	cmp	eax, [ebx + TCP_SOCKET.ISS]
-
 
824
	jle	.simultaneous_open
-
 
825
 
-
 
826
	test	[edx + TCP_segment.Flags], TH_ACK
-
 
827
	jz	.simultaneous_open
-
 
828
 
-
 
829
	DEBUGF	1,"TCP: active open\n"
-
 
830
 
-
 
831
; TODO: update stats
-
 
832
; TODO: set general socket state to connected
-
 
833
 
-
 
834
	mov	[ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED
-
 
835
 
-
 
836
; TODO: check if we should scale the connection (567-572)
-
 
837
; TODO: update RTT estimators
-
 
838
 
-
 
839
	jmp	.trimthenstep6
-
 
840
 
-
 
841
  .simultaneous_open:
-
 
842
 
-
 
843
	DEBUGF	1,"TCP: simultaneous open\n"
-
 
844
; We have received a syn but no ACK, so we are having a simultaneous open..
-
 
845
	mov	[ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
-
 
846
 
-
 
847
;-------------------------------------
-
 
848
; Common processing for receipt of SYN
-
 
849
 
-
 
850
  .trimthenstep6:
-
 
851
 
-
 
852
	inc	[edx + TCP_segment.SequenceNumber]
-
 
853
 
-
 
854
	cmp	cx, [ebx + TCP_SOCKET.RCV_WND]
-
 
855
	jle	@f
-
 
856
 
-
 
857
	movzx	eax, cx
-
 
858
	sub	ax, [ebx + TCP_SOCKET.RCV_WND]
-
 
859
	; TODO: 592
-
 
860
	mov	cx, [ebx + TCP_SOCKET.RCV_WND]
-
 
861
	; TODO...
-
 
862
       @@:
-
 
863
	;;;;;
-
 
864
	jmp	.ack_processed
-
 
865
 
-
 
866
 
-
 
867
  .trim_then_step6:
-
 
868
 
-
 
869
;----------------------------
-
 
870
; trim any data not in window
-
 
871
 
-
 
872
	DEBUGF	1,"Trimming window\n"
-
 
873
 
-
 
874
	mov	eax, [ebx + TCP_SOCKET.RCV_NXT]
-
 
875
	sub	eax, [edx + TCP_segment.SequenceNumber]
-
 
876
	jz	.no_duplicate
-
 
877
 
-
 
878
	test	[edx + TCP_segment.Flags], TH_SYN
-
 
879
	jz	.no_drop
-
 
880
 
-
 
881
	and	[edx + TCP_segment.Flags], not (TH_SYN)
-
 
882
	inc	[edx + TCP_segment.SequenceNumber]
-
 
883
 
-
 
884
	cmp	[edx + TCP_segment.UrgentPointer], 1
-
 
885
	jl	@f
-
 
886
 
-
 
887
	dec	[edx + TCP_segment.UrgentPointer]
-
 
888
 
-
 
889
	jmp	.no_drop
-
 
890
       @@:
-
 
891
 
-
 
892
	and	[edx + TCP_segment.Flags], not (TH_URG)
-
 
893
	dec	eax
-
 
894
	jz	.no_duplicate
-
 
895
  .no_drop:
-
 
896
 
-
 
897
	DEBUGF	1,"Going to drop %u out of %u bytes\n", eax, ecx
-
 
898
 
-
 
899
; eax holds number of bytes to drop
-
 
900
 
-
 
901
;----------------------------------
-
 
902
; Check for entire duplicate packet
-
 
903
 
-
 
904
	cmp	eax, ecx
-
 
905
	jge	.duplicate
-
 
906
 
-
 
907
	;;; TODO: figure 28.30
-
 
908
 
-
 
909
;------------------------
-
 
910
; Check for duplicate FIN
-
 
911
 
-
 
912
	test	[edx + TCP_segment.Flags], TH_FIN
-
 
913
	jz	@f
-
 
914
	inc	ecx
-
 
915
	cmp	eax, ecx
-
 
916
	dec	ecx
-
 
917
	jne	@f
-
 
918
 
-
 
919
	mov	eax, ecx
-
 
920
	and	[edx + TCP_segment.Flags], not TH_FIN
-
 
921
	or	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
-
 
922
	jmp	.no_duplicate
-
 
923
       @@:
-
 
924
 
-
 
925
	; Handle the case when a bound socket connects to itself
-
 
926
	; Allow packets with a SYN and an ACKto continue with the processing
-
 
927
 
-
 
928
;-------------------------------------
-
 
929
; Generate duplicate ACK if nescessary
-
 
930
 
-
 
931
; This code also handles simultaneous half-open or self-connects
120
}
932
 
-
 
933
	test	eax, eax
-
 
934
	jnz	.drop_after_ack
-
 
935
 
-
 
936
	cmp	[edx + TCP_segment.Flags], TH_ACK
-
 
937
	jz	.drop_after_ack
-
 
938
 
-
 
939
  .duplicate:
-
 
940
 
-
 
941
	DEBUGF	1,"Duplicate received\n"
-
 
942
 
-
 
943
;----------------------------------------
-
 
944
; Update statistics for duplicate packets
-
 
945
 
-
 
946
	;;; TODO
-
 
947
 
-
 
948
	jmp	.drop	       ;;; DROP the packet ??
-
 
949
 
-
 
950
  .no_duplicate:
-
 
951
 
-
 
952
;-----------------------------------------------
-
 
953
; Remove duplicate data and update urgent offset
-
 
954
 
-
 
955
	add	[edx + TCP_segment.SequenceNumber], eax
-
 
956
 
-
 
957
	;;; TODO
-
 
958
 
-
 
959
	sub	[edx + TCP_segment.UrgentPointer], ax
-
 
960
	jg	@f
-
 
961
 
-
 
962
	and	[edx + TCP_segment.Flags], not (TH_URG)
-
 
963
	mov	[edx + TCP_segment.UrgentPointer], 0
-
 
964
       @@:
-
 
965
 
-
 
966
;--------------------------------------------------
-
 
967
; Handle data that arrives after process terminates
-
 
968
 
-
 
969
	cmp	[ebx + SOCKET.PID], 0
-
 
970
	jg	@f
-
 
971
 
-
 
972
	cmp	[ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT
-
 
973
	jle	@f
-
 
974
 
-
 
975
	test	ecx, ecx
-
 
976
	jz	@f
-
 
977
 
-
 
978
	;;; Close the socket
-
 
979
	;;; update stats
-
 
980
 
-
 
981
	jmp	.drop_with_reset
-
 
982
       @@:
-
 
983
 
-
 
984
;----------------------------------------
-
 
985
; Remove data beyond right edge of window
-
 
986
 
-
 
987
	mov	eax, [edx + TCP_segment.SequenceNumber]
-
 
988
	add	eax, ecx
-
 
989
	sub	eax, [ebx + TCP_SOCKET.RCV_NXT]
-
 
990
	sub	ax, [ebx + TCP_SOCKET.RCV_WND]
-
 
991
 
-
 
992
	; eax now holds the number of bytes to drop
-
 
993
 
-
 
994
	jle	.no_excess_data
-
 
995
 
-
 
996
	;;; TODO: update stats
-
 
997
 
-
 
998
	cmp	eax, ecx
-
 
999
	jl	.dont_drop_all
-
 
1000
 
-
 
1001
;;; TODO 700-736
-
 
1002
 
-
 
1003
  .dont_drop_all:
-
 
1004
 
-
 
1005
  .no_excess_data:
-
 
1006
 
-
 
1007
;-----------------
-
 
1008
; Record timestamp
-
 
1009
 
-
 
1010
	;;; TODO 737-746
-
 
1011
 
-
 
1012
;------------------
-
 
1013
; Process RST flags
-
 
1014
 
-
 
1015
	test	[edx + TCP_segment.Flags], TH_RST
-
 
1016
	jz	.rst_skip
-
 
1017
 
-
 
1018
	DEBUGF	1,"Got an RST flag"
-
 
1019
 
-
 
1020
	mov	eax, [ebx + TCP_SOCKET.t_state]
-
 
1021
	shl	eax, 2
-
 
1022
	jmp	dword [eax + .rst_sw_list]
-
 
1023
 
-
 
1024
  .rst_sw_list:
-
 
1025
	dd	.rst_skip	;TCB_CLOSED
-
 
1026
	dd	.rst_skip	;TCB_LISTEN
-
 
1027
	dd	.rst_skip	;TCB_SYN_SENT
-
 
1028
	dd	.econnrefused	;TCB_SYN_RECEIVED
-
 
1029
	dd	.econnreset	;TCB_ESTABLISHED
-
 
1030
	dd	.econnreset	;TCB_CLOSE_WAIT
-
 
1031
	dd	.econnreset	;TCB_FIN_WAIT_1
-
 
1032
	dd	.rst_close	;TCB_CLOSING
-
 
1033
	dd	.rst_close	;TCB_LAST_ACK
-
 
1034
	dd	.econnreset	;TCB_FIN_WAIT_2
-
 
1035
	dd	.rst_close	;TCB_TIMED_WAIT
-
 
1036
 
-
 
1037
  .econnrefused:
-
 
1038
 
-
 
1039
	DEBUGF	1,"Connection refused"
-
 
1040
 
-
 
1041
	;;; TODO: debug info
-
 
1042
 
-
 
1043
	jmp	.close
-
 
1044
 
-
 
1045
  .econnreset:
-
 
1046
 
-
 
1047
	DEBUGF	1,"Connection reset"
-
 
1048
 
-
 
1049
	;;; TODO: debug info
-
 
1050
  .close:
-
 
1051
 
-
 
1052
	DEBUGF	1,"Closing connection"
-
 
1053
 
-
 
1054
	;;; update stats
-
 
1055
 
-
 
1056
  .rst_close:
-
 
1057
 
-
 
1058
	DEBUGF	1,"Closing with reset\n"
-
 
1059
 
-
 
1060
	;;; Close the socket
-
 
1061
	jmp	.drop
-
 
1062
 
-
 
1063
  .rst_skip:
-
 
1064
 
-
 
1065
;--------------------------------------
-
 
1066
; handle SYN-full and ACK-less segments
-
 
1067
 
-
 
1068
	test	[edx + TCP_segment.Flags], TH_SYN
-
 
1069
	jz	@f
-
 
1070
 
-
 
1071
	mov	eax, ebx
-
 
1072
	mov	ebx, ECONNRESET
-
 
1073
	call	TCP_drop
-
 
1074
 
-
 
1075
	jmp	.drop_with_reset
-
 
1076
 
-
 
1077
	test	[edx + TCP_segment.Flags], TH_ACK
-
 
1078
	jz	.drop
-
 
1079
      @@:
-
 
1080
 
-
 
1081
;---------------
-
 
1082
; ACK processing
-
 
1083
 
-
 
1084
	cmp	[ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
-
 
1085
	jnz	.no_syn_rcv
-
 
1086
 
-
 
1087
	DEBUGF	1,"TCP state = syn received\n"
-
 
1088
 
-
 
1089
	;;;;;  801-815
-
 
1090
 
-
 
1091
  .no_syn_rcv:
-
 
1092
 
-
 
1093
; check for duplicate ACK
-
 
1094
 
-
 
1095
	mov	eax, [edx + TCP_segment.AckNumber]
-
 
1096
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
-
 
1097
	jg	.not_dup_ack
-
 
1098
 
-
 
1099
	DEBUGF	1,"Duplicate ACK\n"
-
 
1100
 
-
 
1101
	test	ecx, ecx
-
 
1102
	jnz	.ack_processed
-
 
1103
 
-
 
1104
	mov	eax, dword [edx + TCP_segment.Window]
-
 
1105
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
-
 
1106
	jne	.ack_processed
-
 
1107
 
-
 
1108
; Process the duplicate ACK
-
 
1109
 
-
 
1110
	;;;;; 833 - 878
-
 
1111
 
-
 
1112
;;;        call    TCP_output
-
 
1113
	jmp	.drop
-
 
1114
 
-
 
1115
  .not_dup_ack:
-
 
1116
 
-
 
1117
	DEBUGF	1,"new ACK\n"
-
 
1118
 
-
 
1119
 
-
 
1120
;-------------------------------------------------
-
 
1121
; If the congestion window was inflated to account
-
 
1122
; for the other side's cached packets, retract it
-
 
1123
 
-
 
1124
	;;;; 888 -  902
-
 
1125
 
-
 
1126
 
-
 
1127
;------------------------------------------
-
 
1128
; RTT measurements and retransmission timer
-
 
1129
 
-
 
1130
	;;;;; 903 - 926
-
 
1131
 
-
 
1132
	mov	[ebx + TCP_SOCKET.timer_retransmission], 0
-
 
1133
 
-
 
1134
	mov	eax, [ebx + TCP_SOCKET.SND_MAX]
-
 
1135
	cmp	eax, [edx + TCP_segment.AckNumber]
-
 
1136
	je	.all_outstanding
-
 
1137
	mov	[ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value (use a macro for it)
-
 
1138
  .all_outstanding:
-
 
1139
 
-
 
1140
;-------------------------------------------
-
 
1141
; Open congestion window in response to ACKs
-
 
1142
 
-
 
1143
	;;;;
-
 
1144
 
-
 
1145
 
-
 
1146
;------------------------------------------
-
 
1147
; Remove acknowledged data from send buffer
-
 
1148
 
-
 
1149
	pusha
-
 
1150
	mov	ecx, [edx + TCP_segment.AckNumber]
-
 
1151
	sub	ecx, [ebx + TCP_SOCKET.SND_UNA] 	; ecx now holds number of bytes acked
-
 
1152
 
-
 
1153
	lea	eax, [ebx + STREAM_SOCKET.snd]
-
 
1154
	call	SOCKET_ring_free
-
 
1155
	popa
-
 
1156
 
-
 
1157
;---------------------------------------
-
 
1158
; Wake up process waiting on send buffer
-
 
1159
 
-
 
1160
	mov	eax, ebx
-
 
1161
	call	SOCKET_notify_owner
-
 
1162
 
-
 
1163
; Update TCB
-
 
1164
 
-
 
1165
	mov	eax, [edx + TCP_segment.AckNumber]
-
 
1166
	mov	[ebx + TCP_SOCKET.SND_UNA], eax
-
 
1167
 
-
 
1168
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
-
 
1169
	jl	@f
-
 
1170
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
-
 
1171
       @@:
-
 
1172
 
-
 
1173
; General ACK handling complete
-
 
1174
; Now do the state-specific ones
-
 
1175
 
-
 
1176
	mov	eax, [ebx + TCP_SOCKET.t_state]
-
 
1177
	jmp	dword [eax*4 + .ACK_sw_list]
-
 
1178
 
-
 
1179
  .ACK_sw_list:
-
 
1180
	dd	.ack_processed	;TCB_CLOSED
-
 
1181
	dd	.ack_processed	;TCB_LISTEN
-
 
1182
	dd	.ack_processed	;TCB_SYN_SENT
-
 
1183
	dd	.ack_processed	;TCB_SYN_RECEIVED
-
 
1184
	dd	.ack_processed	;TCB_ESTABLISHED
-
 
1185
	dd	.ack_processed	;TCB_CLOSE_WAIT
-
 
1186
	dd	.ack_fw1	;TCB_FIN_WAIT_1
-
 
1187
	dd	.ack_c		;TCB_CLOSING
-
 
1188
	dd	.ack_la 	;TCB_LAST_ACK
-
 
1189
	dd	.ack_processed	;TCB_FIN_WAIT_2
-
 
1190
	dd	.ack_tw 	;TCB_TIMED_WAIT
-
 
1191
 
-
 
1192
 
-
 
1193
  .ack_fw1:
-
 
1194
 
-
 
1195
;;; TODO: 963
-
 
1196
 
-
 
1197
	jmp	.ack_processed
-
 
1198
 
-
 
1199
  .ack_c:
-
 
1200
 
-
 
1201
;;; TODO: 958
-
 
1202
 
-
 
1203
	jmp	.ack_processed
-
 
1204
 
-
 
1205
  .ack_la:
-
 
1206
 
-
 
1207
;;; TODO: 999
-
 
1208
 
-
 
1209
	jmp	.ack_processed
-
 
1210
 
-
 
1211
 
-
 
1212
  .ack_tw:
-
 
1213
 
-
 
1214
;;; TODO: 1010
-
 
1215
 
-
 
1216
	jmp	.ack_processed
-
 
1217
 
-
 
1218
 
-
 
1219
  .ack_processed:
-
 
1220
 
-
 
1221
	DEBUGF	1,"ack processed\n"
-
 
1222
 
-
 
1223
;----------------------------------------------
-
 
1224
; check if we need to update window information
-
 
1225
 
-
 
1226
	test	[edx + TCP_segment.Flags], TH_ACK
-
 
1227
	jz	.no_window_update
-
 
1228
 
-
 
1229
	mov	eax, [ebx + TCP_SOCKET.SND_WL1]
-
 
1230
	cmp	eax, [edx + TCP_segment.SequenceNumber]
-
 
1231
	jl	.update_window
-
 
1232
	jg	@f
-
 
1233
 
-
 
1234
	mov	eax, [ebx + TCP_SOCKET.SND_WL2]
-
 
1235
	cmp	eax, [edx + TCP_segment.AckNumber]
-
 
1236
	jl	.update_window
-
 
1237
	jg	.no_window_update
-
 
1238
       @@:
-
 
1239
 
-
 
1240
	mov	eax, [ebx + TCP_SOCKET.SND_WL2]
-
 
1241
	cmp	eax, [edx + TCP_segment.AckNumber]
-
 
1242
	jne	.no_window_update
-
 
1243
 
-
 
1244
	movzx	eax, [edx + TCP_segment.Window]
-
 
1245
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
-
 
1246
	jle	.no_window_update
-
 
1247
 
-
 
1248
  .update_window:
-
 
1249
 
-
 
1250
	DEBUGF	1,"Updating window\n"
-
 
1251
 
-
 
1252
;----------------------------------
-
 
1253
; Keep track of pure window updates
-
 
1254
 
-
 
1255
;        test    ecx, ecx
-
 
1256
;        jz      @f
-
 
1257
;
-
 
1258
;        mov     eax, [ebx + TCP_SOCKET.SND_WL2]
-
 
1259
;        cmp     eax, [edx + TCP_segment.AckNumber]
-
 
1260
;        jne     @f
-
 
1261
;
-
 
1262
;        ;; mov eax, tiwin
-
 
1263
;        cmp     eax, [ebx + TCP_SOCKET.SND_WND]
-
 
1264
;        jle     @f
-
 
1265
;
-
 
1266
;        ;;; update stats
-
 
1267
;
-
 
1268
;       @@:
-
 
1269
 
-
 
1270
	mov	eax, dword [edx + TCP_segment.Window]
-
 
1271
	cmp	eax, [ebx + TCP_SOCKET.max_sndwnd]
-
 
1272
	jle	@f
-
 
1273
	mov	[ebx + TCP_SOCKET.max_sndwnd], eax
-
 
1274
       @@:
-
 
1275
	mov	[ebx + TCP_SOCKET.SND_WND], eax
-
 
1276
 
-
 
1277
	push	[edx + TCP_segment.SequenceNumber]
-
 
1278
	pop	[ebx + TCP_SOCKET.SND_WL1]
-
 
1279
 
-
 
1280
	push	[edx + TCP_segment.AckNumber]
-
 
1281
	pop	[ebx + TCP_SOCKET.SND_WL2]
-
 
1282
 
-
 
1283
	;;; needoutput = 1
-
 
1284
 
-
 
1285
  .no_window_update:
-
 
1286
 
-
 
1287
;-----------------
-
 
1288
; process URG flag
-
 
1289
 
-
 
1290
	test	[edx + TCP_segment.Flags], TH_URG
-
 
1291
	jz	.not_urgent
-
 
1292
 
-
 
1293
	cmp	[edx + TCP_segment.UrgentPointer], 0
-
 
1294
	jz	.not_urgent
-
 
1295
 
-
 
1296
	cmp	[ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT
-
 
1297
	je	.not_urgent
-
 
1298
 
-
 
1299
; Ignore bogus urgent offsets
-
 
1300
 
-
 
1301
	;;; 1040-1050
-
 
1302
 
-
 
1303
	movzx	eax, [edx + TCP_segment.UrgentPointer]
121
 
1304
	add	eax, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.size]
-
 
1305
	cmp	eax, SOCKET_MAXDATA
-
 
1306
	jle	.not_urgent
-
 
1307
 
-
 
1308
	mov	[edx + TCP_segment.UrgentPointer], 0
-
 
1309
	and	[edx + TCP_segment.Flags], not (TH_URG)
-
 
1310
	jmp	.do_data
-
 
1311
 
-
 
1312
  .not_urgent:
-
 
1313
 
-
 
1314
;--------------------------------------
-
 
1315
; processing of received urgent pointer
-
 
1316
 
-
 
1317
	;;; TODO (1051-1093)
-
 
1318
 
-
 
1319
;--------------------------------
-
 
1320
; process the data in the segment
-
 
1321
 
-
 
1322
  .do_data:
-
 
1323
 
-
 
1324
	DEBUGF	1,"TCP: do data (%u)\n", ecx
-
 
1325
 
-
 
1326
	test	[edx + TCP_segment.Flags], TH_FIN
-
 
1327
	jnz	.process_fin
-
 
1328
 
-
 
1329
	cmp	[ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_1
-
 
1330
	jge	.dont_do_data
-
 
1331
 
-
 
1332
	test	ecx, ecx
-
 
1333
	jz	.final_processing
-
 
1334
 
-
 
1335
	DEBUGF	1,"Processing data in segment\n"
-
 
1336
 
-
 
1337
;; TODO: check if data is in sequence !
-
 
1338
 
-
 
1339
	movzx	eax, [edx + TCP_segment.DataOffset]		;;; todo: remember this in.. edi ?
-
 
1340
	and	eax, 0xf0
-
 
1341
	shr	al, 2
-
 
1342
 
-
 
1343
	lea	esi, [edx + eax]
-
 
1344
 
-
 
1345
	or	[ebx + TCP_SOCKET.t_flags], TF_DELACK
-
 
1346
	add	[ebx + TCP_SOCKET.RCV_NXT], ecx
122
 
1347
 
-
 
1348
	lea	eax, [ebx + STREAM_SOCKET.rcv]
-
 
1349
	call	SOCKET_ring_write
-
 
1350
 
-
 
1351
	mov	eax, ebx
-
 
1352
	call	SOCKET_notify_owner
-
 
1353
 
-
 
1354
	jmp	.final_processing
-
 
1355
 
-
 
1356
 
-
 
1357
  .dont_do_data:
-
 
1358
 
-
 
1359
;---------------
-
 
1360
; FIN processing
-
 
1361
 
-
 
1362
  .process_fin:
-
 
1363
 
-
 
1364
	DEBUGF	1,"Processing FIN\n"
-
 
1365
 
-
 
1366
	mov	eax, [ebx + TCP_SOCKET.t_state]
-
 
1367
	shl	eax, 2
-
 
1368
	jmp	dword [eax + .FIN_sw_list]
-
 
1369
 
-
 
1370
  .FIN_sw_list:
-
 
1371
	dd	.no_fin 	;TCB_CLOSED
-
 
1372
	dd	.no_fin 	;TCB_LISTEN
-
 
1373
	dd	.no_fin 	;TCB_SYN_SENT
-
 
1374
	dd	.fin_syn_est	;TCB_SYN_RECEIVED
-
 
1375
	dd	.fin_syn_est	;TCB_ESTABLISHED
-
 
1376
	dd	.no_fin 	;TCB_CLOSE_WAIT
-
 
1377
	dd	.fin_wait1	;TCB_FIN_WAIT_1
-
 
1378
	dd	.no_fin 	;TCB_CLOSING
-
 
1379
	dd	.no_fin 	;TCB_LAST_ACK
-
 
1380
	dd	.fin_wait2	;TCB_FIN_WAIT_2
-
 
1381
	dd	.fin_timed	;TCB_TIMED_WAIT
-
 
1382
 
-
 
1383
 
-
 
1384
 
-
 
1385
  .fin_syn_est:
-
 
1386
 
-
 
1387
	jmp	.final_processing
-
 
1388
 
-
 
1389
  .fin_wait1:
-
 
1390
 
-
 
1391
	jmp	.final_processing
-
 
1392
 
-
 
1393
  .fin_wait2:
-
 
1394
 
-
 
1395
	jmp	.final_processing
-
 
1396
 
-
 
1397
  .fin_timed:
-
 
1398
 
-
 
1399
	jmp	.final_processing
-
 
1400
 
-
 
1401
  .no_fin:
-
 
1402
 
-
 
1403
;-----------------
-
 
1404
; Final processing
-
 
1405
 
-
 
1406
  .final_processing:
-
 
1407
 
-
 
1408
	DEBUGF	1,"Final processing\n"
-
 
1409
 
-
 
1410
	mov	[ebx + SOCKET.lock], 0
-
 
1411
 
-
 
1412
	;;; if debug enabled, output packet
-
 
1413
 
-
 
1414
	;test    needoutput, needoutput
-
 
1415
	;jz      .dumpit
-
 
1416
 
-
 
1417
	test	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
-
 
1418
	jz	.dumpit
-
 
1419
 
-
 
1420
	DEBUGF	1,"ACK now!\n"
-
 
1421
 
-
 
1422
	push	ebx
-
 
1423
	mov	eax, ebx
-
 
1424
	call	TCP_output
-
 
1425
	pop	ebx
-
 
1426
 
-
 
1427
  .dumpit:
-
 
1428
 
-
 
1429
	call	kernel_free
-
 
1430
	add	esp, 4
-
 
1431
	ret
-
 
1432
 
-
 
1433
;------------------------------------------
-
 
1434
; Generate an ACK, droping incoming segment
-
 
1435
 
-
 
1436
align 4
-
 
1437
.drop_after_ack:
-
 
1438
 
-
 
1439
	DEBUGF	1,"Drop after ACK\n"
-
 
1440
 
-
 
1441
	test	[edx + TCP_segment.Flags], TH_RST
-
 
1442
	jnz	.drop
-
 
1443
 
-
 
1444
	and	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
-
 
1445
 
-
 
1446
	push	ebx
-
 
1447
	mov	eax, ebx
-
 
1448
	call	TCP_output
-
 
1449
	pop	ebx
-
 
1450
 
-
 
1451
	call	kernel_free
-
 
1452
	add	esp, 4
-
 
1453
	ret
-
 
1454
 
-
 
1455
 
-
 
1456
;-------------------------------------------
-
 
1457
; Generate an RST, dropping incoming segment
-
 
1458
 
-
 
1459
align 4
-
 
1460
.drop_with_reset:
-
 
1461
 
-
 
1462
	DEBUGF	1,"Drop with reset\n"
-
 
1463
 
-
 
1464
	test	[edx + TCP_segment.Flags], TH_RST
-
 
1465
	jnz	.drop
-
 
1466
 
-
 
1467
	;;; if its a multicast/broadcast, also drop
-
 
1468
 
-
 
1469
	test	[edx + TCP_segment.Flags], TH_ACK
-
 
1470
	jnz	.respond_ack
-
 
1471
 
-
 
1472
	test	[edx + TCP_segment.Flags], TH_SYN
-
 
1473
	jnz	.respond_syn
-
 
1474
 
-
 
1475
	call	kernel_free
-
 
1476
	add	esp, 4
-
 
1477
	ret
-
 
1478
 
-
 
1479
  .respond_ack:
-
 
1480
 
-
 
1481
	mov	dl, TH_RST
-
 
1482
 
-
 
1483
	push	ebx
-
 
1484
	call	TCP_respond_segment
-
 
1485
	pop	ebx
-
 
1486
 
-
 
1487
	jmp	.destroy_new_socket
-
 
1488
 
-
 
1489
 
-
 
1490
  .respond_syn:
-
 
1491
 
-
 
1492
	mov	dl, TH_RST + TH_ACK
-
 
1493
 
-
 
1494
	push	ebx
-
 
1495
	call	TCP_respond_socket
-
 
1496
	pop	ebx
-
 
1497
 
-
 
1498
	jmp	.destroy_new_socket
-
 
1499
 
-
 
1500
;-----
-
 
1501
; Drop
-
 
1502
 
-
 
1503
align 4
-
 
1504
.drop:
-
 
1505
 
-
 
1506
	DEBUGF	1,"Dropping packet\n"
-
 
1507
 
-
 
1508
	;;;; If debugging options are enabled, output the packet somwhere
-
 
1509
 
-
 
1510
  .destroy_new_socket:
-
 
1511
 
-
 
1512
	;;;; kill the newly created socket
-
 
1513
 
-
 
1514
	call	kernel_free
-
 
1515
	add	esp, 4
-
 
1516
	ret
-
 
1517
 
-
 
1518
 
-
 
1519
 
-
 
1520
 
-
 
1521
 
-
 
1522
 
-
 
1523
;---------------------------
-
 
1524
;
-
 
1525
; TCP_pull_out_of_band
-
 
1526
;
-
 
1527
; IN:  eax =
-
 
1528
;      ebx = socket ptr
-
 
1529
;      edx = tcp packet ptr
-
 
1530
;
-
 
1531
; OUT: /
-
 
1532
;
-
 
1533
;---------------------------
-
 
1534
 
-
 
1535
align 4
-
 
1536
TCP_pull_out_of_band:
-
 
1537
 
-
 
1538
	DEBUGF	1,"TCP_pull_out_of_band\n"
-
 
1539
 
-
 
1540
	;;;; 1282-1305
-
 
1541
 
-
 
1542
	ret
-
 
1543
 
-
 
1544
 
-
 
1545
 
-
 
1546
;-----------------------------------------------------------------
-
 
1547
;
-
 
1548
; TCP_output
-
 
1549
;
-
 
1550
; IN:  eax = socket pointer
-
 
1551
;
-
 
1552
; OUT: /
-
 
1553
;
-
 
1554
;-----------------------------------------------------------------
-
 
1555
align 4
-
 
1556
TCP_output:
-
 
1557
 
-
 
1558
	DEBUGF 1,"TCP_output, socket: %x\n", eax
-
 
1559
 
-
 
1560
; We'll detect the length of the data to be transmitted, and flags to be used
-
 
1561
; If there is some data, or any critical controls to send (SYN / RST), then transmit
-
 
1562
; Otherwise, investigate further
-
 
1563
 
-
 
1564
	mov	ebx, [eax + TCP_SOCKET.SND_MAX]
-
 
1565
	cmp	ebx, [eax + TCP_SOCKET.SND_UNA]
-
 
1566
	jne	.not_idle
-
 
1567
 
-
 
1568
	mov	ebx, [eax + TCP_SOCKET.t_idle]
-
 
1569
	cmp	ebx, [eax + TCP_SOCKET.t_rxtcur]
-
 
1570
	jle	.not_idle
-
 
1571
 
-
 
1572
; We have been idle for a while and no ACKS are expected to clock out any data we send..
-
 
1573
; Slow start to get ack "clock" running again.
-
 
1574
 
-
 
1575
	mov	ebx, [eax + TCP_SOCKET.t_maxseg]
-
 
1576
	mov	[eax + TCP_SOCKET.SND_CWND], ebx
-
 
1577
 
-
 
1578
  .not_idle:
-
 
1579
  .again:
-
 
1580
	mov	ebx, [eax + TCP_SOCKET.SND_NXT] 	; calculate offset
-
 
1581
	sub	ebx, [eax + TCP_SOCKET.SND_UNA] 	;
-
 
1582
 
-
 
1583
	mov	ecx, [eax + TCP_SOCKET.SND_WND] 	; determine window
-
 
1584
	cmp	ecx, [eax + TCP_SOCKET.SND_CWND]	;
-
 
1585
	jl	@f					;
-
 
1586
	mov	ecx, [eax + TCP_SOCKET.SND_CWND]	;
-
 
1587
       @@:						;
-
 
1588
 
-
 
1589
	call	TCP_outflags	; in dl
-
 
1590
 
-
 
1591
; If in persist timeout with window of 0, send 1 byte.
-
 
1592
; Otherwise, if window is small but nonzero, and timer expired,
-
 
1593
; we will send what we can and go to transmit state
-
 
1594
 
-
 
1595
	test	[eax + TCP_SOCKET.t_force], -1
-
 
1596
	jz	.no_persist_timeout
-
 
1597
 
-
 
1598
	test	ecx, ecx
-
 
1599
	jnz	.no_zero_window
-
 
1600
 
-
 
1601
	cmp	ebx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
-
 
1602
	jge	@f
-
 
1603
 
-
 
1604
	and	dl, not (TH_FIN)	  ; clear the FIN flag    ??? how can it be set before?
-
 
1605
 
-
 
1606
       @@:
-
 
1607
	inc	ecx
-
 
1608
	jmp	.no_persist_timeout
-
 
1609
 
-
 
1610
  .no_zero_window:
-
 
1611
 
-
 
1612
	mov	[eax + TCP_SOCKET.timer_persist], 0
-
 
1613
	mov	[eax + TCP_SOCKET.t_rxtshift], 0
-
 
1614
 
-
 
1615
  .no_persist_timeout:
-
 
1616
 
-
 
1617
;;;106
-
 
1618
 
-
 
1619
	mov	esi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
-
 
1620
	cmp	esi, ecx
-
 
1621
	jl	@f
-
 
1622
	mov	esi, ecx
-
 
1623
       @@:
-
 
1624
	sub	esi, ebx
-
 
1625
 
-
 
1626
	cmp	esi, -1
-
 
1627
	jne	.not_minus_one
-
 
1628
 
-
 
1629
; If FIN has been set, but not ACKed, and we havent been called to retransmit,
-
 
1630
; len (esi) will be -1
-
 
1631
; Otherwise, window shrank after we sent into it.
-
 
1632
; If window shrank to 0, cancel pending retransmit and pull SND_NXT back to (closed) window
-
 
1633
; We will enter persist state below.
-
 
1634
; If window didn't close completely, just wait for an ACK
-
 
1635
 
-
 
1636
	xor	esi, esi
-
 
1637
 
-
 
1638
	test	ecx, ecx
-
 
1639
	jnz	@f
-
 
1640
 
-
 
1641
	mov	[eax + TCP_SOCKET.timer_retransmission], 0   ; cancel retransmit
-
 
1642
 
-
 
1643
	push	[eax + TCP_SOCKET.SND_UNA]
-
 
1644
	pop	[eax + TCP_SOCKET.SND_NXT]
-
 
1645
       @@:
-
 
1646
 
-
 
1647
  .not_minus_one:
-
 
1648
 
-
 
1649
;;; 124
-
 
1650
 
-
 
1651
	cmp	esi, [eax + TCP_SOCKET.t_maxseg]
-
 
1652
	jle	@f
-
 
1653
 
-
 
1654
	mov	esi, [eax + TCP_SOCKET.t_maxseg]
-
 
1655
	;sendalot = 1
-
 
1656
 
-
 
1657
       @@:
-
 
1658
 
-
 
1659
;;; 128
-
 
1660
 
-
 
1661
	mov	edi, [eax + TCP_SOCKET.SND_NXT]
-
 
1662
	add	edi, esi	; len
-
 
1663
	sub	edi, [eax + TCP_SOCKET.SND_UNA]
-
 
1664
	add	edi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
-
 
1665
	cmp	edi, 0
-
 
1666
	jle	@f
-
 
1667
 
-
 
1668
	and	dl, not (TH_FIN)	  ; clear the FIN flag
-
 
1669
 
-
 
1670
       @@:
-
 
1671
 
-
 
1672
 
-
 
1673
; set ecx to space available in receive buffer
-
 
1674
; From now on, ecx will be the window we advertise to the other end
-
 
1675
 
-
 
1676
	mov	ecx, SOCKET_MAXDATA
-
 
1677
	sub	ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
-
 
1678
 
-
 
1679
;------------------------------
-
 
1680
; Sender silly window avoidance
-
 
1681
 
-
 
1682
	cmp	ecx, [eax + TCP_SOCKET.t_maxseg]
-
 
1683
	je	.send
-
 
1684
 
-
 
1685
;;; TODO: 144-145
-
 
1686
 
-
 
1687
	test	[eax + TCP_SOCKET.t_force], -1
-
 
1688
	jnz	.send
-
 
1689
 
-
 
1690
	mov	ebx, [eax + TCP_SOCKET.max_sndwnd]
-
 
1691
	shr	ebx, 1
-
 
1692
	cmp	ecx, ebx
-
 
1693
	jge	.send
-
 
1694
 
-
 
1695
	mov	ebx, [eax + TCP_SOCKET.SND_NXT]
-
 
1696
	cmp	ebx, [eax + TCP_SOCKET.SND_MAX]
-
 
1697
	jl	.send
-
 
1698
 
-
 
1699
;----------------------------------------
-
 
1700
; Check if a window update should be sent
-
 
1701
 
-
 
1702
	test	ecx, ecx	; window
-
 
1703
	jz	.no_window
-
 
1704
 
-
 
1705
;;; TODO 154-172
-
 
1706
 
-
 
1707
  .no_window:
-
 
1708
 
-
 
1709
;--------------------------
-
 
1710
; Should a segment be sent?
-
 
1711
 
-
 
1712
	test	[eax + TCP_SOCKET.t_flags], TF_ACKNOW
-
 
1713
	jnz	.send
-
 
1714
 
-
 
1715
	test	dl, TH_SYN + TH_RST
-
 
1716
	jnz	.send
-
 
1717
 
-
 
1718
	mov	ebx, [eax + TCP_SOCKET.SND_UP]
-
 
1719
	cmp	ebx, [eax + TCP_SOCKET.SND_UNA]
-
 
1720
	jg	.send
-
 
1721
 
-
 
1722
	test	dl, TH_FIN
-
 
1723
	jz	.enter_persist
-
 
1724
 
-
 
1725
	test	[eax + TCP_SOCKET.t_flags], TF_SENTFIN
-
 
1726
	jnz	.send
-
 
1727
 
-
 
1728
	mov	ebx, [eax + TCP_SOCKET.SND_NXT]
-
 
1729
	cmp	ebx, [eax + TCP_SOCKET.SND_UNA]
-
 
1730
	je	.send
-
 
1731
 
-
 
1732
;--------------------
-
 
1733
; Enter persist state
-
 
1734
 
-
 
1735
  .enter_persist:
-
 
1736
 
-
 
1737
	DEBUGF	1,"Entering persist state\n"
-
 
1738
 
-
 
1739
;--------------------------------------
-
 
1740
; No reason to send a segment, just ret
-
 
1741
 
-
 
1742
	DEBUGF	1,"No reason to send a segment\n"
-
 
1743
 
-
 
1744
	ret
-
 
1745
 
-
 
1746
 
-
 
1747
;-----------------------------------------------
-
 
1748
;
-
 
1749
; Send a segment
-
 
1750
;
-
 
1751
; eax = socket pointer
-
 
1752
;  dl = flags
-
 
1753
;
-
 
1754
;-----------------------------------------------
-
 
1755
 
-
 
1756
  .send:
-
 
1757
 
-
 
1758
	DEBUGF	1,"Preparing to send a segment\n"
-
 
1759
 
-
 
1760
	mov	edi, TCP_segment.Data	; edi will contain headersize
-
 
1761
 
-
 
1762
	sub	esp, 8			; create some space on stack
-
 
1763
	push	eax			; save this too..
-
 
1764
 
-
 
1765
;------------------------------------
-
 
1766
; Send options with first SYN segment
-
 
1767
 
-
 
1768
	test	dl, TH_SYN
-
 
1769
	jz	.no_options
-
 
1770
 
-
 
1771
	push	[eax + TCP_SOCKET.ISS]
-
 
1772
	pop	[eax + TCP_SOCKET.SND_NXT]
-
 
1773
 
-
 
1774
	test	[eax + TCP_SOCKET.t_flags], TF_NOOPT
-
 
1775
	jnz	.no_options
-
 
1776
 
-
 
1777
	mov	ecx, 1460
-
 
1778
	or	ecx, TCP_OPT_MAXSEG shl 24 + 4 shl 16
-
 
1779
	bswap	ecx
-
 
1780
	push	ecx
-
 
1781
	add	di, 4
-
 
1782
 
-
 
1783
	test	[eax + TCP_SOCKET.t_flags], TF_REQ_SCALE
-
 
1784
	jz	.no_syn
-
 
1785
 
-
 
1786
	test	dl, TH_ACK
-
 
1787
	jnz	.scale_opt
-
 
1788
 
-
 
1789
	test	[eax + TCP_SOCKET.t_flags], TF_RCVD_SCALE
-
 
1790
	jz	.no_syn
-
 
1791
 
-
 
1792
  .scale_opt:
-
 
1793
	movzx	ecx, byte [eax + TCP_SOCKET.request_r_scale]
-
 
1794
	or	ecx, TCP_OPT_WINDOW shl 24 + 4 shl 16 + TCP_OPT_NOP shl 8
-
 
1795
	bswap	ecx
-
 
1796
	pushd	ecx
-
 
1797
	add	di, 4
-
 
1798
 
-
 
1799
  .no_syn:
-
 
1800
 
-
 
1801
;------------------------------------
-
 
1802
; Make the timestamp option if needed
-
 
1803
 
-
 
1804
	test	[eax + TCP_SOCKET.t_flags], TF_REQ_TSTMP
-
 
1805
	jz	.no_timestamp
-
 
1806
 
-
 
1807
	test	dl, TH_RST
-
 
1808
	jnz	.no_timestamp
-
 
1809
 
-
 
1810
	test	dl, TH_ACK
-
 
1811
	jz	.timestamp
-
 
1812
 
-
 
1813
	test	[eax + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
-
 
1814
	jz	.no_timestamp
-
 
1815
 
-
 
1816
  .timestamp:
-
 
1817
	mov	esi, [timer_ticks]
-
 
1818
	bswap	esi
-
 
1819
	push	esi
-
 
1820
	pushw	0
-
 
1821
	pushd	TCP_OPT_TIMESTAMP + 10 shl 8 + TCP_OPT_NOP shl 16 + TCP_OPT_NOP shl 24
-
 
1822
	add	di, 10
-
 
1823
 
-
 
1824
  .no_timestamp:
-
 
1825
	;; TODO: check if we dont exceed the max segment size
-
 
1826
 
-
 
1827
  .no_options:
-
 
1828
	; eax = socket ptr
-
 
1829
	; edx = flags
-
 
1830
	; ecx = data size
-
 
1831
	; edi = header size
-
 
1832
	; esi = snd ring buff ptr
-
 
1833
 
-
 
1834
	mov	ecx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size]
-
 
1835
	cmp	ecx, [eax + TCP_SOCKET.t_maxseg]			;;; right?
-
 
1836
	jle	@f
-
 
1837
	mov	ecx, [eax + TCP_SOCKET.t_maxseg]
-
 
1838
       @@:
-
 
1839
	add	ecx, edi	; total TCP segment size
-
 
1840
 
-
 
1841
; Start by pushing all TCP header values in reverse order on stack
-
 
1842
; (essentially, creating the tcp header!)
-
 
1843
 
-
 
1844
	pushw	0	;        .UrgentPointer          dw ?
-
 
1845
	pushw	0	;        .Checksum               dw ?
-
 
1846
	pushw	0x00a0	;        .Window                 dw ?    ;;;;;;;
-
 
1847
	shl	edi, 2	;        .DataOffset             db ?  only 4 left-most bits
-
 
1848
	shl	dx, 8
-
 
1849
	or	dx, di	;        .Flags                  db ?
-
 
1850
	pushw	dx
-
 
1851
	shr	edi, 2	;        .DataOffset             db ? ;;;;
-
 
1852
 
-
 
1853
	push	[eax + TCP_SOCKET.RCV_NXT]	;        .AckNumber              dd ?
-
 
1854
	ntohd	[esp]
-
 
1855
 
-
 
1856
	push	[eax + TCP_SOCKET.SND_NXT]	;        .SequenceNumber         dd ?
-
 
1857
	ntohd	[esp]
-
 
1858
 
-
 
1859
	push	[eax + TCP_SOCKET.RemotePort]	;        .DestinationPort        dw ?
-
 
1860
	ntohw	[esp]
-
 
1861
 
-
 
1862
	push	[eax + TCP_SOCKET.LocalPort]	;        .SourcePort             dw ?
-
 
1863
	ntohw	[esp]
-
 
1864
 
-
 
1865
	push	edi		; header size
-
 
1866
 
-
 
1867
; Create the IP packet
-
 
1868
	mov	ebx, [eax + IP_SOCKET.LocalIP]	; source ip
-
 
1869
	mov	eax, [eax + IP_SOCKET.RemoteIP] ; dest ip
-
 
1870
	mov	di, IP_PROTO_TCP shl 8 + 128
-
 
1871
	call	IPv4_output
-
 
1872
	jz	.fail
-
 
1873
 
-
 
1874
;-----------------------------------------
-
 
1875
; Move TCP header from stack to TCP packet
-
 
1876
 
-
 
1877
	push	ecx
-
 
1878
	mov	ecx, [esp+4]
-
 
1879
	lea	esi, [esp+4+4]
-
 
1880
	shr	ecx, 2
-
 
1881
	rep	movsd
-
 
1882
	pop	ecx		; full TCP packet size
-
 
1883
 
-
 
1884
	pop	esi		; headersize
-
 
1885
	add	esp, esi
-
 
1886
 
-
 
1887
	mov	[esp + 4], eax		; packet ptr
-
 
1888
	mov	[esp + 4+4], edx	; packet size
-
 
1889
 
-
 
1890
	mov	edx, edi		; begin of data
-
 
1891
	sub	edx, esi		; begin of packet (edi = begin of data)
-
 
1892
	push	ecx
-
 
1893
	sub	ecx, esi		; data size
-
 
1894
 
-
 
1895
;--------------
-
 
1896
; Copy the data
-
 
1897
 
-
 
1898
; eax = ptr to ring struct
-
 
1899
; ecx = buffer size
-
 
1900
; edi = ptr to buffer
-
 
1901
 
-
 
1902
;        test    ecx, ecx
-
 
1903
	mov	eax, [esp+4]		  ; socket ptr
-
 
1904
	add	[eax + TCP_SOCKET.SND_NXT], ecx
-
 
1905
	add	eax, STREAM_SOCKET.snd
-
 
1906
	push	edx
-
 
1907
	call	SOCKET_ring_read
-
 
1908
	pop	esi
-
 
1909
	pop	ecx
-
 
1910
	pop	eax
-
 
1911
 
-
 
1912
	test	[esi + TCP_segment.Flags], TH_SYN + TH_FIN
-
 
1913
	jz	@f
-
 
1914
	inc	[eax + TCP_SOCKET.SND_NXT]
-
 
1915
	;;; TODO: update sentfin flag
-
 
1916
       @@:
-
 
1917
 
-
 
1918
	mov	edx, [eax + TCP_SOCKET.SND_NXT]
-
 
1919
	cmp	edx, [eax + TCP_SOCKET.SND_MAX]
-
 
1920
	jle	@f
-
 
1921
	mov	[eax + TCP_SOCKET.SND_MAX], edx
-
 
1922
 
-
 
1923
	;;;; TODO: time transmission (420)
-
 
1924
       @@:
-
 
1925
 
-
 
1926
	;;; TODO: set retransmission timer
-
 
1927
 
-
 
1928
;--------------------
-
 
1929
; Create the checksum
-
 
1930
 
-
 
1931
	DEBUGF	1,"checksum: ptr=%x size=%u\n", esi, ecx
-
 
1932
 
-
 
1933
	TCP_checksum (eax + IP_SOCKET.LocalIP), (eax + IP_SOCKET.RemoteIP)
-
 
1934
	mov	[esi+TCP_segment.Checksum], dx
-
 
1935
 
-
 
1936
;----------------
-
 
1937
; Send the packet
-
 
1938
 
-
 
1939
	DEBUGF	1,"Sending TCP Packet to device %x\n", ebx
-
 
1940
	call	[ebx + NET_DEVICE.transmit]
-
 
1941
	ret
-
 
1942
 
-
 
1943
 
-
 
1944
  .fail:
-
 
1945
	pop	ecx
-
 
1946
	add	esp, ecx
-
 
1947
	add	esp, 4+8
-
 
1948
	DEBUGF 1,"TCP_output: failed\n"
-
 
1949
	ret
-
 
1950
 
-
 
1951
 
-
 
1952
 
-
 
1953
;-------------------------
-
 
1954
;
-
 
1955
; TCP_outflags
-
 
1956
;
-
 
1957
;  IN:  eax = socket ptr
-
 
1958
;
-
 
1959
;  OUT: edx = flags
-
 
1960
;
-
 
1961
;-------------------------
-
 
1962
align 4
-
 
1963
TCP_outflags:
-
 
1964
 
-
 
1965
	mov	edx, [eax + TCP_SOCKET.t_state]
-
 
1966
	movzx	edx, byte [edx + .flaglist]
-
 
1967
 
-
 
1968
	DEBUGF	1,"TCP_outflags, socket: %x, flags: %x\n", eax, dl
-
 
1969
 
-
 
1970
	ret
-
 
1971
 
-
 
1972
  .flaglist:
-
 
1973
 
-
 
1974
	db	TH_RST + TH_ACK 	; TCB_CLOSED
-
 
1975
	db	0			; TCB_LISTEN
-
 
1976
	db	TH_SYN			; TCB_SYN_SENT
-
 
1977
	db	TH_SYN + TH_ACK 	; TCB_SYN_RECEIVED
-
 
1978
	db		 TH_ACK 	; TCB_ESTABLISHED
-
 
1979
	db		 TH_ACK 	; TCB_CLOSE_WAIT
-
 
1980
	db	TH_SYN + TH_ACK 	; TCB_FIN_WAIT_1
-
 
1981
	db	TH_SYN + TH_ACK 	; TCB_CLOSING
-
 
1982
	db	TH_SYN + TH_ACK 	; TCB_LAST_ACK
-
 
1983
	db		 TH_ACK 	; TCB_FIN_WAIT_2
-
 
1984
	db		 TH_ACK 	; TCB_TIMED_WAIT
-
 
1985
 
-
 
1986
 
-
 
1987
 
-
 
1988
 
-
 
1989
;-------------------------
-
 
1990
;
-
 
1991
; TCP_drop
-
 
1992
;
-
 
1993
;  IN:  eax = socket ptr
-
 
1994
;       ebx = error number
-
 
1995
;
-
 
1996
;  OUT: eax = socket ptr
-
 
1997
;
-
 
1998
;-------------------------
-
 
1999
align 4
-
 
2000
TCP_drop:
-
 
2001
 
-
 
2002
	DEBUGF	1,"TCP_drop\n"
-
 
2003
 
-
 
2004
	cmp	[eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
-
 
2005
	jl	.no_syn_received
-
 
2006
 
-
 
2007
	mov	[eax + TCP_SOCKET.t_state], TCB_CLOSED
-
 
2008
 
-
 
2009
	call	TCP_output
-
 
2010
 
-
 
2011
;;; TODO: update stats
-
 
2012
 
-
 
2013
	jmp	TCP_close
-
 
2014
 
-
 
2015
  .no_syn_received:
-
 
2016
 
-
 
2017
;;; TODO: update stats
-
 
2018
 
-
 
2019
;;; TODO: check if error code is "Connection timed out' and handle accordingly
-
 
2020
 
-
 
2021
	mov	[eax + SOCKET.errorcode], ebx
-
 
2022
 
-
 
2023
	jmp	TCP_close
-
 
2024
 
-
 
2025
 
-
 
2026
;-------------------------
-
 
2027
;
-
 
2028
; TCP_close
-
 
2029
;
-
 
2030
;  IN:  eax = socket ptr
-
 
2031
;  OUT: eax = socket ptr
-
 
2032
;
-
 
2033
;-------------------------
-
 
2034
align 4
-
 
2035
TCP_close:
-
 
2036
 
-
 
2037
	DEBUGF	1,"TCP_close\n"
-
 
2038
 
-
 
2039
;;; TODO: update RTT and mean deviation
-
 
2040
;;; TODO: update slow start threshold
-
 
2041
;;; TODO: release connection resources
-
 
2042
 
-
 
2043
; Now, mark the socket as being disconnected
-
 
2044
 
-
 
2045
	mov	[eax + SOCKET.state], 0 ;;; FIXME
-
 
2046
 
-
 
2047
	ret
-
 
2048
 
-
 
2049
 
-
 
2050
 
-
 
2051
 
-
 
2052
;---------------------------------------
-
 
2053
;
-
 
2054
; The easy way to send an ACK/RST/keepalive segment
-
 
2055
;
-
 
2056
; TCP_respond_socket:
-
 
2057
;
-
 
2058
;  IN:  ebx = socket ptr
-
 
2059
;        cl = flags
-
 
2060
;
-
 
2061
;--------------------------------------
-
 
2062
align 4
-
 
2063
TCP_respond_socket:
-
 
2064
 
-
 
2065
	DEBUGF	1,"TCP_respond_socket\n"
-
 
2066
 
-
 
2067
;---------------------
-
 
2068
; Create the IP packet
-
 
2069
 
-
 
2070
	push	cx ebx
-
 
2071
	mov	eax, [ebx + IP_SOCKET.RemoteIP]
-
 
2072
	mov	ebx, [ebx + IP_SOCKET.LocalIP]
-
 
2073
	mov	ecx, TCP_segment.Data
-
 
2074
	mov	di , IP_PROTO_TCP shl 8 + 128
-
 
2075
	call	IPv4_output
-
 
2076
	test	edi, edi
-
 
2077
	jz	.error
-
 
2078
	pop	esi cx
-
 
2079
	push	edx eax
-
 
2080
 
-
 
2081
;-----------------------------------------------
-
 
2082
; Fill in the TCP header by using the socket ptr
-
 
2083
 
-
 
2084
	mov	ax, [esi + TCP_SOCKET.LocalPort]
-
 
2085
	rol	ax, 8
-
 
2086
	stosw
-
 
2087
	mov	ax, [esi + TCP_SOCKET.RemotePort]
-
 
2088
	rol	ax, 8
-
 
2089
	stosw
-
 
2090
	mov	eax, [esi + TCP_SOCKET.SND_NXT]
-
 
2091
	bswap	eax
-
 
2092
	stosd
-
 
2093
	mov	eax, [esi + TCP_SOCKET.RCV_NXT]
-
 
2094
	bswap	eax
-
 
2095
	stosd
-
 
2096
	mov	al, 0x50	; Dataoffset: 20 bytes
-
 
2097
	stosb
-
 
2098
	mov	al, cl
-
 
2099
	stosb
-
 
2100
	mov	ax, [esi + TCP_SOCKET.RCV_WND]
-
 
2101
	rol	ax, 8
-
 
2102
	stosw			; window
-
 
2103
	xor	eax, eax
-
 
2104
	stosd			; checksum + urgentpointer
-
 
2105
 
-
 
2106
;---------------------
-
 
2107
; Fill in the checksum
-
 
2108
 
-
 
2109
  .checksum:
-
 
2110
	sub	edi, TCP_segment.Data
-
 
2111
	mov	ecx, TCP_segment.Data
-
 
2112
	xchg	esi, edi
-
 
2113
	TCP_checksum (edi + IP_SOCKET.LocalIP), (esi + IP_SOCKET.RemoteIP)
-
 
2114
	mov	[esi+TCP_segment.Checksum], dx
-
 
2115
 
-
 
2116
;--------------------
-
 
2117
; And send the segment
-
 
2118
 
-
 
2119
	call	[ebx + NET_DEVICE.transmit]
-
 
2120
	ret
-
 
2121
 
-
 
2122
  .error:
-
 
2123
	DEBUGF	1,"TCP_respond failed\n"
-
 
2124
	add	esp, 2+4
-
 
2125
 
-
 
2126
	ret
-
 
2127
 
-
 
2128
 
-
 
2129
 
-
 
2130
;-------------------------
-
 
2131
; TCP_respond.segment:
-
 
2132
;
-
 
2133
;  IN:  edx = segment ptr (a previously received segment)
-
 
2134
;        cl = flags
-
 
2135
 
-
 
2136
align 4
-
 
2137
TCP_respond_segment:
-
 
2138
 
-
 
2139
	DEBUGF	1,"TCP_respond_segment\n"
-
 
2140
 
-
 
2141
;---------------------
-
 
2142
; Create the IP packet
-
 
2143
 
-
 
2144
	push	cx edx
-
 
2145
	mov	ebx, [edx - 20 + IPv4_Packet.SourceAddress]	 ;;;; and what if ip packet had options?!
-
 
2146
	mov	eax, [edx - 20 + IPv4_Packet.DestinationAddress]   ;;;
123
include 'tcp_timer.inc'
2147
	mov	ecx, TCP_segment.Data
-
 
2148
	mov	di , IP_PROTO_TCP shl 8 + 128
-
 
2149
	call	IPv4_output
-
 
2150
	jz	.error
-
 
2151
	pop	esi cx
-
 
2152
 
-
 
2153
	push	edx eax
-
 
2154
 
-
 
2155
;---------------------------------------------------
-
 
2156
; Fill in the TCP header by using a received segment
-
 
2157
 
-
 
2158
	mov	ax, [esi + TCP_segment.DestinationPort]
-
 
2159
	rol	ax, 8
-
 
2160
	stosw
-
 
2161
	mov	ax, [esi + TCP_segment.SourcePort]
-
 
2162
	rol	ax, 8
-
 
2163
	stosw
-
 
2164
	mov	eax, [esi + TCP_segment.AckNumber]
-
 
2165
	bswap	eax
-
 
2166
	stosd
-
 
2167
	xor	eax, eax
-
 
2168
	stosd
-
 
2169
	mov	al, 0x50	; Dataoffset: 20 bytes
-
 
2170
	stosb
-
 
2171
	mov	al, cl
-
 
2172
	stosb
-
 
2173
	mov	ax, 1280
-
 
2174
	rol	ax, 8
-
 
2175
	stosw			; window
-
 
2176
	xor	eax, eax
-
 
2177
	stosd			; checksum + urgentpointer
-
 
2178
 
-
 
2179
;---------------------
-
 
2180
; Fill in the checksum
-
 
2181
 
-
 
2182
  .checksum:
-
 
2183
	lea	esi, [edi - TCP_segment.Data]
-
 
2184
	mov	ecx, TCP_segment.Data
-
 
2185
	TCP_checksum (esi - 20 + IPv4_Packet.DestinationAddress), (esi - 20 + IPv4_Packet.DestinationAddress)
-
 
2186
	mov	[esi+TCP_segment.Checksum], dx
-
 
2187
 
-
 
2188
;--------------------
-
 
2189
; And send the segment
-
 
2190
 
-
 
2191
	call	[ebx + NET_DEVICE.transmit]
-
 
2192
	ret
-
 
2193
 
-
 
2194
  .error:
-
 
2195
	DEBUGF	1,"TCP_respond failed\n"
-
 
2196
	add	esp, 2+4
-
 
2197
 
-
 
Line 2198... Line 124...
2198
	ret
124
include 'tcp_subr.inc'
2199
 
125
include 'tcp_input.inc'
2200
 
126
include 'tcp_output.inc'