Rev 1184 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1159 | hidnplayr | 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
||
3 | ;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
||
4 | ;; Distributed under terms of the GNU General Public License ;; |
||
5 | ;; ;; |
||
6 | ;; SOCKET.INC ;; |
||
7 | ;; ;; |
||
8 | ;; ;; |
||
9 | ;; Written by hidnplayr@kolibrios.org ;; |
||
10 | ;; based on code by mike.dld ;; |
||
11 | ;; ;; |
||
12 | ;; GNU GENERAL PUBLIC LICENSE ;; |
||
13 | ;; Version 2, June 1991 ;; |
||
14 | ;; ;; |
||
15 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
16 | |||
17 | $Revision: 1019 $ |
||
18 | |||
19 | align 4 |
||
20 | struct SOCKET |
||
21 | .PrevPtr dd ? ; pointer to previous socket in list |
||
22 | .NextPtr dd ? ; pointer to next socket in list |
||
23 | .Number dd ? ; socket number (unique within single process) |
||
24 | .PID dd ? ; application process id |
||
25 | .Domain dd ? ; INET/UNIX/.. |
||
26 | .Type dd ? ; RAW/UDP/TCP/... |
||
27 | .LocalIP dd ? ; local IP address |
||
28 | .RemoteIP dd ? ; remote IP address |
||
29 | .LocalPort dw ? ; local port |
||
30 | .RemotePort dw ? ; remote port |
||
31 | ; .OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state) |
||
32 | ; .OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state) |
||
33 | .rxDataCount dd ? ; rx data count |
||
34 | ; .TCBState dd ? ; TCB state |
||
35 | ; .TCBTimer dd ? ; TCB timer (seconds) |
||
36 | ; .ISS dd ? ; initial send sequence |
||
37 | ; .IRS dd ? ; initial receive sequence |
||
38 | ; .SND_UNA dd ? ; sequence number of unack'ed sent Packets |
||
39 | ; .SND_NXT dd ? ; bext send sequence number to use |
||
40 | ; .SND_WND dd ? ; send window |
||
41 | ; .RCV_NXT dd ? ; next receive sequence number to use |
||
42 | ; .RCV_WND dd ? ; receive window |
||
43 | ; .SEG_LEN dd ? ; segment length |
||
44 | ; .SEG_WND dd ? ; segment window |
||
45 | .wndsizeTimer dd ? ; window size timer |
||
46 | .lock dd ? ; lock mutex |
||
47 | .backlog dw ? ; Backlog |
||
48 | .rxData: ; receive data buffer here |
||
49 | ends |
||
50 | |||
51 | MAX_backlog equ 20 |
||
52 | |||
53 | ; socket buffers |
||
54 | SOCKETBUFFSIZE equ 4096 ; state + config + buffer. |
||
55 | SOCKETHEADERSIZE equ SOCKET.rxData ; thus 4096 - SOCKETHEADERSIZE bytes data |
||
56 | |||
57 | uglobal |
||
58 | net_sockets rd 2 |
||
59 | last_UDP_port dw ? ; These values give the number of the last used ephemeral port |
||
60 | last_TCP_port dw ? ; |
||
61 | endg |
||
62 | |||
63 | |||
64 | ;----------------------------------------------- |
||
65 | ; |
||
66 | ; SOCKET_init |
||
67 | ; |
||
68 | ; - |
||
69 | ; |
||
70 | ; IN: / |
||
71 | ; OUT: / |
||
72 | ; |
||
73 | ;----------------------------------------------- |
||
74 | |||
75 | align 4 |
||
76 | socket_init: |
||
77 | |||
78 | mov [net_sockets], 0 |
||
79 | mov [net_sockets + 4], 0 |
||
80 | |||
81 | mov [last_UDP_port], MIN_EPHEMERAL_PORT |
||
82 | mov [last_TCP_port], MIN_EPHEMERAL_PORT |
||
83 | |||
84 | ret |
||
85 | |||
86 | |||
87 | ;----------------------------------------------------------------------------- |
||
88 | ; |
||
89 | ; Socket API (function 74) |
||
90 | ; |
||
91 | ;----------------------------------------------------------------------------- |
||
92 | |||
93 | align 4 |
||
94 | sys_socket: |
||
95 | |||
96 | test bl, bl |
||
97 | jz socket_open ; 0 |
||
98 | dec bl |
||
99 | jz socket_close ; 1 |
||
100 | dec bl |
||
101 | jz socket_bind ; 2 |
||
102 | dec bl |
||
103 | jz socket_listen ; 3 |
||
104 | dec bl |
||
105 | jz socket_connect ; 4 |
||
106 | dec bl |
||
107 | jz socket_accept ; 5 |
||
108 | dec bl |
||
109 | jz socket_send ; 6 |
||
110 | dec bl |
||
111 | jz socket_recv ; 7 |
||
112 | |||
1185 | hidnplayr | 113 | s_error: |
1159 | hidnplayr | 114 | mov dword [esp+32],-1 |
115 | |||
116 | ret |
||
117 | |||
118 | |||
119 | |||
120 | |||
121 | ;----------------------------------------------- |
||
122 | ; |
||
123 | ; SOCKET_open |
||
124 | ; |
||
125 | ; |
||
126 | ; IN: domain in ecx |
||
127 | ; type in edx |
||
128 | ; set esi to zero, it is reserved for future use |
||
129 | ; OUT: eax is socket num, -1 on error |
||
130 | ; |
||
131 | ;----------------------------------------------- |
||
132 | socket_open: |
||
133 | |||
134 | DEBUGF 1,"socket_open: domain: %u, type: %u",ecx, edx |
||
135 | |||
136 | call net_socket_alloc |
||
137 | or eax, eax |
||
1185 | hidnplayr | 138 | jz s_error |
1159 | hidnplayr | 139 | |
140 | mov [eax + SOCKET.Domain], ecx |
||
141 | mov [eax + SOCKET.Type], edx |
||
142 | |||
143 | stdcall net_socket_addr_to_num, eax |
||
144 | DEBUGF 1,", socketnumber: %u\n", eax |
||
145 | |||
146 | mov [esp+32], eax |
||
147 | |||
148 | ret |
||
149 | |||
150 | |||
151 | |||
152 | |||
153 | ;----------------------------------------------- |
||
154 | ; |
||
155 | ; SOCKET_bind |
||
156 | ; |
||
157 | ; |
||
158 | ; IN: socket number in ecx |
||
159 | ; pointer to sockaddr struct in edx |
||
160 | ; length of that struct in esi |
||
161 | ; OUT: 0 on success |
||
162 | ; |
||
163 | ;----------------------------------------------- |
||
164 | |||
165 | socket_bind: |
||
166 | |||
167 | DEBUGF 1,"Socket_bind: socknum: %u sockaddr: %x, length: %u, ",ecx,edx,esi |
||
168 | |||
169 | stdcall net_socket_num_to_addr, ecx |
||
170 | cmp eax, -1 |
||
1185 | hidnplayr | 171 | jz s_error |
1159 | hidnplayr | 172 | |
173 | cmp esi, 2 |
||
1185 | hidnplayr | 174 | jl s_error |
1159 | hidnplayr | 175 | |
176 | cmp word [edx], AF_INET4 |
||
177 | je .af_inet4 |
||
178 | |||
1185 | hidnplayr | 179 | jmp s_error |
1159 | hidnplayr | 180 | |
181 | .af_inet4: |
||
182 | |||
183 | cmp esi, 6 |
||
1185 | hidnplayr | 184 | jl s_error |
1159 | hidnplayr | 185 | |
186 | mov bx, word [edx + 2] |
||
187 | DEBUGF 1,"local port: %u ",bx |
||
188 | test bx, bx |
||
189 | jnz .check_only |
||
190 | |||
191 | mov bx , [last_UDP_port] |
||
192 | |||
193 | .find_port_loop: |
||
194 | inc bx |
||
195 | inc [last_UDP_port] |
||
196 | |||
197 | .check_only: |
||
198 | mov esi, net_sockets |
||
199 | |||
200 | .next_udp_socket: |
||
201 | mov esi, [esi + SOCKET.NextPtr] |
||
202 | or esi, esi |
||
203 | jz .udp_port_ok |
||
204 | |||
205 | cmp [esi + SOCKET.Type], IP_PROTO_UDP |
||
206 | jne .next_udp_socket |
||
207 | |||
208 | cmp [esi + SOCKET.LocalPort], bx |
||
209 | jne .next_udp_socket |
||
210 | |||
211 | cmp word [edx + 2], 0 |
||
1185 | hidnplayr | 212 | jne s_error |
1159 | hidnplayr | 213 | |
214 | cmp bx, MAX_EPHEMERAL_PORT |
||
215 | jle .find_port_loop |
||
216 | |||
217 | mov [last_UDP_port], MIN_EPHEMERAL_PORT |
||
1185 | hidnplayr | 218 | jmp s_error |
1159 | hidnplayr | 219 | |
220 | .udp_port_ok: |
||
221 | mov word [eax + SOCKET.LocalPort], bx |
||
222 | |||
223 | mov ebx, dword [edx + 4] |
||
224 | mov dword [eax + SOCKET.LocalIP], ebx |
||
225 | |||
226 | DEBUGF 1,"local ip: %u.%u.%u.%u\n",\ |
||
227 | [eax + SOCKET.LocalIP]:1,[eax + SOCKET.LocalIP + 1]:1,[eax + SOCKET.LocalIP + 2]:1,[eax + SOCKET.LocalIP + 3]:1 |
||
228 | |||
229 | mov dword [esp+32],0 |
||
230 | ret |
||
231 | |||
232 | |||
233 | |||
234 | |||
235 | ;----------------------------------------------- |
||
236 | ; |
||
237 | ; SOCKET_connect |
||
238 | ; |
||
239 | ; |
||
240 | ; IN: socket number in ecx |
||
241 | ; pointer to sockaddr struct in edx |
||
242 | ; length of that struct in esi |
||
243 | ; OUT: 0 on success |
||
244 | ; |
||
245 | ;----------------------------------------------- |
||
246 | align 4 |
||
247 | |||
248 | socket_connect: |
||
249 | |||
250 | DEBUGF 1,"Socket_connect: socknum: %u sockaddr: %x, length: %u,",ecx,edx,esi |
||
251 | |||
252 | stdcall net_socket_num_to_addr, ecx |
||
253 | cmp eax, -1 |
||
1185 | hidnplayr | 254 | jz s_error |
1159 | hidnplayr | 255 | |
256 | cmp esi, 2 |
||
1185 | hidnplayr | 257 | jl s_error |
1159 | hidnplayr | 258 | |
259 | cmp word [edx], AF_INET4 |
||
260 | je .af_inet4 |
||
261 | |||
1185 | hidnplayr | 262 | jmp s_error |
1159 | hidnplayr | 263 | |
264 | .af_inet4: |
||
265 | |||
266 | cmp esi, 8 |
||
1185 | hidnplayr | 267 | jl s_error |
1159 | hidnplayr | 268 | |
269 | cmp [eax + SOCKET.Type], IP_PROTO_UDP |
||
270 | je .udp |
||
271 | |||
272 | cmp [eax + SOCKET.Type], IP_PROTO_ICMP |
||
273 | je .icmp |
||
274 | |||
275 | ; cmp [eax + SOCKET.Type], IP_PROTO_TCP |
||
276 | ; je .tcp |
||
277 | |||
1185 | hidnplayr | 278 | jmp s_error |
1159 | hidnplayr | 279 | |
280 | .udp: |
||
281 | |||
282 | mov bx , word [edx + 2] |
||
283 | mov word [eax + SOCKET.RemotePort], bx |
||
284 | |||
285 | DEBUGF 1,"remote port: %u ",bx |
||
286 | |||
287 | mov ebx, dword [edx + 4] |
||
288 | mov dword [eax + SOCKET.RemoteIP], ebx |
||
289 | |||
290 | DEBUGF 1,"remote ip: %u.%u.%u.%u\n",[edx+4]:1,[edx+5]:1,[edx+6]:1,[edx+7]:1 |
||
291 | |||
292 | mov dword [esp+32],0 |
||
293 | ret |
||
294 | |||
295 | .icmp: |
||
296 | |||
297 | |||
298 | ret |
||
299 | |||
300 | |||
301 | |||
302 | .tcp: |
||
303 | |||
304 | ;local sockAddr dd ? |
||
305 | |||
306 | ; cmp esi, SOCKET_PASSIVE |
||
307 | ; jne .skip_port_check |
||
308 | ; |
||
309 | ; push ebx |
||
310 | ; mov eax, ebx |
||
311 | ; xchg al, ah |
||
312 | ; mov ebx, net_sockets |
||
313 | ; |
||
314 | ; .next_socket: |
||
315 | ; mov ebx, [ebx + SOCKET.NextPtr] |
||
316 | ; or ebx, ebx |
||
317 | ; jz .last_socket |
||
318 | ; cmp [ebx + SOCKET.TCBState], TCB_LISTEN |
||
319 | ; jne .next_socket |
||
320 | ; cmp [ebx + SOCKET.LocalPort], ax |
||
321 | ; jne .next_socket |
||
322 | ; |
||
323 | ; xchg al, ah |
||
324 | ; DEBUGF 1, "K : error: port %u is listened by 0x%x\n", ax, ebx |
||
325 | ; pop ebx |
||
326 | ; jmp .error |
||
327 | ; |
||
328 | ; .last_socket: |
||
329 | ; pop ebx |
||
330 | ; |
||
331 | ; .skip_port_check: |
||
332 | |||
333 | ; mov [eax + SOCKET.wndsizeTimer], 0 ; Reset the window timer. |
||
334 | ; |
||
335 | ; xchg bh, bl |
||
336 | ; mov [eax + SOCKET.LocalPort], bx |
||
337 | ; xchg ch, cl |
||
338 | ; mov [eax + SOCKET.RemotePort], cx |
||
339 | ; mov [eax + SOCKET.OrigRemotePort], cx |
||
340 | ; mov ebx, [IP_LIST] |
||
341 | ; mov [eax + SOCKET.LocalIP], ebx |
||
342 | ; mov [eax + SOCKET.RemoteIP], edx |
||
343 | ; mov [eax + SOCKET.OrigRemoteIP], edx |
||
344 | |||
345 | ; mov ebx, TCB_LISTEN |
||
346 | ; cmp esi, SOCKET_PASSIVE |
||
347 | ; je @f |
||
348 | ; mov ebx, TCB_SYN_SENT |
||
349 | ; @@: mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB |
||
350 | |||
351 | ; cmp ebx, TCB_LISTEN |
||
352 | ; je .exit |
||
353 | |||
354 | ; Now, if we are in active mode, then we have to send a SYN to the specified remote port |
||
355 | ; mov eax, EMPTY_QUEUE |
||
356 | ; call dequeue |
||
357 | ; cmp ax, NO_BUFFER |
||
358 | ; je .exit |
||
359 | |||
360 | ; push eax |
||
361 | |||
362 | ; mov bl, TH_SYN |
||
363 | ; xor ecx, ecx |
||
364 | ; stdcall build_tcp_Packet, [sockAddr] |
||
365 | |||
366 | ; mov eax, NET1OUT_QUEUE |
||
367 | ; mov edx, [IP_LIST] |
||
368 | ; mov ecx, [sockAddr] |
||
369 | ; cmp edx, [ecx + SOCKET.RemoteIP] |
||
370 | ; jne .not_local |
||
371 | ; mov eax, IPIN_QUEUE |
||
372 | |||
373 | ; .not_local: |
||
374 | ; Send it. |
||
375 | ; pop ebx |
||
376 | ; call queue |
||
377 | |||
378 | .exit: |
||
379 | xor eax, eax |
||
380 | ret |
||
381 | |||
382 | |||
383 | |||
384 | |||
385 | ;----------------------------------------------- |
||
386 | ; |
||
387 | ; SOCKET_listen |
||
388 | ; |
||
389 | ; |
||
390 | ; IN: socket number in ecx |
||
391 | ; backlog in edx |
||
392 | ; OUT: eax is socket num, -1 on error |
||
393 | ; |
||
394 | ;----------------------------------------------- |
||
395 | |||
396 | socket_listen: |
||
397 | |||
398 | DEBUGF 1,"Socket_listen: socknum: %u backlog: %u\n",ecx,edx |
||
399 | |||
400 | stdcall net_socket_num_to_addr, ecx |
||
401 | cmp eax, -1 |
||
1185 | hidnplayr | 402 | jz s_error |
1159 | hidnplayr | 403 | |
404 | cmp edx, MAX_backlog |
||
405 | jl .ok |
||
406 | mov dx , 20 |
||
407 | .ok: |
||
408 | |||
409 | mov [eax + SOCKET.backlog], dx |
||
410 | |||
411 | ; TODO: insert code for active connections like TCP |
||
412 | |||
413 | mov dword [esp+32], 0 |
||
414 | ret |
||
415 | |||
416 | |||
417 | |||
418 | |||
419 | |||
420 | |||
421 | ;----------------------------------------------- |
||
422 | ; |
||
423 | ; SOCKET_accept |
||
424 | ; |
||
425 | ; |
||
426 | ; IN: socket number in ecx |
||
427 | ; addr in edx |
||
428 | ; addrlen in esi |
||
429 | ; OUT: eax is socket num, -1 on error |
||
430 | ; |
||
431 | ;----------------------------------------------- |
||
432 | |||
433 | |||
434 | socket_accept: |
||
435 | |||
436 | DEBUGF 1,"Socket_accept: socknum: %u sockaddr: %x, length: %u\n",ecx,edx,esi |
||
437 | |||
438 | stdcall net_socket_num_to_addr, ecx |
||
439 | or eax, eax |
||
1185 | hidnplayr | 440 | jz s_error |
1159 | hidnplayr | 441 | mov esi, eax |
442 | |||
443 | cmp [esi + SOCKET.backlog], 0 |
||
1185 | hidnplayr | 444 | jz s_error |
1159 | hidnplayr | 445 | |
446 | call net_socket_alloc |
||
447 | or eax, eax |
||
1185 | hidnplayr | 448 | jz s_error |
1159 | hidnplayr | 449 | mov edi, eax |
450 | |||
451 | dec [esi + SOCKET.backlog] |
||
452 | |||
453 | mov ecx, (SOCKET.rxData+3)/4 |
||
454 | rep movsd |
||
455 | |||
456 | mov [edi + SOCKET.backlog], 0 |
||
457 | |||
458 | ; TODO: fill in structure in ecx |
||
459 | |||
460 | mov [esi + SOCKET.RemoteIP], 0 |
||
461 | mov [esi + SOCKET.RemotePort], 0 |
||
462 | |||
463 | stdcall net_socket_addr_to_num, eax |
||
464 | mov [esp+32], eax |
||
465 | |||
466 | ret |
||
467 | |||
468 | |||
469 | |||
470 | ;----------------------------------------------- |
||
471 | ; |
||
472 | ; SOCKET_close |
||
473 | ; |
||
474 | ; |
||
475 | ; IN: socket number in ecx |
||
476 | ; OUT: eax is socket num, -1 on error |
||
477 | ; |
||
478 | ;----------------------------------------------- |
||
479 | |||
480 | socket_close: |
||
481 | |||
482 | DEBUGF 1,"Socket_close: socknum: %u\n",ecx |
||
483 | |||
484 | stdcall net_socket_num_to_addr, ecx |
||
485 | or eax, eax |
||
1185 | hidnplayr | 486 | jz s_error |
1159 | hidnplayr | 487 | |
488 | |||
489 | cmp [eax + SOCKET.Type], IP_PROTO_UDP |
||
490 | je .udp |
||
491 | |||
492 | cmp [eax + SOCKET.Type], IP_PROTO_ICMP |
||
493 | je .icmp |
||
494 | |||
495 | ; cmp [eax + SOCKET.Type], IP_PROTO_TCP |
||
496 | ; je .tcp |
||
497 | |||
1185 | hidnplayr | 498 | jmp s_error |
1159 | hidnplayr | 499 | |
500 | .udp: |
||
501 | |||
502 | lea ebx, [eax + SOCKET.lock] |
||
503 | call wait_mutex |
||
504 | ; TODO: mark the socket for deletion, using the mutex |
||
505 | |||
506 | stdcall net_socket_free, eax |
||
507 | |||
508 | mov dword [esp+32],0 |
||
509 | ret |
||
510 | |||
511 | |||
512 | .icmp: |
||
513 | |||
514 | |||
515 | |||
516 | ret |
||
517 | |||
518 | .tcp: |
||
519 | |||
520 | if 1 = 0 |
||
521 | ;local sockAddr dd ? |
||
522 | |||
523 | ; DEBUGF 1, "K : socket_close_tcp (0x%x)\n", ebx |
||
524 | ; first, remove any resend entries |
||
525 | pusha |
||
526 | |||
527 | mov esi, resendQ |
||
528 | mov ecx, 0 |
||
529 | |||
530 | .next_resendq: |
||
531 | cmp ecx, NUMRESENDENTRIES |
||
532 | je .last_resendq ; None left |
||
533 | cmp [esi + 4], ebx |
||
534 | je @f ; found one |
||
535 | inc ecx |
||
536 | add esi, 8 |
||
537 | jmp .next_resendq |
||
538 | |||
539 | @@: mov dword[esi + 4], 0 |
||
540 | inc ecx |
||
541 | add esi, 8 |
||
542 | jmp .next_resendq |
||
543 | |||
544 | .last_resendq: |
||
545 | popa |
||
546 | |||
547 | mov ebx, eax |
||
548 | ; mov [sockAddr], eax |
||
549 | |||
550 | cmp [eax + SOCKET.TCBState], TCB_LISTEN |
||
551 | je .destroy_tcb |
||
552 | cmp [eax + SOCKET.TCBState], TCB_SYN_SENT |
||
553 | je .destroy_tcb |
||
554 | |||
555 | ; Now construct the response, and queue for sending by IP |
||
556 | mov eax, EMPTY_QUEUE |
||
557 | call dequeue |
||
558 | cmp ax, NO_BUFFER |
||
559 | je .error |
||
560 | |||
561 | push eax |
||
562 | |||
563 | mov bl, TH_FIN |
||
564 | xor ecx, ecx |
||
565 | xor esi, esi |
||
566 | stdcall build_tcp_Packet, [sockAddr] |
||
567 | |||
568 | mov ebx, [sockAddr] |
||
569 | ; increament SND.NXT in socket |
||
570 | lea esi, [ebx + SOCKET.SND_NXT] |
||
571 | call inc_inet_esi |
||
572 | |||
573 | ; Get the socket state |
||
574 | mov eax, [ebx + SOCKET.TCBState] |
||
575 | cmp eax, TCB_SYN_RECEIVED |
||
576 | je .fin_wait_1 |
||
577 | cmp eax, TCB_ESTABLISHED |
||
578 | je .fin_wait_1 |
||
579 | |||
580 | ; assume CLOSE WAIT |
||
581 | ; Send a fin, then enter last-ack state |
||
582 | mov [ebx + SOCKET.TCBState], TCB_LAST_ACK |
||
583 | jmp .send |
||
584 | |||
585 | .fin_wait_1: |
||
586 | ; Send a fin, then enter finwait2 state |
||
587 | mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1 |
||
588 | |||
589 | .send: |
||
590 | mov eax, NET1OUT_QUEUE |
||
591 | mov edx, [IP_LIST] |
||
592 | ; mov ecx, [sockAddr] |
||
593 | cmp edx, [ecx + SOCKET.RemoteIP] |
||
594 | jne .not_local |
||
595 | mov eax, IPIN_QUEUE |
||
596 | |||
597 | .not_local: |
||
598 | ; Send it. |
||
599 | pop ebx |
||
600 | call queue |
||
601 | jmp .exit |
||
602 | |||
603 | |||
604 | .destroy_tcb: |
||
605 | |||
606 | stdcall net_socket_free, eax |
||
607 | |||
608 | end if |
||
609 | |||
610 | .exit: |
||
611 | mov dword [esp+32],0 |
||
612 | ret |
||
613 | |||
614 | |||
615 | |||
616 | |||
617 | ;----------------------------------------------- |
||
618 | ; |
||
619 | ; SOCKET_receive |
||
620 | ; |
||
621 | ; |
||
622 | ; IN: socket number in ecx |
||
623 | ; addr in edx |
||
624 | ; addrlen in esi |
||
625 | ; flags in edi |
||
626 | ; OUT: eax is number of bytes copied, -1 on error |
||
627 | ; |
||
628 | ;----------------------------------------------- |
||
629 | |||
630 | socket_recv: |
||
631 | |||
632 | DEBUGF 1,"Socket_receive: socknum: %u sockaddr: %x, length: %u, flags: %x\n",ecx,edx,esi,edi |
||
633 | |||
634 | stdcall net_socket_num_to_addr, ecx ; get real socket address |
||
635 | or eax, eax |
||
1185 | hidnplayr | 636 | jz s_error |
1159 | hidnplayr | 637 | |
638 | DEBUGF 1,"real socket address:%x\n", eax |
||
639 | |||
640 | mov dword[esp+32], -1 |
||
641 | |||
642 | mov edi, edx |
||
643 | |||
644 | lea ebx, [eax + SOCKET.lock] |
||
645 | call wait_mutex |
||
646 | |||
647 | mov ecx, [eax + SOCKET.rxDataCount] ; get count of bytes |
||
648 | DEBUGF 1,"bytes in socket:%u\n", ecx |
||
649 | test ecx, ecx ; if count of bytes is zero.. |
||
650 | jz .exit ; exit function (eax will be zero) |
||
651 | |||
652 | cmp ecx, esi ; if buffer size is larger then the bytes of data, copy all data |
||
653 | jle .copy_all_bytes |
||
654 | |||
655 | sub ecx, esi ; store new count (data bytes in buffer - bytes we're about to copy) |
||
656 | mov [eax + SOCKET.rxDataCount], ecx ; |
||
657 | push ecx |
||
658 | mov edx, esi |
||
659 | |||
660 | call .start_copy ; copy to the application |
||
661 | |||
662 | mov dword[esp+32], edx |
||
663 | |||
664 | lea edi, [eax + SOCKET.rxData] ; Now shift the remaining bytes to start of buffer |
||
665 | lea esi, [edi + edx] |
||
666 | mov ecx, [esp] |
||
667 | shr ecx, 2 ; divide eax by 4 |
||
668 | rep movsd ; copy all full dwords |
||
669 | pop ecx |
||
670 | and ecx, 3 |
||
671 | rep movsb ; copy remaining bytes |
||
672 | |||
673 | .exit: |
||
674 | mov [eax + SOCKET.lock], 0 |
||
675 | ret |
||
676 | |||
677 | .copy_all_bytes: |
||
678 | mov dword[esp+32], ecx |
||
679 | mov [eax + SOCKET.rxDataCount], 0 ; store new count (zero) |
||
680 | push dword .exit ; this code results in same as commented out code |
||
681 | |||
682 | .start_copy: |
||
683 | DEBUGF 1,"copying %u bytes\n",ecx |
||
684 | |||
685 | lea esi, [eax + SOCKET.rxData] |
||
686 | push ecx |
||
687 | shr ecx, 2 ; divide eax by 4 |
||
688 | rep movsd |
||
689 | pop ecx |
||
690 | and ecx, 3 |
||
691 | rep movsb ; copy the rest bytes |
||
692 | |||
693 | ret ; exit, or go back to shift remaining bytes if any |
||
694 | |||
695 | |||
696 | |||
697 | ;----------------------------------------------- |
||
698 | ; |
||
699 | ; SOCKET_send |
||
700 | ; |
||
701 | ; |
||
702 | ; IN: socket number in ecx |
||
703 | ; addr in edx |
||
704 | ; addrlen in esi |
||
705 | ; flags in edi |
||
706 | ; OUT: -1 on error |
||
707 | ; |
||
708 | ;----------------------------------------------- |
||
709 | |||
710 | socket_send: |
||
711 | |||
712 | DEBUGF 1,"Socket_send: socknum: %u sockaddr: %x, length: %u, flags: %x, ",ecx,edx,esi,edi |
||
713 | |||
714 | stdcall net_socket_num_to_addr, ecx ; get real socket address |
||
715 | or eax, eax |
||
1185 | hidnplayr | 716 | jz s_error |
1159 | hidnplayr | 717 | |
718 | DEBUGF 1,"Socket type:%u\n", [eax + SOCKET.Type]:4 |
||
719 | |||
720 | cmp [eax + SOCKET.Type], IP_PROTO_UDP |
||
721 | je .udp |
||
722 | |||
723 | cmp [eax + SOCKET.Type], IP_PROTO_ICMP |
||
724 | je .icmp |
||
725 | |||
726 | ; cmp [eax + SOCKET.Type], IP_PROTO_TCP |
||
727 | ; je .tcp |
||
728 | |||
1185 | hidnplayr | 729 | jmp s_error |
1159 | hidnplayr | 730 | |
731 | .udp: |
||
732 | |||
733 | DEBUGF 1,"type: UDP\n" |
||
734 | |||
735 | mov ecx, esi |
||
736 | mov esi, edx |
||
737 | mov edx, dword [eax + SOCKET.LocalPort] ; load local port and remote port at once |
||
738 | |||
739 | DEBUGF 1,"local port: %u, remote port:%u\n",[eax + SOCKET.LocalPort]:2, [eax + SOCKET.RemotePort]:2 |
||
740 | mov ebx, [eax + SOCKET.LocalIP] |
||
741 | mov eax, [eax + SOCKET.RemoteIP] |
||
742 | |||
743 | call UDP_create_Packet |
||
744 | |||
745 | mov [esp+32], eax |
||
746 | ret |
||
747 | |||
748 | .icmp: |
||
749 | ; note: for ICMP sockets the SOCKET.LocalPort is used as the 'Identifier' value for ICMP packets |
||
750 | ; the application must add the header to the data, the kernel will fill in 'identifier' and 'checksum' |
||
751 | |||
752 | sub ecx, ICMP_Packet.Data |
||
753 | mov esi, edx |
||
754 | push ax |
||
755 | call IPv4_get_frgmnt_num |
||
756 | mov dx, ax |
||
757 | pop ax |
||
758 | shl edx, 16 |
||
759 | mov dh , [esi + ICMP_Packet.Type] |
||
760 | mov dl , [esi + ICMP_Packet.Code] |
||
761 | mov di , [esi + ICMP_Packet.Identifier] |
||
762 | ; mov [eax + SOCKET.LocalPort], di ; Set localport to the identifier number, so we can receive reply's |
||
763 | shl edi, 16 |
||
764 | mov di , [esi + ICMP_Packet.SequenceNumber] |
||
765 | add esi, ICMP_Packet.Data |
||
766 | mov ebx, [eax + SOCKET.LocalIP] |
||
767 | mov eax, [eax + SOCKET.RemoteIP] |
||
768 | call ICMP_create_Packet |
||
769 | |||
770 | mov [esp+32], eax |
||
771 | ret |
||
772 | |||
773 | .tcp: |
||
774 | |||
775 | ret |
||
776 | |||
777 | |||
778 | |||
779 | |||
780 | |||
781 | |||
782 | |||
783 | |||
784 | ; Allocate memory for socket data and put new socket into the list |
||
785 | ; Newly created socket is initialized with calling PID and number and |
||
786 | ; put into beginning of list (which is a fastest way). |
||
787 | ; |
||
788 | ; @return socket structure address in EAX |
||
789 | ; |
||
790 | proc net_socket_alloc stdcall uses ebx ecx edx edi |
||
791 | stdcall kernel_alloc, SOCKETBUFFSIZE |
||
792 | DEBUGF 1, "K : net_socket_alloc (0x%x)\n", eax |
||
793 | ; check if we can allocate needed amount of memory |
||
794 | or eax, eax |
||
795 | jz .exit |
||
796 | |||
797 | ; zero-initialize allocated memory |
||
798 | push eax |
||
799 | mov edi, eax |
||
800 | mov ecx, SOCKETBUFFSIZE / 4 |
||
801 | ; cld |
||
802 | xor eax, eax |
||
803 | rep stosd |
||
804 | pop eax |
||
805 | |||
806 | ; add socket to the list by changing pointers |
||
807 | mov ebx, net_sockets |
||
808 | push [ebx + SOCKET.NextPtr] |
||
809 | mov [ebx + SOCKET.NextPtr], eax |
||
810 | mov [eax + SOCKET.PrevPtr], ebx |
||
811 | pop ebx |
||
812 | mov [eax + SOCKET.NextPtr], ebx |
||
813 | or ebx, ebx |
||
814 | jz @f |
||
815 | mov [ebx + SOCKET.PrevPtr], eax |
||
816 | |||
817 | @@: ; set socket owner PID to the one of calling process |
||
818 | mov ebx, [TASK_BASE] |
||
819 | mov ebx, [ebx + TASKDATA.pid] |
||
820 | mov [eax + SOCKET.PID], ebx |
||
821 | |||
822 | ; find first free socket number and use it |
||
823 | ;mov edx, ebx |
||
824 | mov ebx, net_sockets |
||
825 | xor ecx, ecx |
||
826 | .next_socket_number: |
||
827 | inc ecx |
||
828 | .next_socket: |
||
829 | mov ebx, [ebx + SOCKET.NextPtr] |
||
830 | or ebx, ebx |
||
831 | jz .last_socket_number |
||
832 | cmp [ebx + SOCKET.Number], ecx |
||
833 | jne .next_socket |
||
834 | ;cmp [ebx + SOCKET.PID], edx |
||
835 | ;jne .next_socket |
||
836 | mov ebx, net_sockets |
||
837 | jmp .next_socket_number |
||
838 | |||
839 | .last_socket_number: |
||
840 | mov [eax + SOCKET.Number], ecx |
||
841 | |||
842 | .exit: |
||
843 | ret |
||
844 | endp |
||
845 | |||
846 | ; Free socket data memory and pop socket off the list |
||
847 | ; |
||
848 | ; @param sockAddr is a socket structure address |
||
849 | ; |
||
850 | proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD |
||
851 | mov eax, [sockAddr] |
||
852 | DEBUGF 1, "K : net_socket_free (0x%x)\n", eax |
||
853 | ; check if we got something similar to socket structure address |
||
854 | or eax, eax |
||
855 | jz .error |
||
856 | |||
857 | ; make sure sockAddr is one of the socket addresses in the list |
||
858 | mov ebx, net_sockets |
||
859 | ;mov ecx, [TASK_BASE] |
||
860 | ;mov ecx, [ecx + TASKDATA.pid] |
||
861 | .next_socket: |
||
862 | mov ebx, [ebx + SOCKET.NextPtr] |
||
863 | or ebx, ebx |
||
864 | jz .error |
||
865 | cmp ebx, eax |
||
866 | jne .next_socket |
||
867 | ;cmp [ebx + SOCKET.PID], ecx |
||
868 | ;jne .next_socket |
||
869 | |||
870 | ; okay, we found the correct one |
||
871 | ; remove it from the list first, changing pointers |
||
872 | mov ebx, [eax + SOCKET.NextPtr] |
||
873 | mov eax, [eax + SOCKET.PrevPtr] |
||
874 | mov [eax + SOCKET.NextPtr], ebx |
||
875 | or ebx, ebx |
||
876 | jz @f |
||
877 | mov [ebx + SOCKET.PrevPtr], eax |
||
878 | |||
879 | @@: ; and finally free the memory structure used |
||
880 | stdcall kernel_free, [sockAddr] |
||
881 | ret |
||
882 | |||
883 | .error: |
||
884 | DEBUGF 1, "K : failed\n" |
||
885 | ret |
||
886 | endp |
||
887 | |||
888 | ; Get socket structure address by its number |
||
889 | ; Scan through sockets list to find the socket with specified number. |
||
890 | ; This proc uses SOCKET.PID indirectly to check if socket is owned by |
||
891 | ; calling process. |
||
892 | ; |
||
893 | ; @param sockNum is a socket number |
||
894 | ; @return socket structure address or 0 (not found) in EAX |
||
895 | ; |
||
896 | proc net_socket_num_to_addr stdcall uses ebx ecx, sockNum:DWORD |
||
897 | mov eax, [sockNum] |
||
898 | ; check if we got something similar to socket number |
||
899 | or eax, eax |
||
900 | jz .error |
||
901 | |||
902 | ; scan through sockets list |
||
903 | mov ebx, net_sockets |
||
904 | ;mov ecx, [TASK_BASE] |
||
905 | ;mov ecx, [ecx + TASKDATA.pid] |
||
906 | .next_socket: |
||
907 | mov ebx, [ebx + SOCKET.NextPtr] |
||
908 | or ebx, ebx |
||
909 | jz .error |
||
910 | cmp [ebx + SOCKET.Number], eax |
||
911 | jne .next_socket |
||
912 | ;cmp [ebx + SOCKET.PID], ecx |
||
913 | ;jne .next_socket |
||
914 | |||
915 | ; okay, we found the correct one |
||
916 | mov eax, ebx |
||
917 | ret |
||
918 | |||
919 | .error: |
||
920 | xor eax, eax |
||
921 | ret |
||
922 | endp |
||
923 | |||
924 | ; Get socket number by its structure address |
||
925 | ; Scan through sockets list to find the socket with specified address. |
||
926 | ; This proc uses SOCKET.PID indirectly to check if socket is owned by |
||
927 | ; calling process. |
||
928 | ; |
||
929 | ; @param sockAddr is a socket structure address |
||
930 | ; @return socket number (SOCKET.Number) or 0 (not found) in EAX |
||
931 | ; |
||
932 | proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD |
||
933 | mov eax, [sockAddr] |
||
934 | ; check if we got something similar to socket structure address |
||
935 | or eax, eax |
||
936 | jz .error |
||
937 | |||
938 | ; scan through sockets list |
||
939 | mov ebx, net_sockets |
||
940 | ;mov ecx, [TASK_BASE] |
||
941 | ;mov ecx, [ecx + TASKDATA.pid] |
||
942 | .next_socket: |
||
943 | mov ebx, [ebx + SOCKET.NextPtr] |
||
944 | or ebx, ebx |
||
945 | jz .error |
||
946 | cmp ebx, eax |
||
947 | jne .next_socket |
||
948 | ;cmp [ebx + SOCKET.PID], ecx |
||
949 | ;jne .next_socket |
||
950 | |||
951 | ; okay, we found the correct one |
||
952 | mov eax, [ebx + SOCKET.Number] |
||
953 | ret |
||
954 | |||
955 | .error: |
||
956 | xor eax, eax |
||
957 | ret |
||
958 | endp |