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 |