Subversion Repositories Kolibri OS

Rev

Rev 1208 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  SOCKET.INC                                                     ;;
  7. ;;                                                                 ;;
  8. ;;    Written by hidnplayr@kolibrios.org                           ;;
  9. ;;    based on code by mike.dld                                    ;;
  10. ;;                                                                 ;;
  11. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  12. ;;             Version 2, June 1991                                ;;
  13. ;;                                                                 ;;
  14. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  15.  
  16. $Revision: 1249 $
  17.  
  18. struct  SOCKET_head
  19.          .PrevPtr               dd ? ; pointer to previous socket in list
  20.          .NextPtr               dd ? ; pointer to next socket in list
  21.          .Number                dd ? ; socket number (unique within single process)
  22.          .PID                   dd ? ; application process id
  23.          .Domain                dd ? ; INET/UNIX/..
  24.          .Type                  dd ? ; RAW/UDP/TCP/...
  25.          .Protocol              dd ? ; ICMP/IPv4/ARP/
  26.          .lock                  dd ? ; lock mutex
  27.          .end:
  28. ends
  29.  
  30. struct  IPv4_SOCKET
  31.          .LocalIP               dd ?
  32.          .RemoteIP              dd ?
  33.          .SequenceNumber        dd ?
  34.  
  35.         ; todo: add options (for func 8 and 9)
  36.  
  37.          .end:
  38. ends
  39.  
  40. struct  TCP_SOCKET
  41.  
  42.          .LocalPort             dw ? ; In INET byte order
  43.          .RemotePort            dw ? ; In INET byte order
  44.  
  45.          .backlog               dw ? ; Backlog
  46.          .OrigRemoteIP          dd ? ; original remote IP address (used to reset to LISTEN state)
  47.          .OrigRemotePort        dw ? ; original remote port (used to reset to LISTEN state)
  48.          .TCBState              dd ? ; TCB state
  49.          .TCBTimer              dd ? ; TCB timer (seconds)
  50.          .ISS                   dd ? ; initial send sequence
  51.          .IRS                   dd ? ; initial receive sequence
  52.          .SND_UNA               dd ? ; sequence number of unack'ed sent Packets
  53.          .SND_NXT               dd ? ; next send sequence number to use
  54.          .SND_WND               dd ? ; send window
  55.          .RCV_NXT               dd ? ; next receive sequence number to use
  56.          .RCV_WND               dd ? ; receive window
  57.          .SEG_LEN               dd ? ; segment length
  58.          .SEG_WND               dd ? ; segment window
  59.          .wndsizeTimer          dd ? ; window size timer
  60.  
  61.          .flags                 db ? ; packet flags
  62.  
  63.          .end:
  64. ends
  65.  
  66. struct  UDP_SOCKET
  67.  
  68.          .LocalPort             dw ? ; In INET byte order
  69.          .RemotePort            dw ? ; In INET byte order
  70.  
  71.          .end:
  72. ends
  73.  
  74. struct  ICMP_SOCKET
  75.  
  76.         .Identifier             dw ? ;
  77.  
  78.         .end:
  79.  
  80. ends
  81.  
  82. struct  IPC_SOCKET
  83.  
  84.         .ConnectedTo            dd ? ; Socket number of other socket this one is connected to
  85.  
  86.         .end:
  87.  
  88. ends
  89.  
  90. MAX_backlog             equ 20       ; backlog for stream sockets
  91. SOCKETBUFFSIZE          equ 4096     ; in bytes
  92. SOCKET_QUEUE_SIZE       equ 10       ; maximum number ofincoming packets queued for 1 socket
  93.  
  94. uglobal
  95.         net_sockets     rd 2
  96.         last_UDP_port   dw ? ; These values give the number of the last used ephemeral port
  97.         last_TCP_port   dw ? ;
  98. endg
  99.  
  100.  
  101. ;-----------------------------------------------
  102. ;
  103. ; SOCKET_init
  104. ;
  105. ;  -
  106. ;
  107. ;  IN:  /
  108. ;  OUT: /
  109. ;
  110. ;-----------------------------------------------
  111.  
  112. align 4
  113. socket_init:
  114.  
  115.         mov     [net_sockets], 0
  116.         mov     [net_sockets + 4], 0
  117.  
  118.         mov     [last_UDP_port], MIN_EPHEMERAL_PORT
  119.         mov     [last_TCP_port], MIN_EPHEMERAL_PORT
  120.  
  121.         ret
  122.  
  123.  
  124. ;-----------------------------------------------------------------------------
  125. ;
  126. ; Socket API (function 74)
  127. ;
  128. ;-----------------------------------------------------------------------------
  129.  
  130. align 4
  131. sys_socket:
  132.  
  133.         test    bl, bl
  134.         jz      socket_open     ; 0
  135.         dec     bl
  136.         jz      socket_close    ; 1
  137.         dec     bl
  138.         jz      socket_bind     ; 2
  139.         dec     bl
  140.         jz      socket_listen   ; 3
  141.         dec     bl
  142.         jz      socket_connect  ; 4
  143.         dec     bl
  144.         jz      socket_accept   ; 5
  145.         dec     bl
  146.         jz      socket_send     ; 6
  147.         dec     bl
  148.         jz      socket_recv     ; 7
  149.         dec     bl
  150. ;        jz      socket_get_opt  ; 8
  151.         dec     bl
  152. ;        jz      socket_set_opt  ; 9
  153.  
  154. s_error:
  155.         mov     dword [esp+32],-1
  156.  
  157.         ret
  158.  
  159.  
  160.  
  161.  
  162. ;-----------------------------------------------
  163. ;
  164. ; SOCKET_open
  165. ;
  166. ;
  167. ;  IN:  domain in ecx
  168. ;       type in edx
  169. ;       protocol in esi
  170. ;  OUT: eax is socket num, -1 on error
  171. ;
  172. ;-----------------------------------------------
  173. align 4
  174. socket_open:
  175.  
  176.         DEBUGF  1,"socket_open: domain: %u, type: %u",ecx, edx
  177.  
  178.         call    net_socket_alloc
  179.         or      eax, eax
  180.         jz      s_error
  181.  
  182.         mov     [eax + SOCKET_head.Domain], ecx
  183.         mov     [eax + SOCKET_head.Type], edx
  184.         mov     [eax + SOCKET_head.Protocol], esi
  185.  
  186.         stdcall net_socket_addr_to_num, eax
  187.         DEBUGF  1,", socketnumber: %u\n", eax
  188.  
  189.         mov     [esp+32], eax
  190.  
  191.         ret
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200. ;-----------------------------------------------
  201. ;
  202. ; SOCKET_bind
  203. ;
  204. ;  IN:  socket number in ecx
  205. ;       pointer to sockaddr struct in edx
  206. ;       length of that struct in esi
  207. ;  OUT: 0 on success
  208. ;
  209. ;-----------------------------------------------
  210. align 4
  211. socket_bind:
  212.  
  213.         DEBUGF  1,"Socket_bind: socknum: %u sockaddr: %x, length: %u, ",ecx,edx,esi
  214.  
  215.         stdcall net_socket_num_to_addr, ecx
  216.         cmp     eax, -1
  217.         jz      s_error
  218.  
  219.         cmp     esi, 2
  220.         jl      s_error
  221.  
  222.         cmp     word [edx], AF_INET4
  223.         je      .af_inet4
  224.  
  225.         cmp     word [edx], AF_UNIX
  226.         je      .af_unix
  227.  
  228.         jmp     s_error
  229.  
  230.   .af_unix:
  231.  
  232.         ; TODO: write code here
  233.  
  234.  
  235.         mov     dword [esp+32],0
  236.         ret
  237.  
  238.   .af_inet4:
  239.  
  240.         cmp     esi, 6
  241.         jl      s_error
  242.  
  243.         mov     ecx, [eax + SOCKET_head.Type]
  244.  
  245.         mov     bx, word [edx + 2]
  246.         DEBUGF  1,"local port: %x ",bx
  247.         test    bx, bx
  248.         jz      .find_free
  249.  
  250.         call    socket_check_port
  251.         test    bx, bx
  252.         je      s_error
  253.         jmp     .got_port
  254.  
  255.     .find_free:
  256.  
  257.         call    socket_find_port
  258.         test    bx, bx
  259.         je      s_error
  260.  
  261.     .got_port:
  262.         DEBUGF  1,"using port: %x ",bx
  263.         mov     word [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
  264.  
  265.         mov     ebx, dword [edx + 4]
  266.         mov     dword [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP], ebx
  267.  
  268.         DEBUGF  1,"local ip: %u.%u.%u.%u\n",\
  269.         [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 0]:1,[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 1]:1,\
  270.         [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 2]:1,[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 3]:1
  271.  
  272.         mov     dword [esp+32],0
  273.         ret
  274.  
  275.  
  276.  
  277.  
  278. ;-----------------------------------------------
  279. ;
  280. ; SOCKET_connect
  281. ;
  282. ;
  283. ;  IN:  socket number in ecx
  284. ;       pointer to sockaddr struct in edx
  285. ;       length of that struct in esi
  286. ;  OUT: 0 on success
  287. ;
  288. ;-----------------------------------------------
  289. align 4
  290. socket_connect:
  291.  
  292.         DEBUGF  1,"Socket_connect: socknum: %u sockaddr: %x, length: %u,",ecx,edx,esi
  293.  
  294.         stdcall net_socket_num_to_addr, ecx
  295.         cmp     eax, -1
  296.         jz      s_error
  297.  
  298.         cmp     esi, 2
  299.         jl      s_error
  300.  
  301.         cmp     word [edx], AF_INET4
  302.         je      .af_inet4
  303.  
  304.         jmp     s_error
  305.  
  306.   .af_inet4:
  307.  
  308.         cmp     esi, 8
  309.         jl      s_error
  310.  
  311.         cmp     [eax + SOCKET_head.Type], IP_PROTO_UDP
  312.         je      .udp
  313.  
  314.         cmp     [eax + SOCKET_head.Type], IP_PROTO_ICMP
  315.         je      .icmp
  316.  
  317.         cmp     [eax + SOCKET_head.Type], IP_PROTO_TCP
  318.         je      .tcp
  319.  
  320.         jmp     s_error
  321.  
  322.     .udp:
  323.  
  324.         mov     bx , word [edx + 2]
  325.         mov     word [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx
  326.         DEBUGF  1,"remote port: %x ",bx
  327.  
  328.         mov     ebx, dword [edx + 4]
  329.         mov     dword [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], ebx
  330.         DEBUGF  1,"remote ip: %u.%u.%u.%u\n",[edx+4]:1,[edx+5]:1,[edx+6]:1,[edx+7]:1
  331.  
  332.         mov     dword [esp+32],0
  333.         ret
  334.  
  335.     .icmp:
  336.  
  337.         ; TODO: write code here
  338.  
  339.         ret
  340.  
  341.  
  342.  
  343.   .tcp:
  344.  
  345. ;local sockAddr dd ?
  346.  
  347. ;        cmp     esi, SOCKET_PASSIVE
  348. ;        jne     .skip_port_check
  349. ;
  350. ;        push    ebx
  351. ;        mov     eax, ebx
  352. ;        xchg    al, ah
  353. ;        mov     ebx, net_sockets
  354. ;
  355. ;  .next_socket:
  356. ;        mov     ebx, [ebx + SOCKET.NextPtr]
  357. ;        or      ebx, ebx
  358. ;        jz      .last_socket
  359. ;        cmp     [ebx + SOCKET.TCBState], TCB_LISTEN
  360. ;        jne     .next_socket
  361. ;        cmp     [ebx + SOCKET.LocalPort], ax
  362. ;        jne     .next_socket
  363. ;
  364. ;        xchg    al, ah
  365. ;        DEBUGF  1, "K : error: port %u is listened by 0x%x\n", ax, ebx
  366. ;        pop     ebx
  367. ;        jmp     .error
  368. ;
  369. ;  .last_socket:
  370. ;        pop     ebx
  371. ;
  372. ;  .skip_port_check:
  373.  
  374. ;        mov     [eax + SOCKET.wndsizeTimer], 0     ; Reset the window timer.
  375. ;
  376. ;        xchg    bh, bl
  377. ;        mov     [eax + SOCKET.LocalPort], bx
  378. ;        xchg    ch, cl
  379. ;        mov     [eax + SOCKET.RemotePort], cx
  380. ;        mov     [eax + SOCKET.OrigRemotePort], cx
  381. ;        mov     ebx, [IP_LIST]
  382. ;        mov     [eax + SOCKET.LocalIP], ebx
  383. ;        mov     [eax + SOCKET.RemoteIP], edx
  384. ;        mov     [eax + SOCKET.OrigRemoteIP], edx
  385.  
  386. ;        mov     ebx, TCB_LISTEN
  387. ;        cmp     esi, SOCKET_PASSIVE
  388. ;        je      @f
  389. ;        mov     ebx, TCB_SYN_SENT
  390. ;    @@: mov     [eax + SOCKET.TCBState], ebx            ; Indicate the state of the TCB
  391.  
  392. ;        cmp     ebx, TCB_LISTEN
  393. ;        je      .exit
  394.  
  395.         ; Now, if we are in active mode, then we have to send a SYN to the specified remote port
  396. ;        mov     eax, EMPTY_QUEUE
  397. ;        call    dequeue
  398. ;        cmp     ax, NO_BUFFER
  399. ;        je      .exit
  400.  
  401. ;        push    eax
  402.  
  403. ;        mov     bl, TH_SYN
  404. ;        xor     ecx, ecx
  405. ;        stdcall build_tcp_Packet, [sockAddr]
  406.  
  407. ;        mov     eax, NET1OUT_QUEUE
  408. ;        mov     edx, [IP_LIST]
  409. ;        mov     ecx, [sockAddr]
  410. ;        cmp     edx, [ecx + SOCKET.RemoteIP]
  411. ;        jne     .not_local
  412. ;        mov     eax, IPIN_QUEUE
  413.  
  414. ;  .not_local:
  415.         ; Send it.
  416. ;        pop     ebx
  417. ;        call    queue
  418.  
  419.   .exit:
  420.         xor     eax, eax
  421.         ret
  422.  
  423.  
  424.  
  425.  
  426. ;-----------------------------------------------
  427. ;
  428. ; SOCKET_listen
  429. ;
  430. ;
  431. ;  IN:  socket number in ecx
  432. ;       backlog in edx
  433. ;  OUT: eax is socket num, -1 on error
  434. ;
  435. ;-----------------------------------------------
  436. align 4
  437. socket_listen:
  438.  
  439.         DEBUGF  1,"Socket_listen: socknum: %u backlog: %u\n",ecx,edx
  440.  
  441.         stdcall net_socket_num_to_addr, ecx
  442.         cmp     eax, -1
  443.         jz      s_error
  444.  
  445.         cmp     edx, MAX_backlog
  446.         jl      .ok
  447.         mov     dx , 20
  448.   .ok:
  449.  
  450.         mov     [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], dx
  451.  
  452.         ; TODO: insert code for active connections like TCP
  453.  
  454.         mov     dword [esp+32], 0
  455.         ret
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462. ;-----------------------------------------------
  463. ;
  464. ; SOCKET_accept
  465. ;
  466. ;
  467. ;  IN:  socket number in ecx
  468. ;       addr in edx
  469. ;       addrlen in esi
  470. ;  OUT: eax is socket num, -1 on error
  471. ;
  472. ;-----------------------------------------------
  473. align 4
  474. socket_accept:
  475.  
  476.         DEBUGF  1,"Socket_accept: socknum: %u sockaddr: %x, length: %u\n",ecx,edx,esi
  477.  
  478.         stdcall net_socket_num_to_addr, ecx
  479.         or      eax, eax
  480.         jz      s_error
  481.         mov     esi, eax
  482.  
  483.         cmp     word [esi + SOCKET_head.Domain], AF_INET4
  484.         je      .af_inet4
  485.  
  486.         jmp     s_error
  487.  
  488.   .af_inet4:
  489.  
  490.         cmp     [esi + SOCKET_head.Type], IP_PROTO_TCP
  491.         je      .tcp
  492.  
  493.         jmp     s_error
  494.  
  495.   .tcp:
  496.  
  497.         cmp     [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], 0
  498.         jz      s_error
  499.  
  500.         call    net_socket_alloc
  501.         or      eax, eax
  502.         jz      s_error
  503.         mov     edi, eax
  504.  
  505.         dec     [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog]
  506.  
  507.         mov     ecx, (SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.end+3)/4
  508.         push    esi edi
  509.         rep     movsd
  510.         pop     edi esi
  511.  
  512.         mov     [edi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], 0
  513.  
  514.         ; TODO: fill in structure in ecx
  515.  
  516.         mov     [esi + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 0
  517.         mov     [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], 0
  518.  
  519.         stdcall net_socket_addr_to_num, edi
  520.         mov     [esp+32], eax
  521.  
  522.         ret
  523.  
  524.  
  525.  
  526. ;-----------------------------------------------
  527. ;
  528. ; SOCKET_close
  529. ;
  530. ;
  531. ;  IN:  socket number in ecx
  532. ;  OUT: eax is socket num, -1 on error
  533. ;
  534. ;-----------------------------------------------
  535. align 4
  536. socket_close:
  537.  
  538.         DEBUGF  1,"Socket_close: socknum: %u\n",ecx
  539.  
  540.         stdcall net_socket_num_to_addr, ecx
  541.         or      eax, eax
  542.         jz      s_error
  543.  
  544.         cmp     [eax + SOCKET_head.Domain], AF_INET4
  545.         jne     s_error
  546.  
  547.         cmp     [eax + SOCKET_head.Type], IP_PROTO_UDP
  548.         je      .udp
  549.  
  550.         cmp     [eax + SOCKET_head.Type], IP_PROTO_ICMP
  551.         je      .icmp
  552.  
  553.         cmp     [eax + SOCKET_head.Type], IP_PROTO_TCP
  554.         je      .tcp
  555.  
  556.         jmp     s_error
  557.  
  558.   .udp:
  559.  
  560.         stdcall net_socket_free, eax
  561.         mov     dword [esp+32],0
  562.         ret
  563.  
  564.  
  565.   .icmp:
  566.  
  567.  
  568.  
  569.         ret
  570.  
  571.   .tcp:
  572.  
  573. if 1 = 0
  574. ;local sockAddr dd ?
  575.  
  576. ;        DEBUGF  1, "K : socket_close_tcp (0x%x)\n", ebx
  577.         ; first, remove any resend entries
  578.         pusha
  579.  
  580.         mov     esi, resendQ
  581.         mov     ecx, 0
  582.  
  583.   .next_resendq:
  584.         cmp     ecx, NUMRESENDENTRIES
  585.         je      .last_resendq       ; None left
  586.         cmp     [esi + 4], ebx
  587.         je      @f                  ; found one
  588.         inc     ecx
  589.         add     esi, 8
  590.         jmp     .next_resendq
  591.  
  592.     @@: mov     dword[esi + 4], 0
  593.         inc     ecx
  594.         add     esi, 8
  595.         jmp     .next_resendq
  596.  
  597.   .last_resendq:
  598.         popa
  599.  
  600.         mov     ebx, eax
  601. ;        mov     [sockAddr], eax
  602.  
  603.         cmp     [eax + SOCKET.TCBState], TCB_LISTEN
  604.         je      .destroy_tcb
  605.         cmp     [eax + SOCKET.TCBState], TCB_SYN_SENT
  606.         je      .destroy_tcb
  607.  
  608. ; Now construct the response, and queue for sending by IP
  609.         mov     eax, EMPTY_QUEUE
  610.         call    dequeue
  611.         cmp     ax, NO_BUFFER
  612.         je      .error
  613.  
  614.         push    eax
  615.  
  616.         mov     bl, TH_FIN
  617.         xor     ecx, ecx
  618.         xor     esi, esi
  619.         stdcall build_tcp_Packet, [sockAddr]
  620.  
  621.         mov      ebx, [sockAddr]
  622.         ; increament SND.NXT in socket
  623.         lea     esi, [ebx + SOCKET.SND_NXT]
  624.         call    inc_inet_esi
  625.  
  626.         ; Get the socket state
  627.         mov     eax, [ebx + SOCKET.TCBState]
  628.         cmp     eax, TCB_SYN_RECEIVED
  629.         je      .fin_wait_1
  630.         cmp     eax, TCB_ESTABLISHED
  631.         je      .fin_wait_1
  632.  
  633.         ; assume CLOSE WAIT
  634.         ; Send a fin, then enter last-ack state
  635.         mov     [ebx + SOCKET.TCBState], TCB_LAST_ACK
  636.         jmp     .send
  637.  
  638.   .fin_wait_1:
  639.         ; Send a fin, then enter finwait2 state
  640.         mov     [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1
  641.  
  642.   .send:
  643.         mov     eax, NET1OUT_QUEUE
  644.         mov     edx, [IP_LIST]
  645. ;        mov     ecx, [sockAddr]
  646.         cmp     edx, [ecx + SOCKET.RemoteIP]
  647.         jne     .not_local
  648.         mov     eax, IPIN_QUEUE
  649.  
  650.   .not_local:
  651.         ; Send it.
  652.         pop     ebx
  653.         call    queue
  654.         jmp     .exit
  655.  
  656.  
  657.   .destroy_tcb:
  658.  
  659.         stdcall net_socket_free, eax
  660.  
  661. end if
  662.  
  663.   .exit:
  664.         mov     dword [esp+32],0
  665.         ret
  666.  
  667.  
  668.  
  669.  
  670. ;-----------------------------------------------
  671. ;
  672. ; SOCKET_receive
  673. ;
  674. ;
  675. ;  IN:  socket number in ecx
  676. ;       addr to buffer in edx
  677. ;       length of buffer in esi
  678. ;       flags in edi
  679. ;  OUT: eax is number of bytes copied, -1 on error
  680. ;
  681. ;-----------------------------------------------
  682. align 4
  683. socket_recv:
  684.  
  685.         DEBUGF  1,"Socket_receive: socknum: %u bufferaddress: %x, length: %u, flags: %x\n",ecx,edx,esi,edi
  686.  
  687.         stdcall net_socket_num_to_addr, ecx                ; get real socket address
  688.         or      eax, eax
  689.         jz      s_error
  690.  
  691.         DEBUGF  1,"Socket pointer: %x\n", eax
  692.  
  693.         get_from_queue (eax + 2048), SOCKET_QUEUE_SIZE, 4*3, s_error
  694.  
  695.         mov     edi, edx
  696.         mov     ecx, [esi + socket_queue_entry.data_size]
  697.  
  698.         DEBUGF  1,"Got %u bytes of data\n", ecx
  699.  
  700.         cmp     ecx, edx
  701.         jle     .large_enough
  702.         DEBUGF  1,"Buffer too small...\n"
  703.         jmp     s_error
  704.   .large_enough:
  705.  
  706.         push    [esi + socket_queue_entry.data_ptr]
  707.         mov     esi, [esi + socket_queue_entry.offset]
  708.         add     esi, [esp]
  709.         DEBUGF  1,"Source buffer: %x, real addr: %x\n", [esp], esi
  710.  
  711.         mov     dword[esp+32+4], ecx                         ; return number of bytes copied
  712.  
  713.         shr     ecx, 1
  714.         jnc     .nb
  715.         movsb
  716. .nb:    shr     ecx, 1
  717.         jnc     .nw
  718.         movsw
  719. .nw:    rep     movsd
  720.  
  721.         call    kernel_free
  722.  
  723.         ret
  724.  
  725.  
  726. ;-----------------------------------------------
  727. ;
  728. ; SOCKET_send
  729. ;
  730. ;
  731. ;  IN:  socket number in ecx
  732. ;       pointer to data in edx
  733. ;       datalength in esi
  734. ;       flags in edi
  735. ;  OUT: -1 on error
  736. ;
  737. ;-----------------------------------------------
  738. align 4
  739. socket_send:
  740.  
  741.         DEBUGF  1,"Socket_send: socknum: %u sockaddr: %x, length: %u, flags: %x, ",ecx,edx,esi,edi
  742.  
  743.         stdcall net_socket_num_to_addr, ecx                ; get real socket address
  744.         or      eax, eax
  745.         jz      s_error
  746.  
  747.         cmp     word [eax + SOCKET_head.Domain], AF_INET4
  748.         je      .af_inet4
  749.  
  750.         jmp     s_error
  751.  
  752. ;---------
  753.   .af_inet4:
  754.         DEBUGF  1,"Socket type:%u\n", [eax + SOCKET_head.Type]:4
  755.  
  756.         cmp     [eax + SOCKET_head.Type], IP_PROTO_TCP
  757.         je      .tcp
  758.  
  759.         cmp     [eax + SOCKET_head.Type], IP_PROTO_UDP
  760.         je      .udp
  761.  
  762.         cmp     [eax + SOCKET_head.Type], SOCK_RAW
  763.         je      .raw
  764.  
  765.         jmp     s_error
  766. ;--------
  767.  
  768.   .udp:
  769.  
  770.         DEBUGF  1,"type: UDP, "
  771.  
  772.         cmp     [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort],0
  773.         jne     @f
  774.  
  775.         push    esi
  776.         mov     ecx, [eax + SOCKET_head.Type]
  777.         call    socket_find_port
  778.         test    bx, bx
  779.         pop     esi
  780.         je      s_error
  781.         mov     [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
  782.  
  783.      @@:
  784.  
  785.         mov     ecx, esi
  786.         mov     esi, edx
  787.  
  788.         call    UDP_socket_send
  789.  
  790.         mov     [esp+32], eax
  791.         ret
  792.  
  793.   .tcp:
  794.  
  795.         mov     [esp+32], eax
  796.         ret
  797.  
  798. ;--------
  799.   .raw:
  800.         cmp     [eax + SOCKET_head.Protocol], IP_PROTO_IP
  801.         je      .raw_ip
  802.  
  803.         cmp     [eax + SOCKET_head.Protocol], IP_PROTO_ICMP
  804.         je      .raw_icmp
  805.  
  806.         jmp     s_error
  807. ;--------
  808.  
  809.  
  810.   .raw_ip:
  811.  
  812.         mov     [esp+32], eax
  813.         ret
  814.  
  815.  
  816.   .raw_icmp:
  817.  
  818. ;        sub     ecx, ICMP_Packet.Data
  819. ;        mov     esi, edx
  820. ;        push    ax
  821. ;        call    IPv4_get_frgmnt_num
  822. ;        mov     dx, ax
  823. ;        pop     ax
  824. ;        shl     edx, 16
  825. ;        mov     dh , [esi + ICMP_Packet.Type]
  826. ;        mov     dl , [esi + ICMP_Packet.Code]
  827. ;        mov     di , [esi + ICMP_Packet.Identifier]
  828. ;        mov     [eax + SOCKET.LocalPort], di            ; Set localport to the identifier number, so we can receive reply's
  829. ;        shl     edi, 16
  830. ;        mov     di , [esi + ICMP_Packet.SequenceNumber]
  831. ;        add     esi, ICMP_Packet.Data
  832. ;        mov     ebx, [eax + SOCKET.LocalIP]
  833. ;        mov     eax, [eax + SOCKET.RemoteIP]
  834. ;        call    ICMP_create_packet
  835.  
  836.         mov     [esp+32], eax
  837.         ret
  838.  
  839.  
  840.  
  841. ;-----------------------------------------------
  842. ;
  843. ; SOCKET_find_free_port (local port)
  844. ;
  845. ; works with INET byte order
  846. ;
  847. ;  IN:  type in ecx (TCP/UDP)
  848. ;  OUT: bx = 0 on error, portnumber otherwise
  849. ;
  850. ;-----------------------------------------------
  851. align 4
  852. socket_find_port:
  853.  
  854.         DEBUGF  1,"Socket_find_free_port\n"
  855.  
  856.         cmp     ecx, IP_PROTO_UDP
  857.         je      .udp
  858.  
  859.         cmp     ecx, IP_PROTO_TCP
  860.         je      .tcp
  861.  
  862.   .udp:
  863.         mov     bx, [last_UDP_port]
  864.         je      .continue
  865.  
  866.   .tcp:
  867.         mov     bx, [last_TCP_port]
  868.  
  869.  
  870.   .continue:
  871.         inc     bx
  872.  
  873.   .check_only:
  874.         mov     esi, net_sockets
  875.  
  876.   .next_socket:
  877.         mov     esi, [esi + SOCKET_head.NextPtr]
  878.         or      esi, esi
  879.         jz      .port_ok
  880.  
  881.         cmp     [esi + SOCKET_head.Type], ecx
  882.         jne     .next_socket
  883.  
  884.         rol     bx, 8
  885.         cmp     [esi + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
  886.         rol     bx, 8                           ; this doesnt change the zero flag, does it ?
  887.         jne     .next_socket
  888.  
  889.         cmp     bx, MAX_EPHEMERAL_PORT
  890.         jle     .continue
  891.  
  892.         ; todo: WRAP!
  893. ;        mov     [last_UDP_port], MIN_EPHEMERAL_PORT
  894.   .exit:
  895.         xor     ebx, ebx
  896.  
  897.   .port_ok:
  898.         rol     bx, 8
  899.         ret
  900.  
  901. ;-----------------------------------------------
  902. ;
  903. ; SOCKET_check_port (local port)
  904. ;
  905. ; works with INET byte order
  906. ;
  907. ;  IN:  type in ecx (TCP/UDP)
  908. ;       port to check in bx
  909. ;  OUT: bx = 0 on error, unchanged otherwise
  910. ;
  911. ;-----------------------------------------------
  912. align 4
  913. socket_check_port:
  914.         mov     esi, net_sockets
  915.  
  916.   .next_socket:
  917.         mov     esi, [esi + SOCKET_head.NextPtr]
  918.         or      esi, esi
  919.         jz      .port_ok
  920.  
  921.         cmp     [esi + SOCKET_head.Type], ecx
  922.         jne     .next_socket
  923.  
  924.         cmp     [esi + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
  925.         jne     .next_socket
  926.  
  927.         xor     ebx, ebx
  928.  
  929.   .port_ok:
  930.         ret
  931.  
  932.  
  933. ;-----------------------------------------------
  934. ;
  935. ; SOCKET_internal_receiver
  936. ;
  937. ; Updates a socket with received data
  938. ;
  939. ; Note: the mutex must already be set !
  940. ;
  941. ;  IN:  eax = socket ptr
  942. ;       ecx = size
  943. ;       esi = pointer to buffer
  944. ;       edi = offset
  945. ;
  946. ;  OUT: xxx
  947. ;
  948. ;-----------------------------------------------
  949. align 4
  950. socket_internal_receiver:
  951.  
  952.         DEBUGF 1,"Internal socket receiver: buffer %x, offset: %x\n", esi, edi
  953.  
  954.         push    edi     ; offset
  955.         push    ecx     ; size
  956.         push    esi     ; data_ptr
  957.         mov     esi, esp
  958.         add_to_queue (eax + 2048), SOCKET_QUEUE_SIZE, 3*4, .full
  959.         DEBUGF  1,"Queued packet successfully\n"
  960.         add     esp, 4*3
  961.  
  962.         mov     [eax + SOCKET_head.lock], 0
  963.  
  964.         ; flag an event to the application
  965.         mov     edx, [eax + SOCKET_head.PID]                            ; get socket owner PID
  966.         mov     ecx, 1
  967.         mov     esi, TASK_DATA + TASKDATA.pid
  968.  
  969.        .next_pid:
  970.         cmp     [esi], edx
  971.         je      .found_pid
  972.         inc     ecx
  973.         add     esi, 0x20
  974.         cmp     ecx, [TASK_COUNT]
  975.         jbe     .next_pid
  976.         ret
  977.  
  978.        .found_pid:
  979.         shl     ecx, 8
  980.         or      [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK   ; stack event
  981.         mov     [check_idle_semaphore], 200
  982.         ret
  983.  
  984.   .full:
  985.         DEBUGF 1,"Socket %x is full!\n",eax
  986.         mov     [eax + SOCKET_head.lock], 0
  987.         call    kernel_free
  988.         add     esp, 8
  989.         ret
  990.  
  991.  
  992.  
  993.  
  994. ; Allocate memory for socket data and put new socket into the list
  995. ; Newly created socket is initialized with calling PID and number and
  996. ; put into beginning of list (which is a fastest way).
  997. ;
  998. ; @return socket structure address in EAX
  999. ;
  1000. proc net_socket_alloc stdcall uses ebx ecx edx edi
  1001.         stdcall kernel_alloc, SOCKETBUFFSIZE
  1002.         DEBUGF  1, "K : net_socket_alloc (0x%x)\n", eax
  1003.         ; check if we can allocate needed amount of memory
  1004.         or      eax, eax
  1005.         jz      .exit
  1006.  
  1007.         ; zero-initialize allocated memory
  1008.         push    eax
  1009.         mov     edi, eax
  1010.  
  1011.         mov     ecx, SOCKETBUFFSIZE / 4
  1012. ;        cld
  1013.         xor     eax, eax
  1014.         rep     stosd
  1015.         pop     eax
  1016.  
  1017.         init_queue (eax + 2048)
  1018.  
  1019.         ; add socket to the list by changing pointers
  1020.         mov     ebx, net_sockets
  1021.         push    [ebx + SOCKET_head.NextPtr]
  1022.         mov     [ebx + SOCKET_head.NextPtr], eax
  1023.         mov     [eax + SOCKET_head.PrevPtr], ebx
  1024.         pop     ebx
  1025.         mov     [eax + SOCKET_head.NextPtr], ebx
  1026.         or      ebx, ebx
  1027.         jz      @f
  1028.         mov     [ebx + SOCKET_head.PrevPtr], eax
  1029.  
  1030.     @@: ; set socket owner PID to the one of calling process
  1031.         mov     ebx, [TASK_BASE]
  1032.         mov     ebx, [ebx + TASKDATA.pid]
  1033.         mov     [eax + SOCKET_head.PID], ebx
  1034.  
  1035.         ; find first free socket number and use it
  1036.         ;mov     edx, ebx
  1037.         mov     ebx, net_sockets
  1038.         xor     ecx, ecx
  1039.   .next_socket_number:
  1040.         inc     ecx
  1041.   .next_socket:
  1042.         mov     ebx, [ebx + SOCKET_head.NextPtr]
  1043.         or      ebx, ebx
  1044.         jz      .last_socket_number
  1045.         cmp     [ebx + SOCKET_head.Number], ecx
  1046.         jne     .next_socket
  1047.         ;cmp     [ebx + SOCKET.PID], edx
  1048.         ;jne     .next_socket
  1049.         mov     ebx, net_sockets
  1050.         jmp     .next_socket_number
  1051.  
  1052.   .last_socket_number:
  1053.         mov     [eax + SOCKET_head.Number], ecx
  1054.  
  1055.   .exit:
  1056.         ret
  1057. endp
  1058.  
  1059. ; Free socket data memory and pop socket off the list
  1060. ;
  1061. ; @param sockAddr is a socket structure address
  1062. ;
  1063. proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD
  1064.         mov     eax, [sockAddr]
  1065.         DEBUGF  1, "K : net_socket_free (0x%x)\n", eax
  1066.         ; check if we got something similar to socket structure address
  1067.         or      eax, eax
  1068.         jz      .error
  1069.  
  1070.         ; make sure sockAddr is one of the socket addresses in the list
  1071.         mov     ebx, net_sockets
  1072.         ;mov     ecx, [TASK_BASE]
  1073.         ;mov     ecx, [ecx + TASKDATA.pid]
  1074.   .next_socket:
  1075.         mov     ebx, [ebx + SOCKET_head.NextPtr]
  1076.         or      ebx, ebx
  1077.         jz      .error
  1078.         cmp     ebx, eax
  1079.         jne     .next_socket
  1080.         ;cmp     [ebx + SOCKET.PID], ecx
  1081.         ;jne     .next_socket
  1082.  
  1083.         ; okay, we found the correct one
  1084.         ; remove it from the list first, changing pointers
  1085.         mov     ebx, [eax + SOCKET_head.NextPtr]
  1086.         mov     eax, [eax + SOCKET_head.PrevPtr]
  1087.         mov     [eax + SOCKET_head.NextPtr], ebx
  1088.         or      ebx, ebx
  1089.         jz      @f
  1090.         mov     [ebx + SOCKET_head.PrevPtr], eax
  1091.  
  1092.         lea     ebx, [eax + SOCKET_head.lock]
  1093.         call    wait_mutex
  1094.  
  1095.     @@: ; and finally free the memory structure used
  1096.         stdcall kernel_free, [sockAddr]
  1097.         ret
  1098.  
  1099.   .error:
  1100.         DEBUGF  1, "K :   failed\n"
  1101.         ret
  1102. endp
  1103.  
  1104. ; Get socket structure address by its number
  1105. ; Scan through sockets list to find the socket with specified number.
  1106. ; This proc uses SOCKET.PID indirectly to check if socket is owned by
  1107. ; calling process.
  1108. ;
  1109. ; @param sockNum is a socket number
  1110. ; @return socket structure address or 0 (not found) in EAX
  1111. ;
  1112. proc net_socket_num_to_addr stdcall uses ebx ecx, sockNum:DWORD
  1113.         mov     eax, [sockNum]
  1114.         ; check if we got something similar to socket number
  1115.         or      eax, eax
  1116.         jz      .error
  1117.  
  1118.         ; scan through sockets list
  1119.         mov     ebx, net_sockets
  1120.         ;mov     ecx, [TASK_BASE]
  1121.         ;mov     ecx, [ecx + TASKDATA.pid]
  1122.   .next_socket:
  1123.         mov     ebx, [ebx + SOCKET_head.NextPtr]
  1124.         or      ebx, ebx
  1125.         jz      .error
  1126.         cmp     [ebx + SOCKET_head.Number], eax
  1127.         jne     .next_socket
  1128.         ;cmp     [ebx + SOCKET.PID], ecx
  1129.         ;jne     .next_socket
  1130.  
  1131.         ; okay, we found the correct one
  1132.         mov     eax, ebx
  1133.         ret
  1134.  
  1135.   .error:
  1136.         xor     eax, eax
  1137.         ret
  1138. endp
  1139.  
  1140. ; Get socket number by its structure address
  1141. ; Scan through sockets list to find the socket with specified address.
  1142. ; This proc uses SOCKET.PID indirectly to check if socket is owned by
  1143. ; calling process.
  1144. ;
  1145. ; @param sockAddr is a socket structure address
  1146. ; @return socket number (SOCKET.Number) or 0 (not found) in EAX
  1147. ;
  1148. proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD
  1149.         mov     eax, [sockAddr]
  1150.         ; check if we got something similar to socket structure address
  1151.         or      eax, eax
  1152.         jz      .error
  1153.  
  1154.         ; scan through sockets list
  1155.         mov     ebx, net_sockets
  1156.         ;mov     ecx, [TASK_BASE]
  1157.         ;mov     ecx, [ecx + TASKDATA.pid]
  1158.   .next_socket:
  1159.         mov     ebx, [ebx + SOCKET_head.NextPtr]
  1160.         or      ebx, ebx
  1161.         jz      .error
  1162.         cmp     ebx, eax
  1163.         jne     .next_socket
  1164.         ;cmp     [ebx + SOCKET.PID], ecx
  1165.         ;jne     .next_socket
  1166.  
  1167.         ; okay, we found the correct one
  1168.         mov     eax, [ebx + SOCKET_head.Number]
  1169.         ret
  1170.  
  1171.   .error:
  1172.         xor     eax, eax
  1173.         ret
  1174. endp
  1175.