Subversion Repositories Kolibri OS

Rev

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