Subversion Repositories Kolibri OS

Rev

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

Rev 1473 Rev 1514
Line 1... Line 1...
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved.    ;;
3
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
5
;;                                                                 ;;
6
;;  TCP.INC                                                        ;;
6
;;  TCP.INC                                                        ;;
7
;;                                                                 ;;
7
;;                                                                 ;;
8
;;  Part of the tcp/ip network stack for KolibriOS                 ;;
8
;;  Part of the tcp/ip network stack for KolibriOS                 ;;
9
;;                                                                 ;;
9
;;                                                                 ;;
10
;;    Written by hidnplayr@kolibrios.org                           ;;
10
;;   Written by hidnplayr@kolibrios.org                            ;;
-
 
11
;;                                                                 ;;
11
;;    Inspired by the TCP code of Mike Hibbit for MenuetOS         ;;
12
;;    Based on the code of 4.4BSD                                  ;;
12
;;                                                                 ;;
13
;;                                                                 ;;
13
;;          GNU GENERAL PUBLIC LICENSE                             ;;
14
;;          GNU GENERAL PUBLIC LICENSE                             ;;
14
;;             Version 2, June 1991                                ;;
15
;;             Version 2, June 1991                                ;;
15
;;                                                                 ;;
16
;;                                                                 ;;
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Line -... Line 18...
-
 
18
 
Line -... Line 19...
-
 
19
$Revision: 1514 $
-
 
20
 
17
 
21
; Socket states
-
 
22
TCB_CLOSED		equ 0
-
 
23
TCB_LISTEN		equ 1
-
 
24
TCB_SYN_SENT		equ 2
-
 
25
TCB_SYN_RECEIVED	equ 3
-
 
26
TCB_ESTABLISHED 	equ 4
-
 
27
TCB_CLOSE_WAIT		equ 5
-
 
28
TCB_FIN_WAIT_1		equ 6
-
 
29
TCB_CLOSING		equ 7
-
 
30
TCB_LAST_ACK		equ 8
18
 
31
TCB_FIN_WAIT_2		equ 9
-
 
32
TCB_TIMED_WAIT		equ 10
-
 
33
 
-
 
34
; Socket Flags
-
 
35
TF_ACKNOW		equ 1 shl 0	; ack peer immediately
-
 
36
TF_DELACK		equ 1 shl 1	; ack, but try to delay it
-
 
37
TF_NODELAY		equ 1 shl 2	; don't delay packets to coalesce
-
 
38
TF_NOOPT		equ 1 shl 3	; don't use tcp options
19
$Revision: 1473 $
39
TF_SENTFIN		equ 1 shl 4	; have sent FIN
-
 
40
TF_REQ_SCALE		equ 1 shl 5	; have/will request window scaling
20
 
41
TF_RCVD_SCALE		equ 1 shl 6	; other side has requested scaling
21
TCP_RETRIES		equ 5		; Number of times to resend a Packet
42
TF_REQ_TSTMP		equ 1 shl 7	; have/will request timestamps
-
 
43
TF_RCVD_TSTMP		equ 1 shl 8	; a timestamp was received in SYN
-
 
44
TF_SACK_PERMIT		equ 1 shl 9	; other side said I could SACK
-
 
45
 
-
 
46
; Segment flags
-
 
47
TH_FIN			equ 1 shl 0
22
TCP_PACKET_TTL		equ 50		; resend if not replied to in 1/100 s
48
TH_SYN			equ 1 shl 1
-
 
49
TH_RST			equ 1 shl 2
-
 
50
TH_PUSH 		equ 1 shl 3
23
TCP_SOCKET_TTL		equ 10		; # of secs to wait before closing socket
51
TH_ACK			equ 1 shl 4
-
 
52
TH_URG			equ 1 shl 5
-
 
53
 
-
 
54
; Segment header options
-
 
55
TCP_OPT_EOL		equ 0		; End of option list.
-
 
56
TCP_OPT_NOP		equ 1		; No-Operation.
24
TCP_QUEUE_SIZE		equ 16
57
TCP_OPT_MAXSEG		equ 2		; Maximum Segment Size.
Line 25... Line -...
25
 
-
 
26
TCP_MAX_ACKS		equ 16
58
TCP_OPT_WINDOW		equ 3		; window scale
27
 
59
TCP_OPT_TIMESTAMP	equ 8
28
 
60
 
29
struct	TCP_Packet
61
struct	TCP_segment
30
	.SourcePort		dw ?
62
	.SourcePort		dw ?
31
	.DestinationPort	dw ?
63
	.DestinationPort	dw ?
32
	.SequenceNumber 	dd ?
64
	.SequenceNumber 	dd ?
33
	.AckNumber		dd ?
65
	.AckNumber		dd ?
34
	.DataOffset		db ?	; DataOffset[0-3 bits] and Reserved[4-7]
66
	.DataOffset		db ?	; DataOffset[0-3 bits] and Reserved[4-7]
35
	.Flags			db ?	; Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN
67
	.Flags			db ?	; Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN
36
	.Window 		dw ?
-
 
37
	.Checksum		dw ?
-
 
38
	.UrgentPointer		dw ?
68
	.Window 		dw ?
39
;        .Options                rb 3
69
	.Checksum		dw ?
Line 40... Line 70...
40
;        .Padding                db ?
70
	.UrgentPointer		dw ?
41
	.Data:
71
	.Data:				; ..or options
42
ends
72
ends
43
 
73
 
44
struct	tcp_in_queue_entry
74
struct	tcp_in_queue_entry
45
	.data_ptr	dd ?
75
	.data_ptr	dd ?
Line 46... Line 76...
46
	.data_size	dd ?
76
	.data_size	dd ?
47
	.offset 	dd ?	; TODO: replace this in code by absolute address isntead of relative offset
77
	.offset 	dd ?
48
	.size:
78
	.size:
49
ends
79
ends
50
 
-
 
51
struct	tcp_out_queue_entry
-
 
52
	.data_ptr	dd ?
-
 
53
	.data_size	dd ?
-
 
54
	.ttl		dd ?
-
 
55
	.retries	dd ?
80
 
56
	.owner		dd ?
81
struct	tcp_out_queue_entry
Line 57... Line 82...
57
	.sendproc	dd ?
82
	.data_ptr	dd ?
58
	.seq_num	dd ?
83
	.data_size	dd ?
59
	.socket 	dd ?
84
 
60
	.size:
85
	.size:
61
ends
-
 
62
 
-
 
63
align 4
86
ends
64
uglobal
-
 
65
	TCP_PACKETS_TX		rd  MAX_IP
-
 
66
	TCP_PACKETS_RX		rd  MAX_IP
-
 
67
 
87
 
68
	TCP_IN_QUEUE		rd  (tcp_in_queue_entry.size*TCP_QUEUE_SIZE+queue.data)/4
-
 
69
	TCP_OUT_QUEUE		dd  ?, ?
-
 
70
				rd  (tcp_out_queue_entry.size*TCP_QUEUE_SIZE)/4
-
 
71
 
-
 
72
	TCP_ACKS		dd  ?
88
align 4
73
	TCP_ACK_LIST		rd  3*TCP_MAX_ACKS
-
 
74
endg
-
 
75
 
-
 
76
align 4
-
 
77
iglobal
-
 
78
TCPstateHandler:
-
 
79
 
-
 
80
  dd  stateTCB_LISTEN
-
 
81
  dd  stateTCB_SYN_SENT
-
 
82
  dd  stateTCB_SYN_RECEIVED
-
 
83
  dd  stateTCB_ESTABLISHED
-
 
84
  dd  stateTCB_FIN_WAIT_1
-
 
85
  dd  stateTCB_FIN_WAIT_2
-
 
86
  dd  stateTCB_CLOSE_WAIT
89
uglobal
Line 87... Line 90...
87
  dd  stateTCB_CLOSING
90
	TCP_segments_tx 	rd IP_MAX_INTERFACES
88
  dd  stateTCB_LAST_ACK
91
	TCP_segments_rx 	rd IP_MAX_INTERFACES
Line 104... Line 107...
104
;-----------------------------------------------------------------
107
;-----------------------------------------------------------------
105
align 4
108
align 4
106
TCP_init:
109
TCP_init:
Line 107... Line 110...
107
 
110
 
108
	xor	eax, eax
111
	xor	eax, eax
109
	mov	edi, TCP_PACKETS_TX
112
	mov	edi, TCP_segments_tx
110
	mov	ecx, 2*MAX_IP
113
	mov	ecx, (6*IP_MAX_INTERFACES)
Line 111... Line -...
111
	rep	stosd
-
 
112
 
-
 
113
	init_queue TCP_IN_QUEUE
-
 
114
 
-
 
115
; tcp_out_queue is a special type of queue:
-
 
116
; The first dword is a counter of total packets queued.
-
 
117
; The remaining bytes are socket 'slots' wich use tcp_out_queue_entry data structure.
-
 
118
; An empty slot is know by the fact that tcp_out_queue_entry.data_ptr (first dword of the slot) is set to 0
-
 
119
; There are TCP_OUT_QUEUE_SIZE number of slots
-
 
120
 
114
	rep	stosd
121
	xor	eax, eax
-
 
122
	mov	esi, TCP_OUT_QUEUE
-
 
Line 123... Line 115...
123
	mov	ecx, TCP_QUEUE_SIZE*tcp_out_queue_entry/4+2+2+3*TCP_MAX_ACKS
115
 
Line 124... Line 116...
124
	rep	stosd
116
	mov	[TCP_sequence_num],1
125
 
117
 
126
	ret
118
	ret
127
 
119
 
128
 
120
 
129
;-----------------------------------------------------------------
121
;-----------------------------------------------------------------
130
;
122
;
-
 
123
; decrease socket ttls
-
 
124
;
131
;  TCP_decrease_socket_ttls
125
; IN: /
132
;
126
; OUT: /
133
;  IN:  /
127
;
134
;  OUT: /
128
; destroys: eax
Line 135... Line 129...
135
;
129
;
136
;-----------------------------------------------------------------
-
 
137
align 4
-
 
138
TCP_decrease_socket_ttls:
130
;-----------------------------------------------------------------
139
; scan through all the sockets, decrementing active timers
131
align 4
-
 
132
TCP_timer_1000ms:
140
 
133
; scan through all the active TCP sockets, decrementing active timers
141
	mov	ebx, net_sockets
134
 
Line 142... Line 135...
142
	cmp	[ebx + SOCKET_head.NextPtr], 0
135
	mov	eax, net_sockets
143
	je	.exit
136
  .loop:
144
  .next_socket:
-
 
145
	mov	ebx, [ebx + SOCKET_head.NextPtr]
-
 
Line 146... Line 137...
146
	or	ebx, ebx
137
	mov	eax, [eax + SOCKET.NextPtr]
147
	jz	.exit
138
  .check_only:
148
 
139
	or	eax, eax
149
	cmp	[ebx + SOCKET_head.Type], IP_PROTO_TCP
140
	jz	.exit
150
	jne	.next_socket
141
 
Line 151... Line 142...
151
 
142
	cmp	[eax + SOCKET.Type], IP_PROTO_TCP
152
;        DEBUGF  1, "K :   %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.state]
143
	jne	.loop
153
 
144
 
154
	cmp	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer], 0
145
	cmp	[eax + TCP_SOCKET.t_timer], 0
Line 155... Line 146...
155
	jne	.decrement_tcb
146
	jne	.decrement_tcb
156
	cmp	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 0
147
  ;;;;;;      cmp     [eax + TCP_SOCKET.wndsizeTimer], 0
Line 157... Line 148...
157
	jne	.decrement_wnd
148
	jne	.decrement_wnd
158
	jmp	.next_socket
149
	jmp	.loop
159
 
150
 
160
  .decrement_tcb:
151
  .decrement_tcb:
Line 161... Line 152...
161
; decrement it, delete socket if TCB timer = 0 & socket in timewait state
152
; decrement it, delete socket if TCB timer = 0 & socket in timewait state
162
	dec	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer]
153
	dec	[eax + TCP_SOCKET.t_timer]
163
	jnz	.next_socket
-
 
Line 164... Line 154...
164
 
154
	jnz	.loop
165
	cmp	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
155
 
Line 166... Line 156...
166
	jne	.next_socket
156
	cmp	[eax + TCP_SOCKET.t_state], TCB_TIMED_WAIT
167
 
-
 
168
	push	[ebx + SOCKET_head.PrevPtr]
-
 
169
	stdcall net_socket_free, ebx
-
 
170
	pop	ebx
-
 
171
	jmp	.next_socket
-
 
172
 
-
 
173
  .decrement_wnd:
157
	jne	.loop
174
	dec	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer]
-
 
175
	jmp	.next_socket
158
 
176
 
159
	push	[eax + SOCKET.NextPtr]
177
  .exit:
160
	call	SOCKET_free
178
	ret
161
	pop	eax
179
 
162
	jmp	.check_only
Line 180... Line 163...
180
 
163
 
181
 
-
 
Line 182... Line -...
182
;-----------------------------------------------------------------
-
 
183
;
164
  .decrement_wnd:
Line 184... Line -...
184
; TCP_send_queued:
-
 
185
;
-
 
186
;  Decreases 'ttl' of tcp packets queued.
-
 
Line 187... Line -...
187
;  if 'ttl' reaches 0, resend the packet and decrease 'retries'
-
 
188
;  if 'retries' reaches zero, remove the queued packet
-
 
189
;
-
 
190
;  IN:  /
-
 
191
;  OUT: /
-
 
192
;
-
 
193
;-----------------------------------------------------------------
-
 
194
align 4
-
 
Line 195... Line -...
195
TCP_send_queued:
-
 
196
 
165
;;;;;;        dec     [eax + TCP_SOCKET.wndsizeTimer]
197
	cmp	[TCP_OUT_QUEUE], 0
166
 
198
	je	.exit
-
 
199
 
167
  .exit:
200
	mov	ebx, TCP_OUT_QUEUE+4
168
	ret
201
	call	wait_mutex
169
 
202
 
170
 
203
	mov	eax, TCP_QUEUE_SIZE
171
 
204
	mov	ecx, [TCP_OUT_QUEUE]
-
 
205
	mov	esi, TCP_OUT_QUEUE+8
-
 
206
 
-
 
207
  .loop:
-
 
Line 208... Line -...
208
	cmp	[esi + tcp_out_queue_entry.data_ptr], 0
-
 
209
	jnz	.found_one
-
 
210
	add	esi, tcp_out_queue_entry.size
-
 
211
	loop	.loop
-
 
212
  .exit:
-
 
213
	mov	[TCP_OUT_QUEUE+4], 0
-
 
214
	ret
172
;----------------------
215
 
-
 
216
  .found_one:
-
 
217
	dec	[esi + tcp_out_queue_entry.ttl]
-
 
218
	jz	.send_it
173
;
219
	cmp	[esi + tcp_out_queue_entry.data_ptr], -1
-
 
220
	jz	.is_ack
174
; TCP_500ms
221
  .find_next:
-
 
222
	add	esi, tcp_out_queue_entry.size
-
 
223
	dec	eax
-
 
224
	jz	.exit
-
 
225
	test	ecx, ecx
-
 
226
	jnz	.loop
-
 
227
	mov	[TCP_OUT_QUEUE+4], 0
-
 
228
	ret
-
 
229
 
-
 
230
  .send_it:
-
 
Line 231... Line -...
231
	pusha
-
 
232
	mov	ebx, [esi + tcp_out_queue_entry.owner]
-
 
233
	pushd	[esi + tcp_out_queue_entry.data_size]
-
 
234
	pushd	[esi + tcp_out_queue_entry.data_ptr]
-
 
235
	DEBUGF 1,"Now sending TCP packet %x, size: %u, owner: %x, sendproc %x\n", [esp], [esp+4], ebx, [esi + tcp_out_queue_entry.sendproc]
-
 
236
	inc	[TCP_PACKETS_TX]
-
 
237
	call	[esi + tcp_out_queue_entry.sendproc]
-
 
238
	add	esp, 8
-
 
239
	popa
-
 
240
 
-
 
Line 241... Line 175...
241
	dec	[esi + tcp_out_queue_entry.retries]
175
;
242
	jz	.remove_it
176
;----------------------
243
 
177
align 4
244
	mov	[esi + tcp_out_queue_entry.ttl], TCP_PACKET_TTL
178
TCP_500ms:
-
 
179
 
-
 
180
	add	[TCP_sequence_num], 64000
-
 
181
 
-
 
182
	ret
-
 
183
 
-
 
184
 
245
	jmp	.find_next
185
 
246
 
186
;----------------------
247
  .remove_it:
187
;
248
	push	[esi + tcp_out_queue_entry.data_ptr]
-
 
249
	mov	[esi + tcp_out_queue_entry.data_ptr], 0
-
 
250
	call	kernel_free
-
 
251
	dec	[TCP_OUT_QUEUE]
-
 
252
	jmp	.find_next
-
 
253
 
-
 
254
  .is_ack:
188
; TCP_10ms
255
	pusha
189
;
256
	mov	eax, [esi + tcp_out_queue_entry.socket]
190
;----------------------
257
	mov	ebx, [esi + tcp_out_queue_entry.owner]
191
align 4
258
	mov	ecx, [esi + tcp_out_queue_entry.size]
192
TCP_10ms:
Line 259... Line 193...
259
	call	TCP_send_ack
193
 
Line -... Line 194...
-
 
194
	; todo: decrease timers
-
 
195
 
-
 
196
	ret
-
 
197
 
-
 
198
 
-
 
199
 
-
 
200
 
-
 
201
;-----------------------------------------------------------------
-
 
202
;
-
 
203
; TCP_input:
-
 
204
;
-
 
205
;  IN:  [esp] = ptr to buffer
-
 
206
;       [esp+4] = buffer size
-
 
207
;       ebx = ptr to device struct
-
 
208
;       ecx = segment size
260
	popa
209
;       edx = ptr to TCP segment
-
 
210
;
-
 
211
;       esi = ipv4 source address
-
 
212
;       edi = ipv4 dest   address
-
 
213
;
-
 
214
;  OUT: /
-
 
215
;
-
 
216
;-----------------------------------------------------------------
-
 
217
align 4
-
 
218
TCP_input:
-
 
219
 
-
 
220
       DEBUGF  1,"TCP_input\n"
-
 
221
 
-
 
222
; 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.
-
 
223
 
-
 
224
	movzx	eax, [edx + TCP_segment.DataOffset]
-
 
225
	and	eax, 0xf0
-
 
226
	shr	al , 2
-
 
227
 
-
 
228
	DEBUGF	1,"data offset: %u\n", eax
-
 
229
 
-
 
230
	cmp	eax, 20
-
 
231
	jl	.drop
-
 
232
 
-
 
233
	cmp	eax, ecx
-
 
234
	jg	.drop
-
 
235
 
-
 
236
;-------------------------------
-
 
237
; Now, re-calculate the checksum
-
 
238
 
-
 
239
	push	eax edx ebx
-
 
240
 
-
 
241
	push	edi
-
 
242
	push	esi
-
 
243
	mov	esi, edx
-
 
244
	call	TCP_checksum	; this destroys edx, ecx and esi (but not edi! :)
-
 
245
 
-
 
246
	pop	ebx edx eax
-
 
247
 
-
 
248
	cmp	[edx + TCP_segment.Checksum], 0
-
 
249
	jnz	.drop
-
 
250
 
-
 
251
	DEBUGF	1,"Checksum is correct\n"
-
 
252
 
-
 
253
;-----------------------------------------------------------------------------------------
-
 
254
; Check if this packet has a timestamp option (We do it here so we can process it quickly)
-
 
255
 
-
 
256
	cmp	eax, 20 + 12					; Timestamp option is 12 bytes
-
 
257
	jl	.no_timestamp
-
 
258
	je	.is_ok
-
 
259
 
-
 
260
	cmp	byte [edx + TCP_segment.Data + 12], 0		; end of option list
-
 
261
	jne	.no_timestamp
Line 261... Line -...
261
	mov	[esi + tcp_out_queue_entry.data_ptr], 0
-
 
262
	dec	[TCP_OUT_QUEUE]
-
 
263
	jmp	.find_next
262
 
264
 
263
  .is_ok:
265
 
264
	test	[edx + TCP_segment.Flags], TH_SYN		; SYN flag must not be set
Line 266... Line 265...
266
 
265
	jnz	.no_timestamp
Line 267... Line 266...
267
;-----------------------------------------------------------------
266
 
268
;
267
	cmp	dword [edx + TCP_segment.Data], 0x0101080a	; Timestamp header
269
; TCP_handler:
268
	jne	.no_timestamp
270
;
269
 
-
 
270
	DEBUGF	1,"timestamp ok\n"
-
 
271
 
-
 
272
	; TODO: Parse the options
Line 271... Line 273...
271
;  Called by IPv4_handler,
273
	; TODO: Set a Bit in the TCP to tell all options are parsed
272
;  this procedure will inject the tcp data diagrams in the application sockets.
274
 
273
;
275
	ret
Line 274... Line 276...
274
;  IN:  Pointer to buffer in [esp]
276
 
275
;       size of buffer in [esp+4]
277
  .no_timestamp:
276
;       pointer to device struct in ebx
278
 
277
;       TCP Packet size in ecx
279
;-------------------------------------------
278
;       pointer to TCP Packet in edx
280
; Convert Big-endian values to little endian
279
;       SourceAddres (IPv4) in esi
281
 
Line 280... Line 282...
280
;  OUT: /
282
	ntohld	[edx + TCP_segment.SequenceNumber]
281
;
283
	ntohld	[edx + TCP_segment.AckNumber]
282
;-----------------------------------------------------------------
284
 
283
align 4
285
	ntohlw	[edx + TCP_segment.Window]
284
TCP_handler :
286
	ntohlw	[edx + TCP_segment.UrgentPointer]
285
 
287
 
286
       DEBUGF 1,"TCP_Handler\n"
288
;------------------------------------------------------------
Line 287... Line 289...
287
 
289
; Next thing to do is find the TCB (thus, the socket pointer)
Line -... Line 290...
-
 
290
 
-
 
291
; IP Packet TCP Destination Port = local Port
-
 
292
; (IP Packet SenderAddress = Remote IP)  OR  (Remote IP = 0)
288
; TODO: validate checksum
293
; (IP Packet TCP Source Port = remote Port)  OR (remote Port = 0)
-
 
294
 
-
 
295
	mov	ebx, net_sockets
-
 
296
 
-
 
297
  .socket_loop:
-
 
298
	mov	ebx, [ebx + SOCKET.NextPtr]
-
 
299
	or	ebx, ebx
289
 
300
	jz	.drop_with_reset
290
; Find a matching socket for received packet, all following expressions must be valid:
301
 
Line 291... Line 302...
291
;
302
	cmp	[ebx + SOCKET.Type], IP_PROTO_TCP
292
; IP Packet TCP Destination Port = local Port
-
 
293
; (IP Packet SA = Remote IP)  OR  (Remote IP = 0)
-
 
294
; (IP Packet TCP Source Port = remote Port)  OR (remote Port = 0)
303
	jne	.socket_loop
Line 295... Line -...
295
 
-
 
296
	mov	ebx, net_sockets
304
 
297
 
-
 
298
  .socket_loop:
305
	mov	ax, [edx + TCP_segment.DestinationPort]
299
	mov	ebx, [ebx + SOCKET_head.NextPtr]
-
 
300
	or	ebx, ebx
-
 
Line 301... Line 306...
301
	jz	.dump
306
	cmp	[ebx + TCP_SOCKET.LocalPort], ax
302
 
307
	jne	.socket_loop
Line 303... Line 308...
303
	mov	ax, [edx + TCP_Packet.DestinationPort]
308
 
-
 
309
	mov	eax, [ebx + IP_SOCKET.RemoteIP]
Line 304... Line -...
304
	cmp	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort], ax
-
 
305
	jne	.socket_loop
-
 
306
 
-
 
307
	mov	eax, [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
-
 
308
	cmp	eax, esi
-
 
309
	je	@f
-
 
310
	test	eax, eax
-
 
311
	jne	.socket_loop
-
 
312
       @@:
-
 
313
 
-
 
314
	mov	ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort]
-
 
315
	cmp	[edx + TCP_Packet.SourcePort] , ax
-
 
316
	je	.found_socket
310
	cmp	eax, esi
Line 317... Line -...
317
	test	ax, ax
-
 
318
	jnz	.socket_loop
311
	je	@f
319
  .found_socket:
312
	test	eax, eax
320
       DEBUGF 1,"Found valid socket for packet\n"
-
 
Line 321... Line -...
321
 
-
 
322
	inc	[TCP_PACKETS_RX]
-
 
323
 
-
 
324
	add	ebx, SOCKET_head.lock
313
	jnz	.socket_loop
325
	call	wait_mutex
-
 
326
	sub	ebx, SOCKET_head.lock
-
 
327
 
-
 
Line 328... Line 314...
328
;-------------------------------
314
       @@:
329
; ebx is pointer to socket
315
 
Line 330... Line -...
330
; ecx is size of tcp packet
-
 
331
; edx is pointer to tcp packet
-
 
Line 332... Line 316...
332
 
316
	mov	ax, [ebx + TCP_SOCKET.RemotePort]
Line 333... Line -...
333
; calculate header length
-
 
334
	movzx	eax, [edx + TCP_Packet.DataOffset]
-
 
335
	and	eax, 11110000b
-
 
336
	shr	eax, 2
-
 
Line 337... Line -...
337
       DEBUGF 1,"TCP header size: %u\n", eax
-
 
338
	sub	ecx, eax
-
 
339
 
-
 
340
;-------------------------------
-
 
341
; ecx is size of tcp data
-
 
342
 
-
 
343
; as a Packet has been received, update the TCB timer
-
 
344
 
-
 
345
; If the received Packet has an ACK bit set, remove any Packets in the resend queue that this received Packet acknowledges
317
	cmp	[edx + TCP_segment.SourcePort] , ax
346
	test	[edx + TCP_Packet.Flags], TH_ACK
-
 
347
	jz	.no_ack 				 ; No ACK, so no data yet
-
 
348
 
-
 
349
; Calculate ACK number, in intel byte order
-
 
350
	mov	edi, [edx + TCP_Packet.AckNumber]
-
 
351
	bswap	edi
-
 
Line -... Line 318...
-
 
318
	je	.found_socket
352
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.last_ack_number], edi
319
	test	ax, ax
Line 353... Line -...
353
	DEBUGF 1,"Setting last_ack_number to %u\n", edi
-
 
354
 
-
 
355
; Dequeue all acknowledged packets
-
 
356
	cmp	[TCP_OUT_QUEUE], 0		; first, check if any packets are queued at all
-
 
Line 357... Line 320...
357
	je	.no_ack
320
	jnz	.socket_loop
Line -... Line 321...
-
 
321
  .found_socket:
-
 
322
       DEBUGF 1,"Socket ptr: %x\n", ebx
Line -... Line 323...
-
 
323
 
-
 
324
; ebx now contains the pointer to the socket
-
 
325
 
-
 
326
;----------------------------
-
 
327
; Check if socket isnt closed
-
 
328
 
-
 
329
	cmp	[TCP_SOCKET.t_state], TCB_CLOSED
-
 
330
	je	.drop
-
 
331
 
-
 
332
;----------------
-
 
333
; Lock the socket
-
 
334
 
-
 
335
	add	ebx, SOCKET.lock ; TODO: figure out if we should lock now already
358
 
336
	call	wait_mutex
-
 
337
	sub	ebx, SOCKET.lock
-
 
338
 
-
 
339
;---------------------------------------
-
 
340
; unscale the window into a 32 bit value  ;;;;;;
359
	push	ebx
341
 
-
 
342
	movzx	eax, [edx + TCP_segment.Window]
360
	mov	ebx, TCP_OUT_QUEUE+4
343
	xchg	al, ah
361
	call	wait_mutex
344
 
362
	pop	ebx
-
 
363
 
345
	test	[edx + TCP_segment.Flags], TH_SYN
364
	push	ecx
346
	jnz	.no_syn
365
	DEBUGF 1,"Removing all queued packets with smaller ACK\n"
347
 
366
	mov	ecx, TCP_QUEUE_SIZE
348
	mov	cl , [ebx + TCP_SOCKET.SND_SCALE]
-
 
349
	shl	eax, cl
-
 
350
 
-
 
351
  .no_syn:
-
 
352
 
-
 
353
;-----------------------------------
-
 
354
; Is this socket a listening socket?
-
 
355
 
-
 
356
; If so, create a new socket
-
 
357
 
-
 
358
	test	[ebx + SOCKET.options], SO_ACCEPTCON
-
 
359
	jz	.no_accept_conn
-
 
360
 
-
 
361
 
-
 
362
		; TODO: create a new socket
-
 
363
 
-
 
364
 
-
 
365
  .no_accept_conn:
-
 
366
 
-
 
367
;----------------------------
-
 
368
; Compute window scale factor
-
 
369
 
-
 
370
 
-
 
371
; TODO
-
 
372
 
367
	mov	esi, TCP_OUT_QUEUE+8
373
 
-
 
374
;-------------------------------------
-
 
375
; Reset idle timer and keepalive timer
-
 
376
 
-
 
377
 
-
 
378
; TODO
-
 
379
 
-
 
380
;-----------------------------------------
-
 
381
; Process TCP options if not in LISTEN state
-
 
382
 
-
 
383
	test	[ebx + TCP_SOCKET.t_state], TCB_LISTEN
-
 
384
	jz	.dont_do_options
-
 
385
 
-
 
386
	call	TCP_do_options
-
 
387
 
-
 
388
  .dont_do_options:
-
 
389
 
-
 
390
;-----------------------------------------------------------------------
-
 
391
; Time to do some header prediction (Original Principle by Van Jacobson)
-
 
392
 
-
 
393
 
-
 
394
; There are two common cases for an uni-directional data transfer.
-
 
395
;
-
 
396
; General rule: the packets has no control flags, is in-sequence,
-
 
397
;   window width didnt change and we're not retransmitting.
-
 
398
;
-
 
399
; Second rules:
-
 
400
;  -  If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
-
 
401
;      In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
-
 
402
;
-
 
403
;  -  If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
-
 
404
;      If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
-
 
405
 
-
 
406
	cmp	[TCP_SOCKET.t_state], TCB_ESTABLISHED
-
 
407
	jnz	.not_uni_xfer
-
 
408
 
-
 
409
	test	[TCP_segment.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
-
 
410
	jnz	.not_uni_xfer
-
 
411
 
-
 
412
	test	[TCP_segment.Flags], TH_ACK
-
 
413
	jz	.not_uni_xfer
-
 
414
 
-
 
415
	mov	eax, [edx + TCP_segment.SequenceNumber]
-
 
416
	cmp	eax, [ebx + TCP_SOCKET.RCV_NXT]
-
 
417
	jne	.not_uni_xfer
-
 
418
 
-
 
419
	movzx	eax, [edx + TCP_segment.Window] ;;;;;
-
 
420
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
-
 
421
	jne	.not_uni_xfer
-
 
422
 
-
 
423
	mov	eax, [ebx + TCP_SOCKET.SND_NXT]
-
 
424
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
-
 
425
	jne	.not_uni_xfer
-
 
426
 
-
 
427
;-------------------------------------------------------------------------------
-
 
428
; If last ACK falls within this segment's sequence number, record the timestamp.
-
 
429
 
-
 
430
	; TODO: check if it has a timestamp
-
 
431
 
-
 
432
 
-
 
433
 
-
 
434
 
-
 
435
;---------------------------------------
-
 
436
; check if we are sender in the uni-xfer
-
 
437
 
-
 
438
; If the following 4 conditions are all true, this segment is a pure ACK.
-
 
439
;
-
 
440
; - The segment contains no data (ti_len is 0).
-
 
441
 
-
 
442
	movzx	eax, [edx + TCP_segment.DataOffset]
-
 
443
	and	eax, 11110000b
-
 
444
	shr	eax, 2
-
 
445
	sub	ecx, eax
-
 
446
	jnz	.not_sender
-
 
447
 
-
 
448
; - The acknowledgment field in the segment (ti_ack) is greater than the largest unacknowledged sequence number (snd_una).
-
 
449
;     Since this test is "greater than" and not "greater than or equal to," it is true only if some positive amount of data is acknowledged by the ACK.
-
 
450
 
-
 
451
	mov	eax, [edx + TCP_segment.AckNumber]
-
 
452
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
-
 
453
	jle	.not_uni_xfer
-
 
454
 
-
 
455
; - The acknowledgment field in the segment (ti_ack) is less than or equal to the maximum sequence number sent (snd_max).
-
 
456
 
-
 
457
;        mov     eax, [edx + TCP_segment.Ack]
-
 
458
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
-
 
459
	jg	.not_uni_xfer
-
 
460
 
-
 
461
; - The congestion window (snd_cwnd) is greater than or equal to the current send window (snd_wnd).
-
 
462
;     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.
-
 
463
 
-
 
464
	mov	eax, [ebx + TCP_SOCKET.SND_CWND]
-
 
465
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
-
 
466
	jl	.not_uni_xfer
-
 
467
 
-
 
468
	DEBUGF	1,"Header prediction: we are sender\n"
-
 
469
 
-
 
470
;---------------------------------
-
 
471
; Packet is a pure ACK, process it
-
 
472
 
-
 
473
; Update RTT estimators
-
 
474
 
-
 
475
; Delete acknowledged bytes from send buffer
-
 
476
 
-
 
477
; Stop retransmit timer
-
 
478
 
-
 
479
; Awaken waiting processes
-
 
480
 
-
 
481
; Generate more output
-
 
482
 
-
 
483
 
-
 
484
 
-
 
485
 
-
 
486
	jmp	.drop
-
 
487
 
-
 
488
 
-
 
489
 
-
 
490
 
-
 
491
;-------------------------------------------------
-
 
492
; maybe we are the receiver in the uni-xfer then..
-
 
493
 
-
 
494
  .not_sender:
-
 
495
; The amount of data in the segment (ti_len) is greater than 0 (data count is in ecx)
-
 
496
 
-
 
497
 
-
 
498
; The acknowledgment field (ti_ack) equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
-
 
499
	mov	eax, [edx + TCP_segment.AckNumber]
-
 
500
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
-
 
501
	jne	.not_uni_xfer
-
 
502
 
-
 
503
; The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp).
-
 
504
;;;;
-
 
505
	jnz	.not_uni_xfer
-
 
506
 
-
 
507
; There is room in the receive buffer for the data in the segment.
-
 
508
;;;;
-
 
509
	jnz	.not_uni_xfer
-
 
510
 
-
 
511
;-------------------------------------
-
 
512
; Complete processing of received data
-
 
513
 
-
 
514
	DEBUGF	1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx
-
 
515
 
-
 
516
; The next expected receive sequence number (rcv_nxt) is incremented by the number of bytes of data.
-
 
517
 
-
 
518
	add	[ebx + TCP_SOCKET.RCV_NXT], ecx
-
 
519
 
-
 
520
; Add the data to the socket buffer
-
 
521
 
-
 
522
; The receiving process is awakened (by sorwakeup).
-
 
523
 
-
 
524
; The delayed-ACK flag is set and the input processing is complete.
-
 
525
 
-
 
526
	jmp	.drop
-
 
527
 
368
  .loop:
528
 
369
	cmp	[esi + tcp_out_queue_entry.data_ptr], 0
529
 
Line 370... Line 530...
370
	je	.maybe_next
530
 
Line 371... Line 531...
371
 
531
 
372
	cmp	[esi + tcp_out_queue_entry.socket], ebx
532
;----------------------------------------------------
Line 373... Line 533...
373
	jne	.maybe_next
533
; Header prediction failed, doing it the slow way..
374
 
534
 
375
	cmp	[esi + tcp_out_queue_entry.seq_num], edi
-
 
376
	jg	.maybe_next
-
 
Line 377... Line 535...
377
 
535
  .not_uni_xfer:
378
	DEBUGF 1,"Removing a queued packet\n"
-
 
379
 
536
 
Line 380... Line 537...
380
	push	[esi + tcp_out_queue_entry.data_ptr]
537
	DEBUGF	1,"Header prediction failed\n"
381
	mov	[esi + tcp_out_queue_entry.data_ptr], 0
-
 
382
	dec	[TCP_OUT_QUEUE]
-
 
383
	call	kernel_free
-
 
384
 
-
 
Line 385... Line 538...
385
  .maybe_next:
538
 
-
 
539
;------------------------
-
 
540
; calculate header length                               ;;;;; we already calculated this before!
-
 
541
	movzx	eax, [edx + TCP_segment.DataOffset]
-
 
542
	and	eax, 0xf0
-
 
543
	shr	eax, 2
-
 
544
 
386
	add	esi, tcp_out_queue_entry.size
545
; Update edx to point to data..
387
	loop	.loop
546
	add	edx, eax
388
 
547
; ..and ecx to give data size
389
	mov	[TCP_OUT_QUEUE+4], 0
548
	sub	ecx, eax
-
 
549
 
390
	pop	ecx
550
;------------------------------
-
 
551
; Calculate receive window size
-
 
552
 
391
 
553
	;;;;
392
; Now call the correct handler, depending on the socket state
554
 
-
 
555
 
393
  .no_ack:
556
;-------------------------
394
	mov	eax, [ebx +  SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state]
-
 
395
 
-
 
Line 396... Line 557...
396
	cmp	eax, TCB_LISTEN
557
; TCP slow input procedure
-
 
558
 
397
	jb	.dump
559
	DEBUGF	1,"TCP slow input procedure\n"
-
 
560
 
Line 398... Line -...
398
	cmp	eax, TCB_CLOSED
-
 
399
	ja	.dump
-
 
400
 
-
 
401
	call	dword [TCPstateHandler+eax*4-4]
-
 
402
 
-
 
403
  .dump:
-
 
404
	DEBUGF 1,"Dumping TCP packet\n"
-
 
405
	call	kernel_free
-
 
406
	add	esp, 4 ; pop (balance stack)
-
 
407
 
-
 
408
	ret
-
 
409
 
-
 
410
 
-
 
411
 
-
 
412
;-----------------------------------------------------------------
-
 
413
;
561
	cmp	[eax + TCP_SOCKET.t_state], TCB_LISTEN
414
; TCP_send  (Assumes socket mutex set)
-
 
415
;
-
 
416
; IN: eax = socket pointer
-
 
417
;      bl = flags
-
 
418
;      ecx = number of bytes to send, may be set to 0  (single ACK)
-
 
419
;      esi = pointer to data
-
 
420
;
-
 
421
;-----------------------------------------------------------------
-
 
422
align 4
-
 
423
TCP_send:
-
 
Line 424... Line 562...
424
 
562
	je	.LISTEN
425
	DEBUGF 1,"Creating TCP packet, socket: %x, flags: %x\n",eax, bl
-
 
426
 
-
 
427
	mov	di , IP_PROTO_TCP
-
 
428
	add	ecx, TCP_Packet.Data
-
 
429
 
-
 
430
	push	ecx bx eax esi
563
 
Line 431... Line -...
431
; Create an IPv4 Packet of the correct size
-
 
432
	mov	ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
-
 
433
	mov	eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
-
 
434
 
-
 
435
	call	IPv4_create_packet
-
 
436
	cmp	edi, -1
-
 
437
	je	.fail
564
	cmp	[eax + TCP_SOCKET.t_state], TCB_SYN_SENT
438
 
-
 
439
; If there is any data, copy it first
565
	je	.SYN_SENT
440
	pop	esi
-
 
Line 441... Line -...
441
	push	edi
-
 
442
	add	edi, TCP_Packet.Data
566
 
443
	sub	ecx, TCP_Packet.Data
-
 
444
 
567
 
Line 445... Line -...
445
	shr	ecx, 1
-
 
446
	jnc	.nb
568
;--------------------------------------------
Line 447... Line -...
447
	movsb
-
 
448
.nb:	shr	ecx, 1
-
 
Line 449... Line -...
449
	jnc	.nw
-
 
450
	movsw
-
 
451
.nw:	test	ecx, ecx
-
 
Line 452... Line -...
452
	jz	.nd
-
 
-
 
569
; Protection Against Wrapped Sequence Numbers
453
	rep	movsd
570
 
Line 454... Line 571...
454
.nd:
571
 
Line -... Line 572...
-
 
572
; First, check timestamp if present
-
 
573
 
-
 
574
;;;; TODO
-
 
575
 
-
 
576
; Then, check if at least some bytes of data are within window
-
 
577
 
-
 
578
;;;; TODO
-
 
579
 
-
 
580
	jmp	.trim_then_step6
-
 
581
 
-
 
582
align 4
-
 
583
.LISTEN:
-
 
584
 
-
 
585
	DEBUGF	1,"TCP state: listen\n"
-
 
586
 
-
 
587
	test	[edx + TCP_segment.Flags], TH_RST
-
 
588
	jnz	.drop
-
 
589
 
-
 
590
	test	[edx + TCP_segment.Flags], TH_ACK
-
 
591
	jnz	.drop_with_reset
-
 
592
 
-
 
593
	test	[edx + TCP_segment.Flags], TH_SYN
-
 
594
	jz	.drop
-
 
595
 
-
 
596
	; TODO: check if it's a broadcast or multicast, and drop if so
-
 
597
 
-
 
598
;;; 28.6
-
 
599
 
-
 
600
	; create a new socket and fill in the nescessary variables
-
 
601
 
-
 
602
;; Exit if backlog queue is full
-
 
603
;        mov     ax, [ebx + TCP_SOCKET.backlog_cur]
-
 
604
;        cmp     ax, [ebx + TCP_SOCKET.backlog]
-
 
605
;        jae     .exit
-
 
606
 
-
 
607
; Allocate new socket
-
 
608
	call	SOCKET_alloc
-
 
609
     ;;;   jz      .fail
-
 
610
 
-
 
611
; Copy structure from current socket to new, (including lock!)
-
 
612
; We start at PID to reserve the socket num, and the 2 pointers at beginning of socket
-
 
613
	lea	esi, [edx + SOCKET.PID]
-
 
614
	lea	edi, [eax + SOCKET.PID]
-
 
615
	mov	ecx, (TCP_SOCKET.end - SOCKET.PID + 3)/4
-
 
616
	rep	movsd
-
 
617
 
-
 
618
;; Push pointer to new socket to queue
-
 
619
;        movzx   ecx, [ebx + TCP_SOCKET.backlog_cur]
-
 
620
;        inc     [ebx + TCP_SOCKET.backlog_cur]
-
 
621
;        mov     [ebx + TCP_SOCKET.end + ecx*4], eax
-
 
622
 
-
 
623
	mov	[eax + IP_SOCKET.RemoteIP], esi ; IP source address
-
 
624
 
-
 
625
	mov	cx, [edx + TCP_segment.SourcePort]
-
 
626
	mov	[eax + TCP_SOCKET.RemotePort], cx
-
 
627
 
-
 
628
	mov	ecx, [edx + TCP_segment.SequenceNumber]
-
 
629
	mov	[eax + TCP_SOCKET.IRS], ecx
-
 
630
 
-
 
631
	mov	ecx, [eax + TCP_SOCKET.ISS]
-
 
632
	mov	[eax + TCP_SOCKET.SND_NXT], ecx
455
	pop	edi
633
 
-
 
634
	jmp	.trim_then_step6
-
 
635
 
-
 
636
 
-
 
637
 
-
 
638
align 4
-
 
639
.SYN_SENT:
456
 
640
 
-
 
641
	DEBUGF	1,"TCP state: syn_sent\n"
-
 
642
 
-
 
643
	test	[edx + TCP_segment.Flags], TH_ACK
-
 
644
	jz	@f
457
; Fill in the TCP header
645
 
-
 
646
	mov	eax, [edx + TCP_segment.AckNumber]
-
 
647
	cmp	eax, [ebx + TCP_SOCKET.ISS]
Line 458... Line -...
458
	pop	esi
-
 
459
 
-
 
Line 460... Line -...
460
; fill in tcp sequence number
-
 
461
	push	[esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
-
 
462
	pop	[edi + TCP_Packet.SequenceNumber]
-
 
463
 
-
 
Line 464... Line -...
464
; Fill in local and remote ports
-
 
465
	push	dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort]
-
 
466
	pop	dword [edi + TCP_Packet.SourcePort]
-
 
467
 
-
 
468
; Acknumber
-
 
469
	push	[esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
-
 
470
	pop	[edi + TCP_Packet.AckNumber]
-
 
471
 
-
 
472
; Fill  in other tcp options
-
 
473
	pop	cx
-
 
Line 474... Line -...
474
	mov	[edi + TCP_Packet.Flags], cl
-
 
475
	mov	[edi + TCP_Packet.Window], 0x0005	   ; 1280 bytes
-
 
476
	mov	[edi + TCP_Packet.UrgentPointer], 0
-
 
477
	mov	[edi + TCP_Packet.DataOffset], 0x50
648
	jle	.drop_with_reset
478
	mov	[edi + TCP_Packet.Checksum], 0
649
 
Line 479... Line 650...
479
 
650
	mov	eax, [edx + TCP_segment.AckNumber]
Line 480... Line 651...
480
; Get size of total packet back in ecx
651
	cmp	eax, [ebx + TCP_SOCKET.SND_MAX]
481
	pop	ecx
652
	jg	.drop_with_reset
Line -... Line 653...
-
 
653
       @@:
-
 
654
 
-
 
655
 
-
 
656
	test	[edx + TCP_segment.Flags], TH_RST
-
 
657
	jz	@f
-
 
658
 
-
 
659
	test	[edx + TCP_segment.Flags], TH_ACK
-
 
660
	jz	.drop
-
 
661
 
-
 
662
	;tp = tcp_drop(tp, ECONNREFUSED)
-
 
663
 
-
 
664
	jmp	.drop
-
 
665
       @@:
-
 
666
 
-
 
667
	test	[edx + TCP_segment.Flags], TH_SYN
-
 
668
	jz	.drop
-
 
669
 
-
 
670
; now, process received SYN in response to an active open
-
 
671
	test	[edx + TCP_segment.Flags], TH_ACK
-
 
672
	jz	@f
-
 
673
 
-
 
674
	mov	eax, [edx + TCP_segment.AckNumber]
-
 
675
	mov	[ebx + TCP_SOCKET.SND_UNA], eax
-
 
676
 
-
 
677
	mov	eax, [ebx + TCP_SOCKET.SND_UNA]
-
 
678
	cmp	eax, [ebx + TCP_SOCKET.SND_NXT]
-
 
679
	jle	@f
-
 
680
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
-
 
681
 
-
 
682
 
-
 
683
; TODO: turn off retransmission timer
-
 
684
 
-
 
685
	mov	eax, [edx + TCP_segment.SequenceNumber]
-
 
686
	mov	[ebx + TCP_SOCKET.IRS], eax
-
 
687
 
-
 
688
; TODO: set socket state to connected
-
 
689
 
-
 
690
	mov	[ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED
-
 
691
 
-
 
692
; TODO: check if we should scale the connection (567-572)
-
 
693
; TODO: update RTT estimators
-
 
694
 
-
 
695
 
-
 
696
       @@:
-
 
697
 
-
 
698
; We have received a syn but no ACK, so we are having a simultaneous open..
-
 
699
	mov	[ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
-
 
700
 
482
; Push pointer to and size of total packet (needed for send procedure)
701
;-------------------------------------
-
 
702
; Common processing for receipt of SYN
-
 
703
 
-
 
704
  .trimthenstep6:
-
 
705
 
-
 
706
	inc	[edx + TCP_segment.SequenceNumber]
-
 
707
 
-
 
708
	cmp	cx, [ebx + TCP_SOCKET.RCV_WND]
-
 
709
	jle	@f
-
 
710
 
-
 
711
	movzx	eax, cx
-
 
712
	sub	ax, [ebx + TCP_SOCKET.RCV_WND]
-
 
713
	; TODO: 592
-
 
714
	mov	cx, [ebx + TCP_SOCKET.RCV_WND]
-
 
715
	; TODO...
-
 
716
       @@:
-
 
717
	;;;;;
-
 
718
	;;; jmp     .step6
-
 
719
 
-
 
720
 
-
 
721
 
-
 
722
 
-
 
723
 
-
 
724
align 4
-
 
725
.trim_then_step6:
-
 
726
 
-
 
727
	DEBUGF	1,"Trim, then step 6\n"
-
 
728
 
-
 
729
;----------------------------
-
 
730
; trim any data not in window
-
 
731
 
-
 
732
	mov	eax, [ebx + TCP_SOCKET.RCV_NXT]
-
 
733
	sub	eax, [edx + TCP_segment.SequenceNumber]
-
 
734
 
-
 
735
	test	eax, eax
-
 
736
	jz	.no_drop
-
 
737
 
-
 
738
	test	[edx + TCP_segment.Flags], TH_SYN
-
 
739
	jz	.no_drop
-
 
740
 
-
 
741
	and	[edx + TCP_segment.Flags], not (TH_SYN)
-
 
742
	inc	[edx + TCP_segment.SequenceNumber]
-
 
743
 
-
 
744
	cmp	[edx + TCP_segment.UrgentPointer], 1
-
 
745
	jl	@f
-
 
746
 
-
 
747
	dec	[edx + TCP_segment.UrgentPointer]
-
 
748
 
-
 
749
	jmp	.no_drop
-
 
750
       @@:
-
 
751
 
-
 
752
	and	[edx + TCP_segment.Flags], not (TH_URG)
-
 
753
	dec	eax
-
 
754
 
-
 
755
  .no_drop:
-
 
756
 
-
 
757
; eax holds number of bytes to drop
-
 
758
 
-
 
759
 
-
 
760
;----------------------------------
-
 
761
; Check for entire duplicate packet
-
 
762
 
-
 
763
	cmp	eax, ecx
-
 
764
	jge	.duplicate
-
 
765
 
-
 
766
	;;; TODO: figure 28.30
-
 
767
 
-
 
768
;;        inc     [TCP_segments_rx]
-
 
769
 
-
 
770
;;        add     dword [TCP_bytes_rx], ecx
-
 
771
;;        adc     dword [TCP_bytes_rx+4], 0
-
 
772
 
-
 
773
;------------------------
-
 
774
; Check for duplicate FIN
-
 
775
 
-
 
776
	test	[edx + TCP_segment.Flags], TH_FIN
-
 
777
	jz	@f
-
 
778
	inc	ecx
-
 
779
	cmp	eax, ecx
-
 
780
	dec	ecx
-
 
781
	jne	@f
-
 
782
 
-
 
783
	mov	eax, ecx
-
 
784
	and	[edx + TCP_segment.Flags], not TH_FIN
-
 
785
	;;; TODO: set ACKNOW flag
-
 
786
 
-
 
787
	jmp	.no_duplicate
-
 
788
       @@:
-
 
789
 
-
 
790
	; Handle the case when a bound socket connects to itself
-
 
791
	; Allow packets with a SYN and an ACKto continue with the processing
-
 
792
 
-
 
793
 
-
 
794
;-------------------------------------
-
 
795
; Generate duplicate ACK if nescessary
-
 
796
 
-
 
797
; This code also handles simultaneous half-open or self-connects
-
 
798
 
-
 
799
	test	eax, eax
-
 
800
	jnz	.drop_after_ack
-
 
801
 
-
 
802
	cmp	[edx + TCP_segment.Flags], TH_ACK
-
 
803
	jz	.drop_after_ack
-
 
804
 
-
 
805
  .duplicate:
-
 
806
 
-
 
807
;----------------------------------------
-
 
808
; Update statistics for duplicate packets
-
 
809
 
-
 
810
	;;; TODO
-
 
811
 
-
 
812
	;;; DROP the packet ??
-
 
813
 
-
 
814
  .no_duplicate:
-
 
815
 
-
 
816
;-----------------------------------------------
-
 
817
; Remove duplicate data and update urgent offset
-
 
818
 
-
 
819
	add	[edx + TCP_segment.SequenceNumber], eax
-
 
820
 
-
 
821
	;;; TODO
-
 
822
 
-
 
823
	sub	[edx + TCP_segment.UrgentPointer], ax
-
 
824
	jg	@f
-
 
825
 
-
 
826
	and	[edx + TCP_segment.Flags], not (TH_URG)
-
 
827
	mov	[edx + TCP_segment.UrgentPointer], 0
-
 
828
       @@:
-
 
829
 
-
 
830
;--------------------------------------------------
-
 
831
; Handle data that arrives after process terminates
-
 
832
 
-
 
833
	cmp	[ebx + SOCKET.PID], 0
-
 
834
	jge	@f
-
 
835
 
-
 
836
	cmp	[ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT
-
 
837
	jle	@f
-
 
838
 
-
 
839
	test	ecx, ecx
-
 
840
	jz	@f
-
 
841
 
-
 
842
	;;; Close the socket
-
 
843
	;;; update stats
-
 
844
 
-
 
845
	jmp	.drop_with_reset
-
 
846
 
-
 
847
       @@:
-
 
848
 
-
 
849
;----------------------------------------
-
 
850
; Remove data beyond right edge of window
-
 
851
 
-
 
852
	mov	eax, [edx + TCP_segment.SequenceNumber]
-
 
853
	add	eax, ecx
-
 
854
	sub	eax, [ebx + TCP_SOCKET.RCV_NXT]
-
 
855
	sub	ax, [ebx + TCP_SOCKET.RCV_WND]
-
 
856
 
-
 
857
	; eax now holds the number of bytes to drop
-
 
858
 
-
 
859
	jle	.no_excess_data
-
 
860
 
-
 
861
	;;; TODO: update stats
-
 
862
 
-
 
863
	cmp	eax, ecx
-
 
864
	jl	.dont_drop_all
-
 
865
 
-
 
866
;;; TODO 700-736
-
 
867
 
-
 
868
  .dont_drop_all:
-
 
869
 
-
 
870
  .no_excess_data:
-
 
871
 
-
 
872
 
-
 
873
;-----------------
-
 
874
; Record timestamp
-
 
875
 
-
 
876
	;;; TODO 737-746
-
 
877
 
-
 
878
;------------------
-
 
879
; Process RST flags
-
 
880
 
-
 
881
	test	[edx + TCP_segment.Flags], TH_RST
-
 
882
	jz	.rst_skip
-
 
883
 
-
 
884
	mov	eax, [ebx + TCP_SOCKET.t_state]
-
 
885
	shl	eax, 2
-
 
886
	jmp	dword [eax + .rst_sw_list]
-
 
887
 
-
 
888
  .rst_sw_list:
-
 
889
	dd	.rst_skip	;TCB_CLOSED
-
 
890
	dd	.rst_skip	;TCB_LISTEN
-
 
891
	dd	.rst_skip	;TCB_SYN_SENT
-
 
892
	dd	.econnrefused	;TCB_SYN_RECEIVED
-
 
893
	dd	.econnreset	;TCB_ESTABLISHED
-
 
894
	dd	.econnreset	;TCB_CLOSE_WAIT
-
 
895
	dd	.econnreset	;TCB_FIN_WAIT_1
-
 
896
	dd	.rst_close	;TCB_CLOSING
-
 
897
	dd	.rst_close	;TCB_LAST_ACK
-
 
898
	dd	.econnreset	;TCB_FIN_WAIT_2
-
 
899
	dd	.rst_close	;TCB_TIMED_WAIT
-
 
900
 
-
 
901
  .econnrefused:
-
 
902
 
-
 
903
	;;; TODO: debug info
-
 
904
 
-
 
905
	jmp	.close
-
 
906
 
-
 
907
  .econnreset:
-
 
908
 
-
 
909
	;;; TODO: debug info
-
 
910
    .close:
-
 
911
 
-
 
912
	;;; update stats
-
 
913
 
-
 
914
  .rst_close:
-
 
915
 
-
 
916
	;;; Close the socket
-
 
917
	jmp	.drop
-
 
918
 
-
 
919
  .rst_skip:
-
 
920
 
-
 
921
;--------------------------------------
-
 
922
; handle SYN-full and ACK-less segments
-
 
923
 
-
 
924
	test	[edx + TCP_segment.Flags], TH_SYN
-
 
925
	jz	@f
-
 
926
 
-
 
927
	;;; tcp_drop ( ECONNRESET)
-
 
928
	jmp	.drop_with_reset
-
 
929
 
-
 
930
	test	[edx + TCP_segment.Flags], TH_ACK
-
 
931
	jz	.drop
-
 
932
 
-
 
933
;----------------
-
 
934
; Process the ACK
-
 
935
 
-
 
936
	cmp	[ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED
-
 
937
	jg	.ack_dup
-
 
938
	jl	.ack_nodup
-
 
939
 
-
 
940
;        dd      .ack_nodup      ;TCB_CLOSED
-
 
941
;        dd      .ack_nodup      ;TCB_LISTEN
-
 
942
;        dd      .ack_nodup      ;TCB_SYN_SENT
-
 
943
;        dd      .ack_syn_rcvd   ;TCB_SYN_RECEIVED
-
 
944
;        dd      .ack_dup        ;TCB_ESTABLISHED
-
 
945
;        dd      .ack_dup        ;TCB_CLOSE_WAIT
-
 
946
;        dd      .ack_dup        ;TCB_FIN_WAIT_1
-
 
947
;        dd      .ack_dup        ;TCB_CLOSING
-
 
948
;        dd      .ack_dup        ;TCB_LAST_ACK
-
 
949
;        dd      .ack_dup        ;TCB_FIN_WAIT_2
-
 
950
;        dd      .ack_dup        ;TCB_TIMED_WAIT
-
 
951
 
-
 
952
	;;;;;
-
 
953
 
-
 
954
  .ack_dup:
-
 
955
 
-
 
956
	;;;;
-
 
957
 
-
 
958
  .ack_nodup:
-
 
959
 
-
 
960
	;;;; 887
-
 
961
 
-
 
962
;-------------------------------------------------
-
 
963
; If the congestion window was infalted to account
-
 
964
; for the other side's cached packets, retrace it
-
 
965
 
-
 
966
	;;;; 888 -  902
-
 
967
 
-
 
968
 
-
 
969
;------------------------------------------
-
 
970
; RTT measurements and retransmission timer
-
 
971
 
-
 
972
	;;;;; 903 - 926
-
 
973
 
-
 
974
 
-
 
975
;-------------------------------------------
-
 
976
; Open congestion window in response to ACKs
-
 
977
 
-
 
978
	;;;;
-
 
979
 
-
 
980
 
-
 
981
;------------------------------------------
-
 
982
; Remove acknowledged data from send buffer
-
 
983
 
-
 
984
	;;;; 943 - 956
-
 
985
 
-
 
986
;---------------------------------------
-
 
987
; Wake up process waiting on send buffer
-
 
988
 
-
 
989
	;;;;;
-
 
990
 
-
 
991
	mov	eax, [ebx + TCP_SOCKET.t_state]
-
 
992
	shl	eax, 2
-
 
993
	jmp	dword [eax + .ACK_sw_list]
-
 
994
 
-
 
995
  .ACK_sw_list:
483
	push	edx eax
996
	dd	.step6		;TCB_CLOSED
-
 
997
	dd	.step6		;TCB_LISTEN
-
 
998
	dd	.step6		;TCB_SYN_SENT
-
 
999
	dd	.step6		;TCB_SYN_RECEIVED
-
 
1000
	dd	.step6		;TCB_ESTABLISHED
-
 
1001
	dd	.step6		;TCB_CLOSE_WAIT
-
 
1002
	dd	._963		;TCB_FIN_WAIT_1
-
 
1003
	dd	._958		;TCB_CLOSING
-
 
1004
	dd	._999		;TCB_LAST_ACK
-
 
1005
	dd	.step6		;TCB_FIN_WAIT_2
-
 
1006
	dd	._1010		;TCB_TIMED_WAIT
-
 
1007
 
-
 
1008
 
-
 
1009
._963:
-
 
1010
 
-
 
1011
 
-
 
1012
	jmp	.step6
-
 
1013
 
-
 
1014
 
-
 
1015
._958:
-
 
1016
 
-
 
1017
	jmp	.step6
-
 
1018
 
-
 
1019
._999:
-
 
1020
 
-
 
1021
	jmp	.step6
-
 
1022
 
-
 
1023
 
-
 
1024
._1010:
-
 
1025
 
-
 
1026
	jmp	.step6
-
 
1027
 
-
 
1028
 
-
 
1029
 
-
 
1030
align 4
-
 
1031
.step6:
-
 
1032
 
-
 
1033
	DEBUGF	1,"step 6\n"
-
 
1034
 
-
 
1035
;--------------------------
-
 
1036
; update window information
-
 
1037
 
-
 
1038
	test	[edx + TCP_segment.Flags], TH_ACK
-
 
1039
	jz	.no_window_update
-
 
1040
 
-
 
1041
	mov	eax, [ebx + TCP_SOCKET.SND_WL1]
-
 
1042
	cmp	eax, [edx + TCP_segment.SequenceNumber]
-
 
1043
 
-
 
1044
	;;;; 1021
-
 
1045
 
-
 
1046
;----------------------------------
-
 
1047
; Keep track of pure window updates
-
 
1048
 
-
 
1049
	test	ecx, ecx
-
 
1050
	jz	@f
-
 
1051
 
-
 
1052
	mov	eax, [ebx + TCP_SOCKET.SND_WL2]
-
 
1053
	cmp	eax, [edx + TCP_segment.AckNumber]
-
 
1054
	jne	@f
-
 
1055
 
-
 
1056
	;; mov eax, tiwin
-
 
1057
	cmp	eax, [ebx + TCP_SOCKET.SND_WND]
-
 
1058
	jle	@f
-
 
1059
 
-
 
1060
	;;; update stats
-
 
1061
 
-
 
1062
       @@:
-
 
1063
 
-
 
1064
	;; mov eax, incoming window
-
 
1065
	cmp	eax, [ebx + TCP_SOCKET.max_sndwnd]
-
 
1066
	jle	@f
-
 
1067
	mov	[ebx + TCP_SOCKET.max_sndwnd], eax
-
 
1068
       @@:
-
 
1069
	mov	[ebx + TCP_SOCKET.SND_WND], eax
-
 
1070
 
-
 
1071
	mov	eax, [edx + TCP_segment.SequenceNumber]
-
 
1072
	mov	[ebx + TCP_SOCKET.SND_WL1], eax
-
 
1073
 
-
 
1074
	mov	eax, [edx + TCP_segment.AckNumber]
-
 
1075
	mov	[ebx + TCP_SOCKET.SND_WL2], eax
-
 
1076
 
-
 
1077
	;;; needoutput = 1
-
 
1078
 
-
 
1079
  .no_window_update:
-
 
1080
 
-
 
1081
 
-
 
1082
;-----------------
-
 
1083
; process URG flag
-
 
1084
 
-
 
1085
	test	[edx + TCP_segment.Flags], TH_URG
-
 
1086
	jz	.not_urgent
-
 
1087
 
-
 
1088
	cmp	[edx + TCP_segment.UrgentPointer], 0
-
 
1089
	jz	.not_urgent
-
 
1090
 
-
 
1091
	cmp	[ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT
-
 
1092
	je	.not_urgent
-
 
1093
 
-
 
1094
; Ignore bogus urgent offsets
-
 
1095
 
-
 
1096
	;;; 1040-1050
-
 
1097
 
-
 
1098
	movzx	eax, [edx + TCP_segment.UrgentPointer]
-
 
1099
	add	eax, [ebx + SOCKET.SO_RCV.SB_CC]
-
 
1100
	cmp	eax, SOCKET_MAXDATA
-
 
1101
	jle	.not_urgent
-
 
1102
 
-
 
1103
	mov	[edx + TCP_segment.UrgentPointer], 0
-
 
1104
	and	[edx + TCP_segment.Flags], not (TH_URG)
-
 
1105
	jmp	.do_data
-
 
1106
 
-
 
1107
  .not_urgent:
-
 
1108
 
-
 
1109
;--------------------------------------
-
 
1110
; processing of received urgent pointer
484
; push socket number (for TCP_add_to_queue)
1111
 
-
 
1112
	;;; 1051-1093
485
	push	esi
1113
 
-
 
1114
align 4
Line 486... Line -...
486
 
-
 
487
; Now, calculate the checksum
-
 
488
	xchg	cl, ch
-
 
489
	pushw	cx
-
 
490
	xchg	cl, ch
-
 
491
	pushw	IP_PROTO_TCP shl 8
-
 
492
	pushd	[edi-4] ; destination address           ; TODO: fix this, IPv4 packet could have options..
-
 
493
	pushd	[edi-8] ; source address
-
 
494
 
-
 
495
	xor	edx, edx
-
 
496
	mov	esi, edi
-
 
497
	call	checksum_1
1115
.do_data:
498
	mov	ecx, 12
1116
 
Line -... Line 1117...
-
 
1117
	DEBUGF	1,"Do data:\n"
499
	mov	esi, esp
1118
 
Line -... Line 1119...
-
 
1119
	; process the data in the segment
500
	call	checksum_1
1120
 
Line 501... Line -...
501
; and store it in TCP header
-
 
502
	call	checksum_2
-
 
503
	mov	[edi + TCP_Packet.Checksum], dx
-
 
504
	add	esp, 10 				   ; remove the pseudoheader from stack
-
 
505
 
-
 
506
	DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
-
 
507
	mov	edx, [edi + TCP_Packet.SequenceNumber]
-
 
508
	bswap	edx
-
 
509
	mov	esi, [ebx + ETH_DEVICE.transmit]
-
 
510
 
-
 
511
	pop	cx					   ; get the length from packet, back from pseudoheader
-
 
512
	pop	edi
1121
	test	[edx + TCP_segment.Flags], TH_FIN
513
 
-
 
514
	cmp	cx, TCP_Packet.Data shl 8		   ; if the packet has no data
-
 
Line 515... Line 1122...
515
	je	.only_one				   ; send it only once
1122
	jz	.process_fin
-
 
1123
 
Line 516... Line 1124...
516
 
1124
	test	[ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_1 ;;;;;
Line -... Line 1125...
-
 
1125
	jge	.dont_do_data
Line -... Line 1126...
-
 
1126
 
-
 
1127
	DEBUGF	1,"Processing data in segment\n"
-
 
1128
 
-
 
1129
	;;; NOW, process the data
-
 
1130
 
-
 
1131
	jmp	.final_processing
517
	and	ecx, 0x0000ffff
1132
 
-
 
1133
 
-
 
1134
  .dont_do_data:
-
 
1135
 
-
 
1136
 
-
 
1137
;---------------
-
 
1138
; FIN processing
-
 
1139
 
-
 
1140
  .process_fin:
-
 
1141
 
-
 
1142
	DEBUGF	1,"Processing FIN\n"
-
 
1143
 
-
 
1144
	mov	eax, [ebx + TCP_SOCKET.t_state]
-
 
1145
	shl	eax, 2
-
 
1146
	jmp	dword [eax + .FIN_sw_list]
-
 
1147
 
-
 
1148
  .FIN_sw_list:
-
 
1149
	dd	.no_fin 	;TCB_CLOSED
-
 
1150
	dd	.no_fin 	;TCB_LISTEN
-
 
1151
	dd	.no_fin 	;TCB_SYN_SENT
-
 
1152
	dd	._1131		;TCB_SYN_RECEIVED
-
 
1153
	dd	._1131		;TCB_ESTABLISHED
-
 
1154
	dd	.no_fin 	;TCB_CLOSE_WAIT
-
 
1155
	dd	._1139		;TCB_FIN_WAIT_1
-
 
1156
	dd	.no_fin 	;TCB_CLOSING
-
 
1157
	dd	.no_fin 	;TCB_LAST_ACK
-
 
1158
	dd	._1147		;TCB_FIN_WAIT_2
-
 
1159
	dd	._1156		;TCB_TIMED_WAIT
-
 
1160
 
-
 
1161
 
-
 
1162
 
-
 
1163
  ._1131:
-
 
1164
 
-
 
1165
  ._1139:
-
 
1166
 
-
 
1167
  ._1147:
-
 
1168
 
-
 
1169
  ._1156:
-
 
1170
 
-
 
1171
 
-
 
1172
  .no_fin:
-
 
1173
 
-
 
1174
;-----------------
-
 
1175
; Final processing
-
 
1176
 
-
 
1177
  .final_processing:
-
 
1178
 
-
 
1179
	DEBUGF	1,"Final processing\n"
-
 
1180
 
-
 
1181
	;;; if debug enabled, output packet
518
	xchg	cl, ch
1182
 
519
	sub	cx, TCP_Packet.Data
1183
	;test    ;;;needoutput = 1
-
 
1184
	;jnz     .outputnow
520
 
1185
 
-
 
1186
	test	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
-
 
1187
	jz	.ret
-
 
1188
 
-
 
1189
  .outputnow:
-
 
1190
	call	TCP_output
-
 
1191
 
-
 
1192
  .ret:
-
 
1193
	mov	[ebx + SOCKET.lock], 0
-
 
1194
 
-
 
1195
	call	kernel_free
-
 
1196
	ret	4
-
 
1197
 
-
 
1198
;------------------------------------------
521
	add_INET (edi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT)     ; todo: this should only happen when packet was queued successful
1199
; Generate an ACK, droping incoming segment
522
	mov	ecx, TCP_RETRIES
1200
 
523
 
1201
align 4
524
	jmp	.go_for_it
1202
.drop_after_ack:
-
 
1203
 
525
 
1204
	DEBUGF	1,"Drop after ACK\n"
526
  .only_one:
1205
 
-
 
1206
	test	[edx + TCP_segment.Flags], TH_RST
-
 
1207
	jnz	.drop
Line -... Line 1208...
-
 
1208
 
-
 
1209
	and	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
527
	mov	ecx, 1
1210
 
Line 528... Line 1211...
528
  .go_for_it:
1211
	call	TCP_output
529
 
-
 
Line 530... Line -...
530
	mov	[edi + SOCKET_head.lock], 0
-
 
531
	jmp	TCP_queue				; At last send the packet!
-
 
532
 
-
 
Line 533... Line 1212...
533
  .fail:
1212
 
534
	add	esp, 2+4
1213
	mov	[ebx + SOCKET.lock], 0
-
 
1214
 
535
	or	eax, -1
1215
	call	kernel_free
536
	ret
-
 
537
 
-
 
538
 
-
 
539
;-----------------------------------------------------------------
-
 
540
;
-
 
541
;  Queue a TCP packet for sending
-
 
542
;
-
 
543
;  IN:  [esp] pointer to buffer
-
 
544
;       [esp + 4] size of buffer
-
 
Line 545... Line 1216...
545
;       ebx = driver struct
1216
	ret	4
-
 
1217
 
Line 546... Line 1218...
546
;       edx = sequence number of this packet in intel byte order
1218
 
547
;       esi = sender proc
1219
;-------------------------------------------
548
;       edi = socket number
-
 
549
 
1220
; Generate an RST, dropping incoming segment
550
;  OUT: /
-
 
Line -... Line 1221...
-
 
1221
 
551
;
1222
align 4
Line 552... Line -...
552
;-----------------------------------------------------------------
-
 
553
align 4
-
 
554
TCP_queue:
1223
.drop_with_reset:
Line 555... Line -...
555
 
-
 
Line -... Line 1224...
-
 
1224
 
556
	DEBUGF 1,"Adding packet to TCP queue, buffer: %x, size: %u, driver: %x, acknum: %u\n", [esp], [esp+4], ebx, edx
1225
	DEBUGF	1,"Drop with reset\n"
Line -... Line 1226...
-
 
1226
 
-
 
1227
	test	[edx + TCP_segment.Flags], TH_RST
Line 557... Line 1228...
557
 
1228
	jnz	.drop
558
	cmp	[TCP_OUT_QUEUE], TCP_QUEUE_SIZE
-
 
559
	jge	.full
1229
 
Line 560... Line 1230...
560
 
1230
	;;; if its a multicast/broadcast, also drop
561
	push	ebx
1231
 
Line 562... Line 1232...
562
	mov	ebx, TCP_OUT_QUEUE+4
1232
	test	[edx + TCP_segment.Flags], TH_ACK
Line 563... Line 1233...
563
	call	wait_mutex
1233
	jnz	.respond_ack
Line 564... Line -...
564
	pop	ebx
-
 
565
 
1234
 
566
	mov	ecx, TCP_QUEUE_SIZE
-
 
567
	mov	eax, TCP_OUT_QUEUE+8
-
 
568
  .loop:
-
 
Line 569... Line 1235...
569
	cmp	[eax + tcp_out_queue_entry.data_ptr], 0
1235
	test	[edx + TCP_segment.Flags], TH_SYN
570
	je	.found_it
1236
	jnz	.respond_syn
571
	add	eax, tcp_out_queue_entry.size
-
 
Line -... Line 1237...
-
 
1237
 
572
	loop	.loop
1238
	mov	[ebx + SOCKET.lock], 0
Line 573... Line 1239...
573
 
1239
 
574
	add	esp, 4
-
 
575
  .full:			; silently discard the packet
1240
	call	kernel_free
576
	DEBUGF 1,"TCP queue is full!\n"
1241
	ret	4
577
	call	kernel_free
1242
 
578
	add	esp, 4
-
 
579
 
1243
  .respond_ack:
580
	ret
1244
 
581
 
1245
	;;;;
-
 
1246
 
582
  .found_it:			; eax points to empty queue entry
1247
	call	TCP_respond
-
 
1248
 
-
 
1249
	jmp	.destroy_new_socket
583
 
1250
 
584
	mov	[eax + tcp_out_queue_entry.retries], TCP_RETRIES
1251
 
585
	pop	[eax + tcp_out_queue_entry.data_ptr]
1252
  .respond_syn:
-
 
1253
 
586
	pop	[eax + tcp_out_queue_entry.data_size]
1254
	;;;;
587
	mov	[eax + tcp_out_queue_entry.ttl], 1			; send immediately
1255
 
-
 
1256
	call	TCP_respond
588
	mov	[eax + tcp_out_queue_entry.owner], ebx
1257
 
589
	mov	[eax + tcp_out_queue_entry.sendproc], esi
1258
	jmp	.destroy_new_socket
-
 
1259
 
-
 
1260
;-----
-
 
1261
; Drop
590
	mov	[eax + tcp_out_queue_entry.seq_num], edx
1262
 
591
	mov	[eax + tcp_out_queue_entry.socket], edi
1263
align 4
-
 
1264
.drop:
592
 
1265
 
593
	inc	[TCP_OUT_QUEUE]
1266
	DEBUGF	1,"Dropping packet\n"
594
 
1267
 
595
	sub	eax, TCP_OUT_QUEUE+8
1268
	;;;; If debugging options are enabled, output the packet somwhere
-
 
1269
 
-
 
1270
  .destroy_new_socket:
-
 
1271
 
-
 
1272
	;;;; kill the newly created socket
596
	shr	eax, 5
1273
 
597
	DEBUGF 1,"Added to queue in pos %u, total queued packets: %u\n", eax, [TCP_OUT_QUEUE+8]
-
 
598
 
1274
	mov	[ebx + SOCKET.lock], 0
599
	mov	[TCP_OUT_QUEUE+4], 0
1275
 
600
 
1276
	call	kernel_free
601
	ret
1277
	ret	4
602
 
1278
 
603
 
1279
 
-
 
1280
 
604
;-----------------------------------------------------------------
1281
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
605
;
-
 
606
;  IN:  ebx = socket
-
 
Line 607... Line 1282...
607
;       ecx = ack number
1282
 
608
;
1283
 
609
;  OUT: /
-
 
610
;
-
 
611
;-----------------------------------------------------------------
1284
 
Line -... Line 1285...
-
 
1285
;---------------------
-
 
1286
;
-
 
1287
; TCP_do_options
-
 
1288
;
-
 
1289
;-------------------
-
 
1290
 
-
 
1291
align 4
-
 
1292
TCP_do_options:
-
 
1293
 
-
 
1294
	DEBUGF	1,"TCP_do_options\n"
-
 
1295
 
612
align 4
1296
	push	eax
-
 
1297
	sub	eax, 20
-
 
1298
	jz	.no_options
-
 
1299
 
613
TCP_queue_ack:
1300
	lea	esi, [edx + TCP_segment.Data]
-
 
1301
 
-
 
1302
 
-
 
1303
;-------------------------------------------
-
 
1304
; Begin the loop by checking for EOL and NOP
-
 
1305
 
-
 
1306
  .loop:
614
 
1307
 
Line -... Line 1308...
-
 
1308
	cmp	byte [esi], TCP_OPT_EOL 	; end of option list?
-
 
1309
	jz	.no_options
-
 
1310
 
-
 
1311
	cmp	byte [esi], TCP_OPT_NOP 	; nop ?
-
 
1312
      ;;;  cmove   edi, 1                          ; if so, set option size to 1
-
 
1313
	jz	.continue			; and continue scanning
-
 
1314
 
615
	DEBUGF 1,"Adding ACK to TCP queue, socket: %x, acknum: %u\n", ebx, ecx
1315
;------------------
616
 
1316
; We have an option
617
	cmp	[TCP_OUT_QUEUE], TCP_QUEUE_SIZE
1317
 
618
	jge	.full
1318
	movzx	edi, byte [esi + 1]		; get the length of this option in edi
619
 
1319
 
620
	push	ebx ecx
1320
 
-
 
1321
;--------------------------------------
621
	mov	ebx, TCP_OUT_QUEUE+4
1322
; Check for Maximum segment size option
622
	call	wait_mutex
1323
 
623
 
1324
	cmp	byte [esi], TCP_OPT_MAXSEG
624
	mov	ecx, TCP_QUEUE_SIZE
1325
	jne	.no_maxseg
625
	mov	eax, TCP_OUT_QUEUE+8
-
 
626
  .loop:
1326
 
627
	cmp	[eax + tcp_out_queue_entry.data_ptr], 0
1327
	cmp	edi, 4	; option length
Line 628... Line 1328...
628
	je	.found_it
1328
	jne	.continue
629
	add	eax, tcp_out_queue_entry.size
-
 
Line 630... Line 1329...
630
	loop	.loop
1329
 
-
 
1330
	test	[edx + TCP_segment.Flags], TH_SYN
631
 
1331
	jz	.continue
Line 632... Line 1332...
632
	add	esp, 8
1332
 
633
  .full:			; silently discard the packet
1333
	; Now parse the option...
634
	DEBUGF 1,"TCP queue is full!\n"
1334
 
Line 635... Line -...
635
	ret
-
 
636
 
-
 
637
  .found_it:			; eax points to empty queue entry
-
 
638
 
-
 
639
	pop	[eax + tcp_out_queue_entry.data_size]			; ACK number
-
 
640
	mov	[eax + tcp_out_queue_entry.data_ptr], -1		; ACK packet
-
 
641
	pop	[eax + tcp_out_queue_entry.socket]
-
 
642
	mov	[eax + tcp_out_queue_entry.retries], 1
1335
	jmp	.continue
643
	mov	[eax + tcp_out_queue_entry.ttl], 20			; 200 ms
1336
 
644
 
1337
  .no_maxseg:
Line 645... Line 1338...
645
	inc	[TCP_OUT_QUEUE]
1338
 
646
 
1339
;------------------------
647
	sub	eax, TCP_OUT_QUEUE+8
-
 
Line 648... Line 1340...
648
	shr	eax, 5
1340
; Check for Window option
649
	DEBUGF 1,"Added to queue in pos %u, total queued packets: %u\n", eax, [TCP_OUT_QUEUE+8]
1341
 
650
 
-
 
Line -... Line 1342...
-
 
1342
	cmp	byte [esi], TCP_OPT_WINDOW
-
 
1343
	jne	.no_window
-
 
1344
 
-
 
1345
	cmp	edi, 3 ; option length
Line -... Line 1346...
-
 
1346
	jne	.continue
-
 
1347
 
-
 
1348
	test	[edx + TCP_segment.Flags], TH_SYN
-
 
1349
	jz	.continue
-
 
1350
 
Line -... Line 1351...
-
 
1351
	; ...
Line -... Line 1352...
-
 
1352
 
-
 
1353
	jmp	.continue
-
 
1354
 
Line 651... Line 1355...
651
	mov	[TCP_OUT_QUEUE+4], 0
1355
  .no_window:
-
 
1356
 
Line -... Line 1357...
-
 
1357
;---------------------------
-
 
1358
; Check for Timestamp option
Line -... Line 1359...
-
 
1359
 
-
 
1360
	cmp	byte [esi], TCP_OPT_TIMESTAMP
Line -... Line 1361...
-
 
1361
	jne	.no_timestamp
Line -... Line 1362...
-
 
1362
 
652
 
1363
	cmp	edi, 10 ; option length
653
	ret
1364
	jne	.continue
Line 654... Line 1365...
654
 
1365
 
Line 655... Line -...
655
 
-
 
656
; IN: eax = socket pointer
-
 
657
;     ebx = device structure
-
 
658
;     ecx = ack number
-
 
659
 
-
 
660
align 4
-
 
661
TCP_send_ack:
-
 
662
 
-
 
663
	DEBUGF 1,"Creating TCP ACK packet, socket: %x, acknum: %x\n", eax, ecx
-
 
664
 
-
 
665
	push	ecx eax
-
 
666
 
-
 
667
	mov	di , IP_PROTO_TCP
-
 
668
	mov	ecx, TCP_Packet.Data
-
 
669
; Create an IPv4 Packet of the correct size
-
 
670
	mov	ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
-
 
671
	mov	eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
-
 
672
 
-
 
673
	call	IPv4_create_packet
-
 
674
	cmp	edi, -1
1366
	; ...
675
	je	.fail
-
 
676
 
-
 
677
	pop	ecx
-
 
678
 
1367
 
679
; fill in tcp sequence number
-
 
680
	push	[ecx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
-
 
681
	pop	[edi + TCP_Packet.SequenceNumber]
-
 
682
 
-
 
683
; Fill in local and remote ports
-
 
684
	push	dword [ecx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort]
-
 
685
	pop	dword [edi + TCP_Packet.SourcePort]
-
 
686
 
-
 
Line 687... Line 1368...
687
; Acknumber
1368
 
Line 688... Line -...
688
	pop	[edi + TCP_Packet.AckNumber]
-
 
689
 
-
 
690
; Fill  in other tcp options
-
 
691
	mov	[edi + TCP_Packet.Flags], TH_ACK
-
 
692
	mov	[edi + TCP_Packet.Window], 0x0005	   ; 1280 bytes
-
 
693
	mov	[edi + TCP_Packet.UrgentPointer], 0
1369
	jmp	.continue
Line 694... Line 1370...
694
	mov	[edi + TCP_Packet.DataOffset], 0x50
1370
 
695
	mov	[edi + TCP_Packet.Checksum], 0
-
 
696
 
1371
  .no_timestamp:
697
; Push pointer to and size of total packet (needed for send procedure)
1372
 
-
 
1373
;----------------------------------
-
 
1374
; Future options may be placed here
-
 
1375
 
Line 698... Line 1376...
698
	push	edx eax esi
1376
 
699
 
1377
 
700
; Now, calculate the checksum
-
 
Line -... Line 1378...
-
 
1378
 
701
	pushw	TCP_Packet.Data shl 8
1379
;------------------------------
702
	pushw	IP_PROTO_TCP shl 8
1380
; Continue scanning for options
-
 
1381
 
703
	pushd	[edi-4] ; destination address           ; TODO: fix this, IPv4 packet could have options..
1382
  .continue:
704
	pushd	[edi-8] ; source address
-
 
-
 
1383
	add	esi, edi
Line -... Line 1384...
-
 
1384
	sub	eax, edi
Line 705... Line 1385...
705
 
1385
	jg	.loop
706
	xor	edx, edx
1386
 
Line 707... Line 1387...
707
	mov	ecx, 12
1387
  .no_options:
Line 708... Line 1388...
708
	mov	esi, esp
1388
 
709
	call	checksum_1
1389
	pop	eax
-
 
1390
 
Line 710... Line 1391...
710
	call	checksum_2
1391
	ret
Line 711... Line 1392...
711
	mov	[edi + TCP_Packet.Checksum], dx
1392
 
712
	add	esp, 12 				; remove the pseudoheader from stack
-
 
Line 713... Line 1393...
713
 
1393
 
714
	pop	eax
-
 
715
	call	eax
-
 
-
 
1394
 
Line -... Line 1395...
-
 
1395
 
-
 
1396
;---------------------------
Line 716... Line 1397...
716
	call	kernel_free
1397
;
717
	add	esp, 4 ; pop (balance stack)
-
 
Line 718... Line 1398...
718
	ret
1398
; TCP_pull_out_of_band
719
 
-
 
Line -... Line 1399...
-
 
1399
;
720
  .fail:
1400
; IN:  eax =
-
 
1401
;      ebx = socket ptr
721
	add	esp, 8
1402
;      edx = tcp packet ptr
-
 
1403
;
-
 
1404
; OUT: /
Line 722... Line 1405...
722
	ret
1405
;
Line 723... Line -...
723
 
-
 
724
 
1406
;---------------------------
Line 725... Line -...
725
 
-
 
726
 
-
 
727
;-----------------------------------------------------------------
-
 
728
;
-
 
729
; Remove all queued TCP packets for a specified socket
-
 
730
;
-
 
731
; IN: eax = socket number
-
 
Line 732... Line -...
732
; OUT: /
-
 
733
;
1407
 
734
; destoys esi and ecx
-
 
Line 735... Line -...
735
;
-
 
736
;-----------------------------------------------------------------
-
 
Line -... Line 1408...
-
 
1408
align 4
737
 
1409
TCP_pull_out_of_band:
Line 738... Line -...
738
align 4
-
 
739
TCP_remove_socket:
1410
 
740
 
1411
	DEBUGF	1,"TCP_pull_out_of_band\n"
Line 741... Line -...
741
	cmp	[TCP_OUT_QUEUE], 0
-
 
742
	je	.skip
-
 
743
 
-
 
744
	mov	ebx, TCP_OUT_QUEUE+4
-
 
Line -... Line 1412...
-
 
1412
 
-
 
1413
	;;;; 1282-1305
Line -... Line 1414...
-
 
1414
 
Line 745... Line -...
745
	call	wait_mutex
-
 
746
 
1415
	ret
-
 
1416
 
Line 747... Line 1417...
747
	mov	eax, TCP_QUEUE_SIZE
1417
 
Line 748... Line -...
748
	mov	ecx, [TCP_OUT_QUEUE]
-
 
749
	mov	esi, TCP_OUT_QUEUE+8
1418
 
Line 750... Line -...
750
 
-
 
751
  .loop:
-
 
752
	cmp	[esi + tcp_out_queue_entry.data_ptr], 0
-
 
753
	jz	.maybenext
-
 
Line 754... Line 1419...
754
	cmp	[esi + tcp_out_queue_entry.socket], eax
1419
 
755
	jnz	.maybenext
1420
 
Line 756... Line 1421...
756
 
1421
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
757
	push	[esi + tcp_out_queue_entry.data_ptr]
-
 
758
	mov	[esi + tcp_out_queue_entry.data_ptr], 0
1422
 
Line 759... Line -...
759
	dec	[TCP_OUT_QUEUE]
-
 
760
	call	kernel_free
1423
 
761
 
-
 
Line 762... Line 1424...
762
  .maybenext:
1424
 
763
	add	esi, tcp_out_queue_entry.size
-
 
764
	loop	.loop
-
 
Line -... Line 1425...
-
 
1425
 
-
 
1426
 
Line -... Line 1427...
-
 
1427
;-----------------------------------------------------------------
765
 
1428
;
Line -... Line 1429...
-
 
1429
; TCP_output
-
 
1430
;
Line 766... Line 1431...
766
	mov	[TCP_OUT_QUEUE+4], 0
1431
; IN: eax = socket pointer
767
  .skip:
1432
;;     esi = ptr to data
-
 
1433
;;     ecx = number of data bytes
Line -... Line 1434...
-
 
1434
;
768
	ret
1435
; OUT: /
Line 769... Line 1436...
769
 
1436
;
770
 
1437
;-----------------------------------------------------------------
771
 
-
 
772
 
-
 
773
 
-
 
774
;---------- TCB state handlers start here
-
 
Line 775... Line 1438...
775
 
1438
align 4
776
 
1439
TCP_output:
777
 
1440
 
Line 778... Line -...
778
 
-
 
779
align 4
1441
	DEBUGF 1,"TCP_output, socket: %x\n", eax
780
stateTCB_LISTEN:
1442
 
781
 
-
 
782
	DEBUGF	1,"TCBStateHandler: Listen\n"
-
 
783
 
-
 
784
	test	[edx + TCP_Packet.Flags], TH_SYN	; SYN packet? => send syn+ack, open new socket and set connection to established
-
 
Line 785... Line -...
785
	jz	.exit
-
 
786
; Exit if backlog queue is full
1443
; We'll detect the length of the data to be transmitted, and flags to be used
787
	mov	ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
-
 
Line 788... Line 1444...
788
	cmp	ax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog]
1444
; If there is some data, or any critical controls to send (SYN / RST), then transmit
789
	jae	.exit
-
 
Line 790... Line -...
790
; Allocate new socket
-
 
791
	push	esi edi
-
 
792
	call	net_socket_alloc
-
 
793
	test	eax, eax
-
 
794
	jz	.fail
-
 
795
; Copy structure from current socket to new, including lock
-
 
796
	lea	esi, [ebx + SOCKET_head.PID]		; yes, PID must also be copied
-
 
797
	lea	edi, [eax + SOCKET_head.PID]
-
 
Line 798... Line -...
798
	mov	ecx, ((SOCKET_head.end - SOCKET_head.PID) + IPv4_SOCKET.end + TCP_SOCKET.end + 3)/4
-
 
799
	rep	movsd
-
 
800
	pop	edi esi
-
 
Line 801... Line -...
801
; Push pointer to new socket to queue
-
 
802
	movzx	ecx, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
1445
; Otherwise, investigate further
803
	inc	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
1446
 
Line 804... Line 1447...
804
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.end + ecx*4], eax
1447
	mov	ebx, [eax + TCP_SOCKET.SND_MAX]
Line 805... Line -...
805
 
-
 
806
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], esi ; IP source address
-
 
807
	mov	cx, [edx + TCP_Packet.SourcePort]
-
 
808
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], cx
1448
	cmp	ebx, [eax + TCP_SOCKET.SND_UNA]
Line 809... Line -...
809
	mov	ecx, [edx + TCP_Packet.SequenceNumber]
-
 
810
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.IRS], ecx
-
 
Line 811... Line -...
811
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], ecx
-
 
812
	lea	esi, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
-
 
813
	inc_INET esi ; RCV.NXT
-
 
Line 814... Line -...
814
	mov	ecx, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.ISS]
-
 
815
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT], ecx
-
 
816
 
-
 
817
	mov	[ebx + SOCKET_head.lock], 0
-
 
818
 
-
 
819
	push	eax
-
 
820
; Now construct the response
-
 
821
	mov	bl, TH_SYN + TH_ACK
-
 
822
	xor	ecx, ecx
-
 
823
	call	TCP_send
-
 
824
	pop	eax
-
 
Line 825... Line -...
825
 
-
 
826
	mov	[eax + SOCKET_head.lock], 0
-
 
827
	mov	[eax +	SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
-
 
Line -... Line 1449...
-
 
1449
	jne	.not_idle
-
 
1450
 
-
 
1451
	mov	ebx, [eax + TCP_SOCKET.t_idle]
-
 
1452
	cmp	ebx, [eax + TCP_SOCKET.t_rxtcur]
-
 
1453
	jle	.not_idle
-
 
1454
 
-
 
1455
; We have been idle for a while and no ACKS are expected to clock out any data we send..
-
 
1456
; Slow start to get ack "clock" running again.
Line 828... Line 1457...
828
	call	notify_network_event
1457
 
Line -... Line 1458...
-
 
1458
	mov	ebx, [eax + TCP_SOCKET.t_maxseg]
Line -... Line 1459...
-
 
1459
	mov	[eax + TCP_SOCKET.SND_CWND], ebx
-
 
1460
 
-
 
1461
  .not_idle:
-
 
1462
  .again:
-
 
1463
	mov	ebx, [eax + TCP_SOCKET.SND_NXT] 	; calculate offset
-
 
1464
	sub	ebx, [eax + TCP_SOCKET.SND_UNA] 	;
829
	ret
1465
 
-
 
1466
	mov	ecx, [eax + TCP_SOCKET.SND_WND] 	; determine window
-
 
1467
	cmp	ecx, [eax + TCP_SOCKET.SND_CWND]	;
-
 
1468
	jl	@f					;
-
 
1469
	mov	ecx, [eax + TCP_SOCKET.SND_CWND]	;
-
 
1470
       @@:						;
-
 
1471
 
-
 
1472
	call	TCP_outflags
-
 
1473
 
830
 
1474
; If in persist timeout with window of 0, send 1 byte.
-
 
1475
; Otherwise, if window is small but nonzero, and timer expired,
-
 
1476
; we will send what we can and go to transmit state
Line 831... Line 1477...
831
  .exit:
1477
 
Line -... Line 1478...
-
 
1478
	test	[eax + TCP_SOCKET.t_force], -1
-
 
1479
	jz	.no_persist_timeout
-
 
1480
 
-
 
1481
	test	ecx, ecx
-
 
1482
	jnz	.no_zero_window
-
 
1483
 
-
 
1484
	cmp	ebx, [eax + SOCKET.SO_SND.SB_CC]
-
 
1485
	jge	@f
-
 
1486
 
-
 
1487
	and	dl, not (TH_FIN)	  ; clear the FIN flag    ??? how can it be set before?
-
 
1488
 
832
	mov	[ebx + SOCKET_head.lock], 0
1489
       @@:
-
 
1490
	inc	ecx
833
	ret
1491
	jmp	.no_persist_timeout
-
 
1492
 
-
 
1493
  .no_zero_window:
-
 
1494
 
-
 
1495
;;;        mov     [eax + TCP_SOCKET.t_timer....TCPT_PERSIST], 0
-
 
1496
	mov	[eax + TCP_SOCKET.t_rxtshift], 0
-
 
1497
 
-
 
1498
  .no_persist_timeout:
-
 
1499
 
-
 
1500
;;;106
-
 
1501
 
-
 
1502
	mov	esi, [eax + SOCKET.SO_SND.SB_CC]
-
 
1503
	cmp	esi, ecx
-
 
1504
	jl	@f
-
 
1505
	mov	esi, ecx
-
 
1506
       @@:
-
 
1507
	sub	esi, ebx
-
 
1508
 
-
 
1509
	cmp	esi, -1
-
 
1510
	jne	.not_minus_one
-
 
1511
 
-
 
1512
; If FIN has been set, but not ACKed, and we havent been called to retransmit,
-
 
1513
; len (esi) will be -1
-
 
1514
; Otherwise, window shrank after we sent into it.
834
 
1515
; If window shrank to 0, cancel pending retransmit and pull SND_NXT back to (closed) window
-
 
1516
; We will enter persist state below.
-
 
1517
; If window didn't close completely, just wait for an ACK
-
 
1518
 
-
 
1519
	xor	esi, esi
835
  .fail:
1520
 
836
	add	esp, 8
-
 
837
	mov	[ebx + SOCKET_head.lock], 0
1521
	test	ecx, ecx
Line 838... Line 1522...
838
	ret
1522
	jnz	@f
839
 
-
 
Line 840... Line -...
840
 
-
 
841
align 4
1523
 
Line 842... Line -...
842
stateTCB_SYN_SENT:
-
 
843
 
1524
;;;        mov     [eax + TCP_SOCKET.t_timer..TCPT_REXMT], 0
844
	DEBUGF	1,"TCBStateHandler: Syn_Sent\n"
-
 
Line 845... Line -...
845
 
-
 
846
	; We are awaiting an ACK to our SYN, with a SYM
-
 
847
	; Look at control flags - expecting an ACK
-
 
848
 
-
 
849
	mov	al, [edx + TCP_Packet.Flags]
1525
 
850
 
1526
	push	[eax + TCP_SOCKET.SND_UNA]
-
 
1527
	pop	[eax + TCP_SOCKET.SND_NXT]
851
	test	al, TH_RST
1528
       @@:
852
	jnz	.reset			; jump if RST bit set
1529
 
853
 
1530
  .not_minus_one:
854
	push	[edx + TCP_Packet.SequenceNumber]				     ;;
1531
 
855
	pop	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]	     ;;
-
 
856
	inc_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT)      ;;
-
 
Line 857... Line -...
857
 
-
 
858
 
1532
;;; 124
859
	push	[edx + TCP_Packet.AckNumber]					    ;;;;;;
1533
 
Line 860... Line -...
860
	pop	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]	    ;;;;;;
-
 
861
 
-
 
862
	and	al, TH_SYN + TH_ACK
-
 
863
	jz	.exit			; jump if none of the following is set: RST, SYN, ACK
-
 
864
 
1534
	cmp	esi, [eax + TCP_SOCKET.t_maxseg]
865
	test	al, TH_ACK
-
 
866
	jz     .onlysyn 		; jump if only SYN bit is set
-
 
Line 867... Line -...
867
 
-
 
868
	; If we arrived here, SYN and ACK are set
-
 
869
 
1535
	jle	@f
Line 870... Line 1536...
870
	mov	[ebx +	SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
1536
 
871
	pushw	TH_ACK
-
 
872
 
-
 
Line 873... Line 1537...
873
  .send:	; Send an ACK
1537
	mov	esi, [eax + TCP_SOCKET.t_maxseg]
Line 874... Line -...
874
	mov	eax, ebx
-
 
875
	pop	bx
-
 
876
	push	eax
-
 
Line 877... Line 1538...
877
	xor	ecx, ecx
1538
	;sendalot = 1
-
 
1539
 
878
	call	TCP_send
1540
       @@:
-
 
1541
 
-
 
1542
;;; 128
-
 
1543
 
-
 
1544
	mov	edi, [eax + TCP_SOCKET.SND_NXT]
879
	pop	ebx
1545
	add	edi, esi	; len
880
 
1546
	sub	edi, [eax + TCP_SOCKET.SND_UNA]
881
  .exit:
1547
	add	edi, [eax + SOCKET.SO_SND.SB_CC]
-
 
1548
	cmp	edi, 0
882
	mov	[ebx + SOCKET_head.lock], 0
1549
	jle	@f
883
	ret
1550
 
884
 
1551
	and	dl, not (TH_FIN)	  ; clear the FIN flag
885
  .reset:
1552
 
886
	; TODO: ....
1553
       @@:
Line 887... Line -...
887
 
-
 
888
	; remove all queued TCP packets for this connection !
-
 
889
 
-
 
890
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSED
-
 
891
	mov	[ebx + SOCKET_head.lock], 0
-
 
892
	ret
-
 
893
 
-
 
894
  .onlysyn:
-
 
895
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
-
 
896
	pushw	TH_SYN + TH_ACK
-
 
897
	jmp	.send
-
 
898
 
-
 
899
 
-
 
900
 
-
 
901
align 4
-
 
902
stateTCB_SYN_RECEIVED:
-
 
903
 
1554
 
Line 904... Line -...
904
	DEBUGF	1,"TCBStateHandler: Syn_received\n"
-
 
905
 
-
 
906
	test	[edx + TCP_Packet.Flags], TH_RST	; reset connection? => LISTEN
-
 
Line 907... Line 1555...
907
	jz	.check_ack
1555
 
908
 
-
 
909
	push	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemotePort]
1556
;;;; 130 TODO: set window (ecx) to space in send buffer
Line -... Line 1557...
-
 
1557
 
Line 910... Line 1558...
910
	pop	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort]
1558
 
911
	push	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemoteIP]
1559
;------------------------------
-
 
1560
; Sender silly window avoidance
Line -... Line 1561...
-
 
1561
 
-
 
1562
	test	esi, esi
-
 
1563
	jz	.zero_length
912
	pop	[ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
1564
 
Line 913... Line 1565...
913
 
1565
 
914
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN
1566
	cmp	esi, [eax + TCP_SOCKET.t_maxseg]
915
	jmp	.exit
1567
	je	.send
-
 
1568
 
Line 916... Line 1569...
916
 
1569
;;; TODO: 144-145
917
  .check_ack:
1570
 
-
 
1571
	test	[eax + TCP_SOCKET.t_force], -1
Line -... Line 1572...
-
 
1572
	jnz	.send
918
	test	[edx + TCP_Packet.Flags], TH_ACK	; ACK? => connection established!
1573
 
919
	jz	.exit
1574
;;; TODO: 149..152
920
 
-
 
Line 921... Line -...
921
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
-
 
922
	mov	eax, ebx
-
 
923
	call	notify_network_event
-
 
924
 
-
 
Line 925... Line -...
925
  .exit:
-
 
926
	mov	[ebx + SOCKET_head.lock], 0
-
 
927
	ret
-
 
928
 
1575
 
929
 
-
 
930
if 0
1576
  .zero_length:
931
 
1577
 
932
 
-
 
Line 933... Line -...
933
align 4
-
 
934
stateTCB_ESTABLISHED:
1578
 
935
 
-
 
Line -... Line 1579...
-
 
1579
;----------------------------------------
Line -... Line 1580...
-
 
1580
; Check if a window update should be sent
Line 936... Line 1581...
936
	DEBUGF	1,"TCBStateHandler: Established\n"
1581
 
937
 
-
 
Line 938... Line -...
938
	mov	eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
-
 
Line 939... Line 1582...
939
	bswap	eax
1582
	cmp	ecx, 0	; window
940
	DEBUGF	1,"RCV_NXT is set to:%u\n", eax
1583
	jle	.no_window
Line -... Line 1584...
-
 
1584
 
-
 
1585
;;; TODO 154-172
941
	bswap	eax
1586
 
942
	cmp	eax, [edx + TCP_Packet.SequenceNumber]
1587
  .no_window:
Line 943... Line 1588...
943
	jne	.exit					;;;;;;
1588
 
-
 
1589
;--------------------------
944
 
1590
; Should a segment be sent?
-
 
1591
 
945
; check if we received an ACK
1592
	test	[ebx + TCP_SOCKET.t_flags], TF_ACKNOW
946
	test	[edx + TCP_Packet.Flags], TH_ACK
1593
	jnz	.send
-
 
1594
 
-
 
1595
	test	dl, TH_SYN + TH_RST
947
	jz	.no_ack
1596
	jnz	.send
-
 
1597
 
948
 
1598
	mov	eax, [ebx + TCP_SOCKET.SND_UP]
-
 
1599
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
949
	mov	ax, [edx + TCP_Packet.Window]
1600
	jg	.send
-
 
1601
 
-
 
1602
	test	dl, TH_FIN
-
 
1603
	jz	.enter_persist
-
 
1604
 
-
 
1605
	test	[ebx + TCP_SOCKET.t_flags], TF_SENTFIN
-
 
1606
	jnz	.send
-
 
1607
 
-
 
1608
	mov	eax, [ebx + TCP_SOCKET.SND_NXT]
-
 
1609
	cmp	eax, [ebx + TCP_SOCKET.SND_UNA]
-
 
1610
	je	.send
-
 
1611
 
-
 
1612
;--------------------
-
 
1613
; Enter persist state
-
 
1614
 
-
 
1615
  .enter_persist:
-
 
1616
 
Line 950... Line -...
950
	xchg	al, ah
-
 
951
	cmp	ax, 1024
-
 
952
	ja	@f
1617
	DEBUGF	1,"Entering pesist state\n"
Line -... Line 1618...
-
 
1618
 
-
 
1619
 
-
 
1620
 
-
 
1621
;--------------------------------------
-
 
1622
; No reason to send a segment, just ret
-
 
1623
 
-
 
1624
	DEBUGF	1,"No reason to send a segment\n"
-
 
1625
 
-
 
1626
	ret
953
	mov	[ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 1
1627
 
954
      @@:
1628
 
-
 
1629
 
-
 
1630
 
-
 
1631
 
Line 955... Line 1632...
955
  .no_ack:
1632
;-----------------------------------------------
956
 
-
 
957
; Now, see if we received any data
-
 
Line 958... Line -...
958
	test	ecx, ecx
-
 
959
	jz	.nodata
1633
;
Line -... Line 1634...
-
 
1634
; Send a segment
Line -... Line 1635...
-
 
1635
;
-
 
1636
; ebx = socket pointer
-
 
1637
;  dl = flags
-
 
1638
;
-
 
1639
;-----------------------------------------------
-
 
1640
 
-
 
1641
.send:
-
 
1642
 
-
 
1643
	DEBUGF	1,"Preparing to send a segment\n"
-
 
1644
 
-
 
1645
	xor	edi, edi	; edi will contain the number of header option bytes
Line -... Line 1646...
-
 
1646
 
-
 
1647
;------------------------------------
-
 
1648
; Send options with first SYN segment
-
 
1649
 
-
 
1650
	test	dl, TH_SYN
-
 
1651
	jz	.no_options
-
 
1652
 
-
 
1653
	mov	eax, [ebx + TCP_SOCKET.ISS]
-
 
1654
	mov	[ebx + TCP_SOCKET.SND_NXT], eax
-
 
1655
 
960
 
1656
	test	[ebx + TCP_SOCKET.t_flags], TF_NOOPT
961
; Calculate next sequencenumber
1657
	jnz	.no_options
Line 962... Line 1658...
962
	add_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT)
1658
 
Line 963... Line 1659...
963
 
1659
	mov	eax, TCP_OPT_MAXSEG shl 24 + 4 shl 16
964
	push	edx
1660
	mov	 ax, 1280 ;;;;;;
965
	DEBUGF	1,"Got %u bytes data!\n", ecx
-
 
Line 966... Line 1661...
966
; calculate header length
1661
	bswap	eax
Line -... Line 1662...
-
 
1662
	push	eax
-
 
1663
 
967
	movzx	eax, [edx + TCP_Packet.DataOffset]
1664
	mov	di, 4
Line 968... Line -...
968
	and	eax, 11110000b
-
 
969
	shr	eax, 2
1665
 
Line 970... Line -...
970
	DEBUGF	1,"TCP header size: %u\n", eax
-
 
971
	add	edx, eax	; now edx points to data
-
 
Line 972... Line -...
972
 
-
 
Line 973... Line -...
973
	add	esp, 4
-
 
974
	pop	esi		; pointer to buffer
-
 
975
	add	esp, 4
-
 
Line -... Line 1666...
-
 
1666
	test	[ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE
-
 
1667
	jz	.no_syn
-
 
1668
 
-
 
1669
	test	dl, TH_ACK
-
 
1670
	jnz	.scale_opt
-
 
1671
 
976
 
1672
	test	[ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
-
 
1673
	jz	.no_syn
-
 
1674
 
-
 
1675
  .scale_opt:
-
 
1676
 
-
 
1677
	mov	eax, TCP_OPT_WINDOW shl 24 + 4 shl 16 + TCP_OPT_NOP
-
 
1678
	mov	 ah, byte [ebx + TCP_SOCKET.request_r_scale]
Line 977... Line 1679...
977
	sub	edx, esi
1679
	bswap	eax
978
	mov	edi, edx	; offset
-
 
Line 979... Line -...
979
	mov	eax, ebx	; socket ptr
-
 
980
 
1680
	push	eax
Line -... Line 1681...
-
 
1681
 
-
 
1682
	add	di, 4
-
 
1683
 
-
 
1684
  .no_syn:
-
 
1685
 
-
 
1686
;------------------------------------
-
 
1687
; Make the timestamp option if needed
-
 
1688
 
-
 
1689
	test	[ebx + TCP_SOCKET.t_flags], TF_REQ_TSTMP
-
 
1690
	jz	.no_timestamp
-
 
1691
 
-
 
1692
	test	dl, TH_RST
-
 
1693
	jnz	.no_timestamp
-
 
1694
 
-
 
1695
	test	dl, TH_ACK
-
 
1696
	jz	.timestamp
-
 
1697
 
-
 
1698
	test	[ebx + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
981
	call	socket_internal_receiver	; Place the data from packet into socket
1699
	jz	.no_timestamp
982
 
1700
 
Line -... Line 1701...
-
 
1701
  .timestamp:
983
;        lea     ebx, [eax + SOCKET_head.lock]
1702
 
Line 984... Line 1703...
984
;        call    wait_mutex
1703
	DEBUGF	1,"Creating a timestamp\n"
-
 
1704
 
Line -... Line 1705...
-
 
1705
	push	dword (TCP_OPT_TIMESTAMP shl 8 + 10 + TCP_OPT_NOP shl 16 + TCP_OPT_NOP shl 24)
-
 
1706
	pushw	0
-
 
1707
	mov	eax, [timer_ticks]
-
 
1708
	bswap	eax
-
 
1709
	push	eax
-
 
1710
 
-
 
1711
	add	di, 10
-
 
1712
 
-
 
1713
  .no_timestamp:
-
 
1714
 
-
 
1715
	;; TODO: check if we dont exceed the max segment size
-
 
1716
 
985
	mov	ebx, eax
1717
  .no_options:
-
 
1718
	add	edi, TCP_segment.Data
-
 
1719
 
Line -... Line 1720...
-
 
1720
;-----------------------------------
-
 
1721
; Check if we have some data to send
Line 986... Line 1722...
986
	pop	edx
1722
 
-
 
1723
     ;;;   mov     ecx, [huppeldepup]
987
 
1724
 
-
 
1725
	test	ecx, ecx
Line 988... Line 1726...
988
	test	[edx + TCP_Packet.Flags], TH_FIN + TH_RST
1726
	jz	.no_data
-
 
1727
 
Line 989... Line 1728...
989
	jz	.ack
1728
	;;; 278-316
Line 990... Line -...
990
 
-
 
Line 991... Line 1729...
991
  .nodata:
1729
 
992
	test	[edx + TCP_Packet.Flags], TH_FIN + TH_RST
1730
	jmp	.header
Line 1267... Line 2005...
1267
.error:
2005
.error:
1268
	mov	eax, -1
2006
	mov	eax, -1
1269
	ret
2007
	ret
Line 1270... Line 2008...
1270
 
2008
 
1271
.packets_tx:
2009
.packets_tx:
1272
	add	eax, TCP_PACKETS_TX
2010
	add	eax, TCP_segments_tx
1273
	mov	eax, [eax]
2011
	mov	eax, [eax]
Line 1274... Line 2012...
1274
	ret
2012
	ret
1275
 
2013
 
1276
.packets_rx:
2014
.packets_rx:
1277
	add	eax, TCP_PACKETS_RX
2015
	add	eax, TCP_segments_rx