Subversion Repositories Kolibri OS

Rev

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