Subversion Repositories Kolibri OS

Rev

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

Rev 1019 Rev 1154
Line 25... Line 25...
25
;;   22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net          ;;
25
;;   22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net          ;;
26
;;   11.11.2006 - [Johnny_B] and [smb]                          ;;
26
;;   11.11.2006 - [Johnny_B] and [smb]                          ;;
27
;;                                                              ;;
27
;;                                                              ;;
28
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
28
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Line 29... Line 29...
29
 
29
 
Line 30... Line 30...
30
$Revision: 1019 $
30
$Revision: 1154 $
31
 
31
 
32
; socket data structure
32
; socket data structure
33
struct SOCKET
33
struct SOCKET
Line 64... Line 64...
64
 
64
 
65
; socket types
65
; socket types
66
SOCK_STREAM = 1
66
SOCK_STREAM = 1
Line -... Line 67...
-
 
67
SOCK_DGRAM  = 2
-
 
68
 
-
 
69
; pointer to bitmap of free ports (1=free, 0=used)
-
 
70
uglobal
-
 
71
align 4
-
 
72
network_free_ports	dd	?
-
 
73
endg
-
 
74
 
-
 
75
iglobal
-
 
76
align 4
-
 
77
network_free_hint	dd	1024/8
67
SOCK_DGRAM  = 2
78
endg
68
 
79
 
69
;; Allocate memory for socket data and put new socket into the list
80
;; Allocate memory for socket data and put new socket into the list
70
; Newly created socket is initialized with calling PID and number and
81
; Newly created socket is initialized with calling PID and number and
71
; put into beginning of list (which is a fastest way).
82
; put into beginning of list (which is a fastest way).
Line 151... Line 162...
151
	jne	.next_socket
162
	jne	.next_socket
152
	;cmp     [ebx + SOCKET.PID], ecx
163
	;cmp     [ebx + SOCKET.PID], ecx
153
	;jne     .next_socket
164
	;jne     .next_socket
Line 154... Line 165...
154
 
165
 
-
 
166
	; okay, we found the correct one
-
 
167
	; mark local port as unused
-
 
168
	movzx	ebx, [eax + SOCKET.LocalPort]
-
 
169
	push	eax
-
 
170
	mov	eax, [network_free_ports]
-
 
171
	xchg	bl, bh
-
 
172
lock	bts	[eax], ebx
155
	; okay, we found the correct one
173
	pop	eax
156
	; remove it from the list first, changing pointers
174
	; remove it from the list first, changing pointers
157
	mov	ebx, [eax + SOCKET.NextPtr]
175
	mov	ebx, [eax + SOCKET.NextPtr]
158
	mov	eax, [eax + SOCKET.PrevPtr]
176
	mov	eax, [eax + SOCKET.PrevPtr]
159
	mov	[eax + SOCKET.NextPtr], ebx
177
	mov	[eax + SOCKET.NextPtr], ebx
Line 251... Line 269...
251
;
269
;
252
; @param BX is a port number
270
; @param BX is a port number
253
; @return 1 (port is free) or 0 (port is in use) in EAX
271
; @return 1 (port is free) or 0 (port is in use) in EAX
254
;;
272
;;
255
proc is_localport_unused stdcall
273
proc is_localport_unused stdcall
256
	xchg	bl, bh
-
 
257
 
-
 
258
	; assume the return value is 'free'
-
 
259
	xor	eax, eax
274
	movzx	ebx, bx
260
	inc	al
-
 
261
 
-
 
262
	mov	edx, net_sockets
275
	mov	eax, [network_free_ports]
263
 
-
 
264
  .next_socket:
-
 
265
	mov	edx, [edx + SOCKET.NextPtr]
-
 
266
	or	edx, edx
276
	bt	[eax], ebx
267
	jz	.exit
-
 
268
	cmp	[edx + SOCKET.LocalPort], bx
-
 
269
	jne	.next_socket
-
 
270
 
-
 
271
	; return 'in use'
-
 
272
	dec	al
277
	setc	al
273
 
-
 
274
  .exit:
278
	movzx	eax, al
275
	ret
279
	ret
276
endp
280
endp
Line -... Line 281...
-
 
281
 
-
 
282
;======================================
-
 
283
set_local_port:
-
 
284
;--------------------------------------
-
 
285
;? Set local port in socket structure.
-
 
286
;--------------------------------------
-
 
287
;> eax -> struct SOCKET
-
 
288
;> bx = local port, or 0 if the kernel must select it itself
-
 
289
;--------------------------------------
-
 
290
;< CF set on error / cleared on success
-
 
291
;< [eax+SOCKET.LocalPort] filled on success
-
 
292
;======================================
-
 
293
; 0. Prepare: save registers, make eax point to ports table, expand port to ebx.
-
 
294
	push	eax ecx
-
 
295
	mov	eax, [network_free_ports]
-
 
296
	movzx	ebx, bx
-
 
297
; 1. Test, whether the kernel should choose port itself. If no, proceed to 5.
-
 
298
	test	ebx, ebx
-
 
299
	jnz	.given
-
 
300
; 2. Yes, it should. Set ecx = limit of table, eax = start value
-
 
301
	lea	ecx, [eax+0x10000/8]
-
 
302
	add	eax, [network_free_hint]
-
 
303
; 3. First scan loop: from free hint to end of table.
-
 
304
.scan1:
-
 
305
; 3a. For each dword, find bit set to 1
-
 
306
	bsf	ebx, [eax]
-
 
307
	jz	.next1
-
 
308
; 3b. If such bit has been found, atomically test again and clear it.
-
 
309
lock	btr	[eax], ebx
-
 
310
; 3c. If the bit was still set (usual case), we have found and reserved one port.
-
 
311
; Proceed to 6.
-
 
312
	jc	.found
-
 
313
; 3d. Otherwise, someone has reserved it between bsf and btr, so retry search.
-
 
314
	jmp	.scan1
-
 
315
.next1:
-
 
316
; 3e. All bits are cleared, so advance to next dword.
-
 
317
	add	eax, 4
-
 
318
; 3f. Check limit and continue loop.
-
 
319
	cmp	eax, ecx
-
 
320
	jb	.scan1
-
 
321
; 4. Second scan loop: from port 1024 (start of non-system ports) to free hint.
-
 
322
	mov	eax, [network_free_ports]
-
 
323
	mov	ecx, eax
-
 
324
	add	ecx, [network_free_hint]
-
 
325
	add	eax, 1024/8
-
 
326
; 4a. Test whether there is something to scan.
-
 
327
	cmp	eax, ecx
-
 
328
	jae	.fail
-
 
329
; 4b. Enter the loop, the process is same as for 3.
-
 
330
.scan2:
-
 
331
	bsf	ebx, [eax]
-
 
332
	jz	.next2
-
 
333
lock	btr	[eax], ebx
-
 
334
	jc	.found
-
 
335
	jmp	.scan2
-
 
336
.next2:
-
 
337
	add	eax, 4
-
 
338
	cmp	eax, ecx
-
 
339
	jb	.scan2
-
 
340
; 4c. None found. Fail.
-
 
341
.fail:
-
 
342
	pop	ecx eax
-
 
343
	stc
-
 
344
	ret
-
 
345
; 5. No, the kernel should reserve selected port.
-
 
346
.given:
-
 
347
; 5a. Atomically test old value and clear bit.
-
 
348
lock	btr	[eax], ebx
-
 
349
; 5b. If the bit was set, reservation is successful. Proceed to 8.
-
 
350
	jc	.set
-
 
351
; 5c. Otherwise, fail.
-
 
352
	jmp	.fail
-
 
353
.found:
-
 
354
; 6. We have found the bit set to 1, convert the position to port number.
-
 
355
	sub	eax, [network_free_ports]
-
 
356
	lea	ebx, [ebx+eax*8]
-
 
357
; 7. Update free hint.
-
 
358
	add	eax, 4
-
 
359
	cmp	eax, 65536/8
-
 
360
	jb	@f
-
 
361
	mov	eax, 1024/8
-
 
362
@@:
-
 
363
	mov	[network_free_hint], eax
-
 
364
.set:
-
 
365
; 8. Restore eax, set SOCKET.LocalPort and return.
-
 
366
	pop	ecx eax
-
 
367
	xchg	bl, bh	; Intel -> network byte order
-
 
368
	mov	[eax + SOCKET.LocalPort], bx
-
 
369
	clc
-
 
370
	ret
277
 
371
 
278
;; [53.0] Open DGRAM socket (connectionless, unreliable)
372
;; [53.0] Open DGRAM socket (connectionless, unreliable)
279
;
373
;
280
; @param BX is local port number
374
; @param BX is local port number
281
; @param CX is remote port number
375
; @param CX is remote port number
Line 289... Line 383...
289
 
383
 
Line 290... Line 384...
290
	DEBUGF	1, "K : socket_open (0x%x)\n", eax
384
	DEBUGF	1, "K : socket_open (0x%x)\n", eax
Line 291... Line 385...
291
 
385
 
292
	push	eax
386
	push	eax
293
 
387
 
294
	xchg	bh, bl
388
	call	set_local_port
295
	mov	[eax + SOCKET.LocalPort], bx
389
	jc	.error.free
296
	xchg	ch, cl
390
	xchg	ch, cl
297
	mov	[eax + SOCKET.RemotePort], cx
391
	mov	[eax + SOCKET.RemotePort], cx
Line 298... Line 392...
298
	mov	ebx, [stack_ip]
392
	mov	ebx, [stack_ip]
299
	mov	[eax + SOCKET.LocalIP], ebx
393
	mov	[eax + SOCKET.LocalIP], ebx
300
	mov	[eax + SOCKET.RemoteIP], edx
394
	mov	[eax + SOCKET.RemoteIP], edx
Line -... Line 395...
-
 
395
 
-
 
396
	;pop     eax      ; Get the socket number back, so we can return it
-
 
397
	stdcall net_socket_addr_to_num
301
 
398
	ret
302
	;pop     eax      ; Get the socket number back, so we can return it
399
 
303
	stdcall net_socket_addr_to_num
400
  .error.free:
304
	ret
401
	stdcall	net_socket_free;, eax
305
 
402
 
Line 355... Line 452...
355
	mov	[sockAddr], eax
452
	mov	[sockAddr], eax
Line 356... Line 453...
356
 
453
 
357
	; TODO - check this works!
454
	; TODO - check this works!
Line 358... Line 455...
358
	;mov     [eax + SOCKET.wndsizeTimer], 0     ; Reset the window timer.
455
	;mov     [eax + SOCKET.wndsizeTimer], 0     ; Reset the window timer.
359
 
456
 
360
	xchg	bh, bl
457
	call	set_local_port
361
	mov	[eax + SOCKET.LocalPort], bx
458
	jc	.error.free
362
	xchg	ch, cl
459
	xchg	ch, cl
363
	mov	[eax + SOCKET.RemotePort], cx
460
	mov	[eax + SOCKET.RemotePort], cx
364
	mov	[eax + SOCKET.OrigRemotePort], cx
461
	mov	[eax + SOCKET.OrigRemotePort], cx
Line 409... Line 506...
409
  .exit:
506
  .exit:
410
	; Get the socket number back, so we can return it
507
	; Get the socket number back, so we can return it
411
	stdcall net_socket_addr_to_num, [sockAddr]
508
	stdcall net_socket_addr_to_num, [sockAddr]
412
	ret
509
	ret
Line -... Line 510...
-
 
510
 
-
 
511
  .error.free:
-
 
512
	stdcall	net_socket_free, eax
413
 
513
 
414
  .error:
514
  .error:
415
	DEBUGF	1, "K : socket_open_tcp (fail)\n"
515
	DEBUGF	1, "K : socket_open_tcp (fail)\n"
416
	or	eax, -1
516
	or	eax, -1
417
	ret
517
	ret