Subversion Repositories Kolibri OS

Rev

Rev 3908 | Rev 4423 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  Part of the TCP/IP network stack for KolibriOS                 ;;
  7. ;;                                                                 ;;
  8. ;;   Written by hidnplayr@kolibrios.org,                           ;;
  9. ;;     and Clevermouse.                                            ;;
  10. ;;                                                                 ;;
  11. ;;       Based on code by mike.dld                                 ;;
  12. ;;                                                                 ;;
  13. ;;         GNU GENERAL PUBLIC LICENSE                              ;;
  14. ;;          Version 2, June 1991                                   ;;
  15. ;;                                                                 ;;
  16. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  17.  
  18. $Revision: 4265 $
  19.  
  20. struct  SOCKET
  21.  
  22.         NextPtr                 dd ? ; pointer to next socket in list
  23.         PrevPtr                 dd ? ; pointer to previous socket in list
  24.         Number                  dd ? ; socket number
  25.  
  26.         mutex                   MUTEX
  27.  
  28.         PID                     dd ? ; process ID
  29.         TID                     dd ? ; thread ID
  30.         Domain                  dd ? ; INET/LOCAL/..
  31.         Type                    dd ? ; RAW/STREAM/DGRAP
  32.         Protocol                dd ? ; ICMP/IPv4/ARP/TCP/UDP
  33.         errorcode               dd ?
  34.         device                  dd ? ; driver pointer, socket pointer if it's an LOCAL socket
  35.  
  36.         options                 dd ?
  37.         state                   dd ?
  38.         backlog                 dw ? ; how many incoming connections that can be queued
  39.  
  40.         snd_proc                dd ?
  41.         rcv_proc                dd ?
  42.         connect_proc            dd ?
  43.  
  44. ends
  45.  
  46. struct  IP_SOCKET               SOCKET
  47.  
  48.         LocalIP                 rd 4 ; network byte order
  49.         RemoteIP                rd 4 ; network byte order
  50.  
  51. ends
  52.  
  53. struct  TCP_SOCKET              IP_SOCKET
  54.  
  55.         LocalPort               dw ? ; network byte order
  56.         RemotePort              dw ? ; network byte order
  57.  
  58.         t_state                 dd ? ; TCB state
  59.         t_rxtshift              db ?
  60.                                 rb 3 ; align
  61.         t_rxtcur                dd ?
  62.         t_dupacks               dd ?
  63.         t_maxseg                dd ?
  64.         t_force                 dd ?
  65.         t_flags                 dd ?
  66.  
  67. ;---------------
  68. ; RFC783 page 21
  69.  
  70. ; send sequence
  71.         SND_UNA                 dd ? ; sequence number of unack'ed sent Packets
  72.         SND_NXT                 dd ? ; next send sequence number to use
  73.         SND_UP                  dd ? ; urgent pointer
  74.         SND_WL1                 dd ? ; window minus one
  75.         SND_WL2                 dd ? ;
  76.         ISS                     dd ? ; initial send sequence number
  77.         SND_WND                 dd ? ; send window
  78.  
  79. ; receive sequence
  80.         RCV_WND                 dd ? ; receive window
  81.         RCV_NXT                 dd ? ; next receive sequence number to use
  82.         RCV_UP                  dd ? ; urgent pointer
  83.         IRS                     dd ? ; initial receive sequence number
  84.  
  85. ;---------------------
  86. ; Additional variables
  87.  
  88. ; receive variables
  89.         RCV_ADV                 dd ?
  90.  
  91. ; retransmit variables
  92.         SND_MAX                 dd ?
  93.  
  94. ; congestion control
  95.         SND_CWND                dd ?
  96.         SND_SSTHRESH            dd ?
  97.  
  98. ;----------------------
  99. ; Transmit timing stuff
  100.         t_idle                  dd ?
  101.         t_rtt                   dd ?
  102.         t_rtseq                 dd ?
  103.         t_srtt                  dd ?
  104.         t_rttvar                dd ?
  105.         t_rttmin                dd ?
  106.         max_sndwnd              dd ?
  107.  
  108. ;-----------------
  109. ; Out-of-band data
  110.         t_oobflags              dd ?
  111.         t_iobc                  dd ?
  112.         t_softerror             dd ?
  113.  
  114.  
  115. ;---------
  116. ; RFC 1323                              ; the order of next 4 elements may not change
  117.  
  118.         SND_SCALE               db ?
  119.         RCV_SCALE               db ?
  120.         requested_s_scale       db ?
  121.         request_r_scale         db ?
  122.  
  123.         ts_recent               dd ?    ; a copy of the most-recent valid timestamp from the other end
  124.         ts_recent_age           dd ?
  125.         last_ack_sent           dd ?
  126.  
  127.  
  128. ;-------
  129. ; Timers
  130.         timer_flags             dd ?
  131.         timer_retransmission    dd ? ; rexmt
  132.         timer_persist           dd ?
  133.         timer_keepalive         dd ? ; keepalive/syn timeout
  134.         timer_timed_wait        dd ? ; also used as 2msl timer
  135.         timer_connect           dd ?
  136.  
  137. ; extra
  138.  
  139.         ts_ecr                  dd ? ; timestamp echo reply
  140.         ts_val                  dd ?
  141.  
  142.         seg_next                dd ? ; re-assembly queue
  143.  
  144.         temp_bits               db ?
  145.                                 rb 3 ; align
  146.  
  147.  
  148. ends
  149.  
  150. struct  UDP_SOCKET              IP_SOCKET
  151.  
  152.         LocalPort               dw ? ; network byte order
  153.         RemotePort              dw ? ; network byte order
  154.  
  155. ends
  156.  
  157.  
  158. struct  ICMP_SOCKET             IP_SOCKET
  159.  
  160.         Identifier              dw ?
  161.  
  162. ends
  163.  
  164.  
  165. struct  RING_BUFFER
  166.  
  167.         mutex                   MUTEX
  168.         start_ptr               dd ? ; Pointer to start of buffer
  169.         end_ptr                 dd ? ; pointer to end of buffer
  170.         read_ptr                dd ? ; Read pointer
  171.         write_ptr               dd ? ; Write pointer
  172.         size                    dd ? ; Number of bytes buffered
  173.  
  174. ends
  175.  
  176. struct  STREAM_SOCKET           TCP_SOCKET
  177.  
  178.         rcv                     RING_BUFFER
  179.         snd                     RING_BUFFER
  180.  
  181. ends
  182.  
  183. struct  socket_queue_entry
  184.  
  185.         data_ptr                dd ?
  186.         buf_ptr                 dd ?
  187.         data_size               dd ?
  188.  
  189. ends
  190.  
  191.  
  192. SOCKETBUFFSIZE          = 4096     ; in bytes
  193.  
  194. SOCKET_QUEUE_SIZE       = 10       ; maximum number of incoming packets queued for 1 socket
  195. ; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
  196. SOCKET_QUEUE_LOCATION   = (SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*sizeof.socket_queue_entry - sizeof.queue)
  197.  
  198. uglobal
  199. align 4
  200.  
  201.         net_sockets     rd 4
  202.         last_socket_num dd ?
  203.         last_UDP_port   dw ? ; These values give the number of the last used ephemeral port
  204.         last_TCP_port   dw ? ;
  205.         socket_mutex    MUTEX
  206.  
  207. endg
  208.  
  209.  
  210. ;-----------------------------------------------------------------
  211. ;
  212. ; SOCKET_init
  213. ;
  214. ;-----------------------------------------------------------------
  215. macro   SOCKET_init {
  216.  
  217.         xor     eax, eax
  218.         mov     edi, net_sockets
  219.         mov     ecx, 5
  220.         rep stosd
  221.  
  222.        @@:
  223.         pseudo_random eax
  224.         cmp     ax, EPHEMERAL_PORT_MIN
  225.         jb      @r
  226.         cmp     ax, EPHEMERAL_PORT_MAX
  227.         ja      @r
  228.         xchg    al, ah
  229.         mov     [last_UDP_port], ax
  230.  
  231.        @@:
  232.         pseudo_random eax
  233.         cmp     ax, EPHEMERAL_PORT_MIN
  234.         jb      @r
  235.         cmp     ax, EPHEMERAL_PORT_MAX
  236.         ja      @r
  237.         xchg    al, ah
  238.         mov     [last_TCP_port], ax
  239.  
  240.         mov     ecx, socket_mutex
  241.         call    mutex_init
  242.  
  243. }
  244.  
  245. ;-----------------------------------------------------------------
  246. ;
  247. ; Socket API (function 74)
  248. ;
  249. ;-----------------------------------------------------------------
  250. align 4
  251. sys_socket:
  252.  
  253.         mov     dword[esp+20], 0        ; Set error code to 0
  254.  
  255.         cmp     ebx, 255
  256.         jz      SOCKET_debug
  257.  
  258.         cmp     ebx, .number
  259.         ja      .error
  260.         jmp     dword [.table + 4*ebx]
  261.  
  262.   .table:
  263.         dd      SOCKET_open     ; 0
  264.         dd      SOCKET_close    ; 1
  265.         dd      SOCKET_bind     ; 2
  266.         dd      SOCKET_listen   ; 3
  267.         dd      SOCKET_connect  ; 4
  268.         dd      SOCKET_accept   ; 5
  269.         dd      SOCKET_send     ; 6
  270.         dd      SOCKET_receive  ; 7
  271.         dd      SOCKET_set_opt  ; 8
  272.         dd      SOCKET_get_opt  ; 9
  273.         dd      SOCKET_pair     ; 10
  274.   .number = ($ - .table) / 4 - 1
  275.  
  276.   .error:
  277.         mov     dword[esp+32], -1
  278.         mov     dword[esp+20], EINVAL
  279.  
  280.         ret
  281.  
  282. ;-----------------------------------------------------------------
  283. ;
  284. ; SOCKET_open
  285. ;
  286. ;  IN:  domain in ecx
  287. ;       type in edx
  288. ;       protocol in esi
  289. ;  OUT: eax is socket num, -1 on error
  290. ;
  291. ;-----------------------------------------------------------------
  292. align 4
  293. SOCKET_open:
  294.  
  295.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi
  296.  
  297.         push    ecx edx esi
  298.         call    SOCKET_alloc
  299.         pop     esi edx ecx
  300.         jz      .nobuffs
  301.  
  302.         mov     [esp+32], edi                   ; return socketnumber
  303.         DEBUGF  DEBUG_NETWORK_VERBOSE, "socknum=%u\n", edi
  304.  
  305.         test    edx, SO_NONBLOCK
  306.         jz      @f
  307.         or      [eax + SOCKET.options], SO_NONBLOCK
  308.         and     edx, not SO_NONBLOCK
  309.   @@:
  310.  
  311.         mov     [eax + SOCKET.Domain], ecx
  312.         mov     [eax + SOCKET.Type], edx
  313.         mov     [eax + SOCKET.Protocol], esi
  314.         mov     [eax + SOCKET.connect_proc], connect_notsupp
  315.  
  316.         cmp     ecx, AF_INET4
  317.         jne     .no_inet4
  318.  
  319.         cmp     edx, SOCK_DGRAM
  320.         je      .udp
  321.  
  322.         cmp     edx, SOCK_STREAM
  323.         je      .tcp
  324.  
  325.         cmp     edx, SOCK_RAW
  326.         je      .raw
  327.  
  328.   .no_inet4:
  329.         cmp     ecx, AF_PPP
  330.         jne     .no_ppp
  331.  
  332.         cmp     esi, PPP_PROTO_ETHERNET
  333.         je      .pppoe
  334.  
  335.   .no_ppp:
  336.   .unsupported:
  337.         push    eax
  338.         call    SOCKET_free
  339.         pop     eax
  340.         mov     dword[esp+20], EOPNOTSUPP
  341.         mov     dword[esp+32], -1
  342.         ret
  343.  
  344.   .nobuffs:
  345.         mov     dword[esp+20], ENOBUFS
  346.         mov     dword[esp+32], -1
  347.         ret
  348.  
  349.   .raw:
  350.         test    esi, esi       ; IP_PROTO_IP
  351.         jz      .raw_ip
  352.  
  353.         cmp     esi, IP_PROTO_ICMP
  354.         je      .raw_icmp
  355.  
  356.         jmp     .unsupported
  357.  
  358. align 4
  359.   .udp:
  360.         mov     [eax + SOCKET.Protocol], IP_PROTO_UDP
  361.         mov     [eax + SOCKET.snd_proc], SOCKET_send_udp
  362.         mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
  363.         mov     [eax + SOCKET.connect_proc], UDP_connect
  364.         ret
  365.  
  366. align 4
  367.   .tcp:
  368.         mov     [eax + SOCKET.Protocol], IP_PROTO_TCP
  369.         mov     [eax + SOCKET.snd_proc], SOCKET_send_tcp
  370.         mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
  371.         mov     [eax + SOCKET.connect_proc], TCP_connect
  372.  
  373.         TCP_init_socket eax
  374.         ret
  375.  
  376.  
  377. align 4
  378.   .raw_ip:
  379.         mov     [eax + SOCKET.snd_proc], SOCKET_send_ip
  380.         mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
  381.         mov     [eax + SOCKET.connect_proc], IPv4_connect
  382.         ret
  383.  
  384.  
  385. align 4
  386.   .raw_icmp:
  387.         mov     [eax + SOCKET.snd_proc], SOCKET_send_icmp
  388.         mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
  389.         mov     [eax + SOCKET.connect_proc], IPv4_connect
  390.         ret
  391.  
  392. align 4
  393.   .pppoe:
  394.         push    eax
  395.         init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
  396.         pop     eax
  397.  
  398.         mov     [eax + SOCKET.snd_proc], SOCKET_send_pppoe
  399.         mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
  400.         ret
  401.  
  402.  
  403. ;-----------------------------------------------------------------
  404. ;
  405. ; SOCKET_bind
  406. ;
  407. ;  IN:  socket number in ecx
  408. ;       pointer to sockaddr struct in edx
  409. ;       length of that struct in esi
  410. ;  OUT: 0 on success
  411. ;
  412. ;-----------------------------------------------------------------
  413. align 4
  414. SOCKET_bind:
  415.  
  416.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
  417.  
  418.         call    SOCKET_num_to_ptr
  419.         jz      .invalid
  420.  
  421.         cmp     esi, 2
  422.         jb      .invalid
  423.  
  424.         cmp     [eax + UDP_SOCKET.LocalPort], 0         ; Socket can only be bound once
  425.         jnz     .invalid
  426.  
  427.         cmp     word [edx], AF_INET4
  428.         je      .af_inet4
  429.  
  430.         cmp     word [edx], AF_LOCAL
  431.         je      .af_local
  432.  
  433.   .notsupp:
  434.         mov     dword[esp+20], EOPNOTSUPP
  435.         mov     dword[esp+32], -1
  436.         ret
  437.  
  438.   .invalid:
  439.         mov     dword[esp+20], EINVAL
  440.         mov     dword[esp+32], -1
  441.         ret
  442.  
  443.   .af_local:
  444.         ; TODO: write code here
  445.         mov     dword[esp+32], 0
  446.         ret
  447.  
  448.   .af_inet4:
  449.         cmp     esi, 6
  450.         jb      .invalid
  451.  
  452.         cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
  453.         je      .udp
  454.  
  455.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
  456.         je      .tcp
  457.  
  458.         jmp     .notsupp
  459.  
  460.   .tcp:
  461.   .udp:
  462.  
  463.         pushd   [edx + 4]                       ; First, fill in the IP
  464.         popd    [eax + IP_SOCKET.LocalIP]
  465.  
  466.         mov     bx, [edx + 2]                   ; Did caller specify a local port?
  467.         test    bx, bx
  468.         jnz     .just_check
  469.         call    SOCKET_find_port                ; Nope, find an ephemeral one
  470.         jmp     .done
  471.  
  472.   .just_check:
  473.         call    SOCKET_check_port               ; Yes, check if it's still available
  474.         jz      .addrinuse                      ; ZF is set by socket_check_port on error
  475.  
  476.   .done:
  477.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_bind: local ip=%u.%u.%u.%u\n",\
  478.         [eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
  479.         [eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
  480.  
  481.         mov     dword[esp+32], 0
  482.         ret
  483.  
  484.   .addrinuse:
  485.         mov     dword[esp+32], -1
  486.         mov     dword[esp+20], EADDRINUSE
  487.         ret
  488.  
  489.  
  490.  
  491.  
  492. ;-----------------------------------------------------------------
  493. ;
  494. ; SOCKET_connect
  495. ;
  496. ;  IN:  socket number in ecx
  497. ;       pointer to sockaddr struct in edx
  498. ;       length of that struct in esi
  499. ;  OUT: 0 on success
  500. ;
  501. ;-----------------------------------------------------------------
  502. align 4
  503. SOCKET_connect:
  504.  
  505.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
  506.  
  507.         call    SOCKET_num_to_ptr
  508.         jz      .invalid
  509.  
  510.         cmp     esi, 8
  511.         jb      .invalid
  512.  
  513.         cmp     [eax + SOCKET.state], SS_ISCONNECTING
  514.         je      .already
  515.  
  516.         test    [eax + SOCKET.options], SO_ACCEPTCON
  517.         jnz     .notsupp
  518.  
  519.         call    [eax + SOCKET.connect_proc]
  520.  
  521.         mov     dword[esp+20], ebx
  522.         mov     dword[esp+32], eax
  523.         ret
  524.  
  525.  
  526.   .notsupp:
  527.         mov     dword[esp+20], EOPNOTSUPP
  528.         mov     dword[esp+32], -1
  529.         ret
  530.  
  531.   .invalid:
  532.         mov     dword[esp+20], EINVAL
  533.         mov     dword[esp+32], -1
  534.         ret
  535.  
  536.   .already:
  537.         mov     dword[esp+20], EALREADY
  538.         mov     dword[esp+32], -1
  539.         ret
  540.  
  541.  
  542. connect_notsupp:
  543.         xor     eax, eax
  544.         dec     eax
  545.         mov     ebx, EOPNOTSUPP
  546.         ret
  547.  
  548.  
  549. ;-----------------------------------------------------------------
  550. ;
  551. ; SOCKET_listen
  552. ;
  553. ;  IN:  socket number in ecx
  554. ;       backlog in edx
  555. ;  OUT: eax is socket num, -1 on error
  556. ;
  557. ;-----------------------------------------------------------------
  558. align 4
  559. SOCKET_listen:
  560.  
  561.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
  562.  
  563.         call    SOCKET_num_to_ptr
  564.         jz      .invalid
  565.  
  566.         cmp     [eax + SOCKET.Domain], AF_INET4
  567.         jne     .notsupp
  568.  
  569.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
  570.         jne     .invalid
  571.  
  572.         cmp     [eax + TCP_SOCKET.LocalPort], 0
  573.         je      .already
  574.  
  575.         cmp     [eax + IP_SOCKET.LocalIP], 0
  576.         jne     @f
  577.         push    [IP_LIST + 4]           ;;; fixme!!!!
  578.         pop     [eax + IP_SOCKET.LocalIP]
  579.        @@:
  580.  
  581.         cmp     edx, MAX_backlog
  582.         jbe     @f
  583.         mov     edx, MAX_backlog
  584.        @@:
  585.  
  586.         mov     [eax + SOCKET.backlog], dx
  587.         or      [eax + SOCKET.options], SO_ACCEPTCON
  588.         mov     [eax + TCP_SOCKET.t_state], TCPS_LISTEN
  589.         mov     [eax + TCP_SOCKET.timer_keepalive], 0           ; disable keepalive timer
  590.  
  591.         push    eax
  592.         init_queue (eax + SOCKET_QUEUE_LOCATION)                ; Set up sockets queue
  593.         pop     eax
  594.  
  595.         mov     dword[esp+32], 0
  596.         ret
  597.  
  598.   .notsupp:
  599.         mov     dword[esp+20], EOPNOTSUPP
  600.         mov     dword[esp+32], -1
  601.         ret
  602.  
  603.   .invalid:
  604.         mov     dword[esp+20], EINVAL
  605.         mov     dword[esp+32], -1
  606.         ret
  607.  
  608.   .already:
  609.         mov     dword[esp+20], EALREADY
  610.         mov     dword[esp+32], -1
  611.         ret
  612.  
  613.  
  614. ;-----------------------------------------------------------------
  615. ;
  616. ; SOCKET_accept
  617. ;
  618. ;  IN:  socket number in ecx
  619. ;       addr in edx
  620. ;       addrlen in esi
  621. ;  OUT: eax is socket num, -1 on error
  622. ;
  623. ;-----------------------------------------------------------------
  624. align 4
  625. SOCKET_accept:
  626.  
  627.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
  628.  
  629.         call    SOCKET_num_to_ptr
  630.         jz      .invalid
  631.  
  632.         test    [eax + SOCKET.options], SO_ACCEPTCON
  633.         jz      .invalid
  634.  
  635.         cmp     [eax + SOCKET.Domain], AF_INET4
  636.         jne     .notsupp
  637.  
  638.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
  639.         jne     .invalid
  640.  
  641.   .loop:
  642.         get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .block
  643.  
  644. ; Ok, we got a socket ptr
  645.         mov     eax, [esi]
  646.  
  647. ; Change thread ID to that of the current thread
  648.         mov     ebx, [TASK_BASE]
  649.         mov     ebx, [ebx + TASKDATA.pid]
  650.         mov     [eax + SOCKET.TID], ebx
  651.  
  652. ; Convert it to a socket number
  653.         call    SOCKET_ptr_to_num
  654.         jz      .invalid        ; FIXME ?
  655.  
  656. ; and return it to caller
  657.         mov     [esp+32], eax
  658.         ret
  659.  
  660.   .block:
  661.         test    [eax + SOCKET.options], SO_NONBLOCK
  662.         jnz     .wouldblock
  663.  
  664.         call    SOCKET_block
  665.         jmp     .loop
  666.  
  667.   .wouldblock:
  668.         mov     dword[esp+20], EWOULDBLOCK
  669.         mov     dword[esp+32], -1
  670.         ret
  671.  
  672.   .invalid:
  673.         mov     dword[esp+20], EINVAL
  674.         mov     dword[esp+32], -1
  675.         ret
  676.  
  677.   .notsupp:
  678.         mov     dword[esp+20], EOPNOTSUPP
  679.         mov     dword[esp+32], -1
  680.         ret
  681.  
  682. ;-----------------------------------------------------------------
  683. ;
  684. ; SOCKET_close
  685. ;
  686. ;  IN:  socket number in ecx
  687. ;  OUT: eax is socket num, -1 on error
  688. ;
  689. ;-----------------------------------------------------------------
  690. align 4
  691. SOCKET_close:
  692.  
  693.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_close: socknum=%u\n", ecx
  694.  
  695.         call    SOCKET_num_to_ptr
  696.         jz      .invalid
  697.  
  698.         mov     dword[esp+32], 0                                ; The socket exists, so we will succeed in closing it.
  699.  
  700.         or      [eax + SOCKET.options], SO_NONBLOCK             ; Mark the socket as non blocking, we dont want it to block any longer!
  701.  
  702.         test    [eax + SOCKET.state], SS_BLOCKED                ; Is the socket still in blocked state?
  703.         jz      @f
  704.         call    SOCKET_notify.unblock                           ; Unblock it.
  705.   @@:
  706.  
  707.         cmp     [eax + SOCKET.Domain], AF_INET4
  708.         jne     .free
  709.  
  710.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
  711.         je      .tcp
  712.  
  713.   .free:
  714.         call    SOCKET_free
  715.         ret
  716.  
  717.   .tcp:
  718.         cmp     [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED    ; state must be LISTEN, SYN_SENT or CLOSED
  719.         jb      .free
  720.  
  721.         call    TCP_usrclosed
  722.         call    TCP_output      ;;;; Fixme: is this nescessary??
  723.         call    SOCKET_free
  724.  
  725.         ret
  726.  
  727.  
  728.   .invalid:
  729.         mov     dword[esp+20], EINVAL
  730.         mov     dword[esp+32], -1
  731.         ret
  732.  
  733.  
  734. ;-----------------------------------------------------------------
  735. ;
  736. ; SOCKET_receive
  737. ;
  738. ;  IN:  socket number in ecx
  739. ;       addr to buffer in edx
  740. ;       length of buffer in esi
  741. ;       flags in edi
  742. ;  OUT: eax is number of bytes copied, -1 on error
  743. ;
  744. ;-----------------------------------------------------------------
  745. align 4
  746. SOCKET_receive:
  747.  
  748.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
  749.  
  750.         call    SOCKET_num_to_ptr
  751.         jz      .invalid
  752.  
  753.   .loop:
  754.         push    edi
  755.         call    [eax + SOCKET.rcv_proc]
  756.         pop     edi
  757.  
  758.         test    [eax + SOCKET.state], SS_CANTRCVMORE
  759.         jnz     .return
  760.  
  761.         cmp     ebx, EWOULDBLOCK
  762.         jne     .return
  763.  
  764.         test    edi, MSG_DONTWAIT
  765.         jnz     .return_err
  766.  
  767. ;        test    [eax + SOCKET.options], SO_NONBLOCK
  768. ;        jnz     .return_err
  769.  
  770.         call    SOCKET_block
  771.         jmp     .loop
  772.  
  773.  
  774.   .invalid:
  775.         push    EINVAL
  776.         pop     ebx
  777.   .return_err:
  778.         mov     ecx, -1
  779.   .return:
  780.         mov     [esp+20], ebx
  781.         mov     [esp+32], ecx
  782.         ret
  783.  
  784.  
  785.  
  786.  
  787.  
  788. align 4
  789. SOCKET_receive_dgram:
  790.  
  791.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: DGRAM\n"
  792.  
  793.         mov     ebx, esi                                        ; bufferlength
  794.  
  795.         get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .wouldblock ; sets esi only on success.
  796.         mov     ecx, [esi + socket_queue_entry.data_size]
  797.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: %u bytes data\n", ecx
  798.  
  799.         cmp     ecx, ebx                                        ; If data segment does not fit in applications buffer, abort
  800.         ja      .too_small
  801.  
  802.         push    eax ecx
  803.         push    [esi + socket_queue_entry.buf_ptr]              ; save the buffer addr so we can clear it later
  804.         mov     esi, [esi + socket_queue_entry.data_ptr]
  805.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
  806.  
  807. ; copy the data from kernel buffer to application buffer
  808.         mov     edi, edx                                        ; bufferaddr
  809.         shr     ecx, 1
  810.         jnc     .nb
  811.         movsb
  812.   .nb:
  813.         shr     ecx, 1
  814.         jnc     .nw
  815.         movsw
  816.   .nw:
  817.         test    ecx, ecx
  818.         jz      .nd
  819.         rep movsd
  820.   .nd:
  821.  
  822.         call    NET_packet_free
  823.         pop     ecx eax                                         ; return number of bytes copied to application
  824.         xor     ebx, ebx
  825.         ret
  826.  
  827.   .too_small:
  828.         mov     ecx, -1
  829.         push    EMSGSIZE
  830.         pop     ebx
  831.         ret
  832.  
  833.   .wouldblock:
  834.         push    EWOULDBLOCK
  835.         pop     ebx
  836.         ret
  837.  
  838.  
  839.  
  840. align 4
  841. SOCKET_receive_local:
  842.  
  843.         ; does this socket have a PID yet?
  844.         cmp     [eax + SOCKET.PID], 0
  845.         jne     @f
  846.  
  847.         ; Change PID to that of current process
  848.         mov     ebx, [TASK_BASE]
  849.         mov     ebx, [ebx + TASKDATA.pid]
  850.         mov     [eax + SOCKET.PID], ebx
  851.         mov     [eax + SOCKET.TID], ebx                         ; currently TID = PID in kolibrios :(
  852.       @@:
  853.  
  854.         mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
  855.  
  856. ; ... continue to SOCKET_receive_stream
  857.  
  858. align 4
  859. SOCKET_receive_stream:
  860.  
  861.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: STREAM\n"
  862.  
  863.         cmp     [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0
  864.         je      .wouldblock
  865.  
  866.         test    edi, MSG_PEEK
  867.         jnz     .peek
  868.  
  869.         mov     ecx, esi
  870.         mov     edi, edx
  871.         xor     edx, edx
  872.  
  873.         push    eax
  874.         add     eax, STREAM_SOCKET.rcv
  875.         call    SOCKET_ring_read                                ; copy data from kernel buffer to application buffer
  876.         call    SOCKET_ring_free                                ; free read memory
  877.         pop     eax
  878.  
  879.         xor     ebx, ebx                                        ; errorcode = 0 (no error)
  880.         ret
  881.  
  882.   .wouldblock:
  883.         push    EWOULDBLOCK
  884.         pop     ebx
  885.         xor     ecx, ecx
  886.         ret
  887.  
  888.   .peek:
  889.         mov     ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
  890.         xor     ebx, ebx
  891.         ret
  892.  
  893.  
  894. ;-----------------------------------------------------------------
  895. ;
  896. ; SOCKET_send
  897. ;
  898. ;
  899. ;  IN:  socket number in ecx
  900. ;       pointer to data in edx
  901. ;       datalength in esi
  902. ;       flags in edi
  903. ;  OUT: -1 on error
  904. ;
  905. ;-----------------------------------------------------------------
  906. align 4
  907. SOCKET_send:
  908.  
  909.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
  910.  
  911.         call    SOCKET_num_to_ptr
  912.         jz      .invalid
  913.  
  914.         mov     ecx, esi
  915.         mov     esi, edx
  916.  
  917.         jmp     [eax + SOCKET.snd_proc]
  918.  
  919.   .invalid:
  920.         mov     dword[esp+20], EINVAL
  921.         mov     dword[esp+32], -1
  922.         ret
  923.  
  924.  
  925. align 4
  926. SOCKET_send_udp:
  927.  
  928.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: UDP\n"
  929.  
  930.         mov     [esp+32], ecx
  931.         call    UDP_output
  932.         cmp     eax, -1
  933.         je      .error
  934.         ret
  935.  
  936.   .error:
  937.         mov     dword[esp+32], -1
  938.         mov     dword[esp+20], EMSGSIZE ; FIXME: UDP_output should return error codes!
  939.         ret
  940.  
  941.  
  942. align 4
  943. SOCKET_send_tcp:
  944.  
  945.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: TCP\n"
  946.  
  947.         push    eax
  948.         add     eax, STREAM_SOCKET.snd
  949.         call    SOCKET_ring_write
  950.         pop     eax
  951.  
  952.         mov     [esp+32], ecx
  953.         mov     [eax + SOCKET.errorcode], 0
  954.         push    eax
  955.         call    TCP_output              ; FIXME: this doesnt look pretty, does it?
  956.         pop     eax
  957.         mov     eax, [eax + SOCKET.errorcode]
  958.         mov     [esp+20], eax
  959.         ret
  960.  
  961.  
  962. align 4
  963. SOCKET_send_ip:
  964.  
  965.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n"
  966.  
  967.         mov     [esp+32], ecx
  968.         call    IPv4_output_raw         ; FIXME: IPv4_output_raw should return error codes!
  969.         cmp     eax, -1
  970.         je      .error
  971.         ret
  972.  
  973.   .error:
  974.         mov     dword[esp+32], -1
  975.         mov     dword[esp+20], EMSGSIZE
  976.         ret
  977.  
  978.  
  979. align 4
  980. SOCKET_send_icmp:
  981.  
  982.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n"
  983.  
  984.         mov     [esp+32], ecx
  985.         call    ICMP_output_raw         ; FIXME: errorcodes
  986.         cmp     eax, -1
  987.         je      .error
  988.         ret
  989.  
  990.   .error:
  991.         mov     dword[esp+32], -1
  992.         mov     dword[esp+20], EMSGSIZE
  993.         ret
  994.  
  995.  
  996. align 4
  997. SOCKET_send_pppoe:
  998.  
  999.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: PPPoE\n"
  1000.  
  1001.         mov     [esp+32], ecx
  1002.         mov     ebx, [eax + SOCKET.device]
  1003.  
  1004.         call    PPPoE_discovery_output  ; FIXME: errorcodes
  1005.         cmp     eax, -1
  1006.         je      .error
  1007.         ret
  1008.  
  1009.   .error:
  1010.         mov     dword[esp+32], -1
  1011.         mov     dword[esp+20], EMSGSIZE
  1012.         ret
  1013.  
  1014.  
  1015.  
  1016. align 4
  1017. SOCKET_send_local:
  1018.  
  1019.         ; does this socket have a PID yet?
  1020.         cmp     [eax + SOCKET.PID], 0
  1021.         jne     @f
  1022.  
  1023.         ; Change PID to that of current process
  1024.         mov     ebx, [TASK_BASE]
  1025.         mov     ebx, [ebx + TASKDATA.pid]
  1026.         mov     [eax + SOCKET.PID], ebx
  1027.         mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
  1028.       @@:
  1029.         mov     [eax + SOCKET.snd_proc], SOCKET_send_local_
  1030.  
  1031. align 4
  1032. SOCKET_send_local_:
  1033.  
  1034.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: LOCAL\n"
  1035.  
  1036.         ; get the other side's socket and check if it still exists
  1037.         mov     eax, [eax + SOCKET.device]
  1038.         call    SOCKET_check
  1039.         jz      .invalid
  1040.  
  1041.         ; allright, shove in the data!
  1042.         push    eax
  1043.         add     eax, STREAM_SOCKET.rcv
  1044.         call    SOCKET_ring_write
  1045.         pop     eax
  1046.  
  1047.         ; return the number of written bytes (or errorcode) to application
  1048.         mov     [esp+32], ecx
  1049.  
  1050.         ; and notify the other end
  1051.         call    SOCKET_notify
  1052.  
  1053.         ret
  1054.  
  1055.   .invalid:
  1056.         mov     dword[esp+32], -1
  1057.         mov     dword[esp+20], EINVAL
  1058.         ret
  1059.  
  1060.  
  1061. ;-----------------------------------------------------------------
  1062. ;
  1063. ; SOCKET_get_options
  1064. ;
  1065. ;  IN:  ecx = socket number
  1066. ;       edx = pointer to the options:
  1067. ;               dd      level, optname, optval, optlen
  1068. ;  OUT: -1 on error
  1069. ;
  1070. ; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
  1071. ; TODO: find best way to notify that send()'ed data were acknowledged
  1072. ; Also pseudo-optname -3 is valid and returns socket state, one of TCPS_*.
  1073. ;
  1074. ;-----------------------------------------------------------------
  1075. align 4
  1076. SOCKET_get_opt:
  1077.  
  1078.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_get_opt\n"
  1079.  
  1080.         call    SOCKET_num_to_ptr
  1081.         jz      .invalid
  1082.  
  1083.         cmp     dword [edx], IP_PROTO_TCP
  1084.         jne     .invalid
  1085.         cmp     dword [edx+4], -2
  1086.         je      @f
  1087.         cmp     dword [edx+4], -3
  1088.         jne     .invalid
  1089. @@:
  1090. ;        mov     eax, [edx+12]
  1091. ;        test    eax, eax
  1092. ;        jz      .fail
  1093. ;        cmp     dword [eax], 4
  1094. ;        mov     dword [eax], 4
  1095. ;        jb      .fail
  1096. ;        stdcall net_socket_num_to_addr, ecx
  1097. ;        test    eax, eax
  1098. ;        jz      .fail
  1099. ;        ; todo: check that eax is really TCP socket
  1100. ;        mov     ecx, [eax + TCP_SOCKET.last_ack_number]
  1101. ;        cmp     dword [edx+4], -2
  1102. ;        jz      @f
  1103. ;        mov     ecx, [eax + TCP_SOCKET.state]
  1104. @@:
  1105.         mov     eax, [edx+8]
  1106.         test    eax, eax
  1107.         jz      @f
  1108.         mov     [eax], ecx
  1109. @@:
  1110.         mov     dword [esp+32], 0
  1111.         ret
  1112.  
  1113.   .invalid:
  1114.         mov     dword[esp+32], -1
  1115.         mov     dword[esp+20], EINVAL
  1116.         ret
  1117.  
  1118.  
  1119.  
  1120. ;-----------------------------------------------------------------
  1121. ;
  1122. ; SOCKET_set_options
  1123. ;
  1124. ;  IN:  ecx = socket number
  1125. ;       edx = pointer to the options:
  1126. ;               dd      level, optname, optlen, optval
  1127. ;  OUT: -1 on error
  1128. ;
  1129. ;-----------------------------------------------------------------
  1130. align 4
  1131. SOCKET_set_opt:
  1132.  
  1133.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt\n"
  1134.  
  1135.         call    SOCKET_num_to_ptr
  1136.         jz      .invalid
  1137.  
  1138.         cmp     dword [edx], SOL_SOCKET
  1139.         jne     .invalid
  1140.  
  1141.         cmp     dword [edx+4], SO_BINDTODEVICE
  1142.         je      .bind
  1143.  
  1144.   .invalid:
  1145.         mov     dword[esp+32], -1
  1146.         mov     dword[esp+20], EINVAL
  1147.         ret
  1148.  
  1149.   .bind:
  1150.         cmp     dword[edx+8], 0
  1151.         je      .unbind
  1152.  
  1153.         movzx   edx, byte[edx + 9]
  1154.         cmp     edx, NET_DEVICES_MAX
  1155.         ja      .invalid
  1156.  
  1157.         mov     edx, [NET_DRV_LIST + 4*edx]
  1158.         test    edx, edx
  1159.         jz      .already
  1160.         mov     [eax + SOCKET.device], edx
  1161.  
  1162.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx
  1163.  
  1164.         mov     dword[esp+32], 0        ; success!
  1165.         ret
  1166.  
  1167.   .unbind:
  1168.         mov     [eax + SOCKET.device], 0
  1169.  
  1170.         mov     dword[esp+32], 0        ; success!
  1171.         ret
  1172.  
  1173.   .already:
  1174.         mov     dword[esp+20], EALREADY
  1175.         mov     dword[esp+32], -1
  1176.         ret
  1177.  
  1178.  
  1179.  
  1180.  
  1181. ;-----------------------------------------------------------------
  1182. ;
  1183. ; SOCKET_pair
  1184. ;
  1185. ; Allocates a pair of linked LOCAL domain sockets
  1186. ;
  1187. ; IN: /
  1188. ; OUT: eax is socket1 num, -1 on error
  1189. ;      ebx is socket2 num
  1190. ;
  1191. ;-----------------------------------------------------------------
  1192. align 4
  1193. SOCKET_pair:
  1194.  
  1195.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_pair\n"
  1196.  
  1197.         call    SOCKET_alloc
  1198.         jz      .nomem1
  1199.         mov     [esp+32], edi   ; application's eax
  1200.  
  1201.         mov     [eax + SOCKET.Domain], AF_LOCAL
  1202.         mov     [eax + SOCKET.Type], SOCK_STREAM
  1203.         mov     [eax + SOCKET.Protocol], 0              ;;; CHECKME
  1204.         mov     [eax + SOCKET.snd_proc], SOCKET_send_local
  1205.         mov     [eax + SOCKET.rcv_proc], SOCKET_receive_local
  1206.         mov     [eax + SOCKET.PID], 0
  1207.         mov     ebx, eax
  1208.  
  1209.         call    SOCKET_alloc
  1210.         jz      .nomem2
  1211.         mov     [esp+20], edi   ; application's ebx
  1212.  
  1213.         mov     [eax + SOCKET.Domain], AF_LOCAL
  1214.         mov     [eax + SOCKET.Type], SOCK_STREAM
  1215.         mov     [eax + SOCKET.Protocol], 0              ;;; CHECKME
  1216.         mov     [eax + SOCKET.snd_proc], SOCKET_send_local
  1217.         mov     [eax + SOCKET.rcv_proc], SOCKET_receive_local
  1218.         mov     [eax + SOCKET.PID], 0
  1219.  
  1220.         ; Link the two sockets to eachother
  1221.         mov     [eax + SOCKET.device], ebx
  1222.         mov     [ebx + SOCKET.device], eax
  1223.  
  1224.         lea     eax, [eax + STREAM_SOCKET.rcv]
  1225.         call    SOCKET_ring_create
  1226.  
  1227.         lea     eax, [ebx + STREAM_SOCKET.rcv]
  1228.         call    SOCKET_ring_create
  1229.         pop     eax
  1230.  
  1231.         ret
  1232.  
  1233.   .nomem2:
  1234.         mov     eax, ebx
  1235.         call    SOCKET_free
  1236.   .nomem1:
  1237.         mov     dword[esp+32], -1
  1238.         mov     dword[esp+28], ENOMEM
  1239.         ret
  1240.  
  1241.  
  1242.  
  1243. ;-----------------------------------------------------------------
  1244. ;
  1245. ; SOCKET_debug
  1246. ;
  1247. ;  Copies socket variables to application buffer
  1248. ;
  1249. ;  IN:  ecx = socket number
  1250. ;       edx = pointer to buffer
  1251. ;
  1252. ;  OUT: -1 on error
  1253. ;-----------------------------------------------------------------
  1254. align 4
  1255. SOCKET_debug:
  1256.  
  1257.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_debug\n"
  1258.  
  1259.         mov     edi, edx
  1260.  
  1261.         test    ecx, ecx
  1262.         jz      .returnall
  1263.  
  1264.         call    SOCKET_num_to_ptr
  1265.         jz      .invalid
  1266.  
  1267.         mov     esi, eax
  1268.         mov     ecx, SOCKETBUFFSIZE/4
  1269.         rep movsd
  1270.  
  1271.         mov     dword[esp+32], 0
  1272.         ret
  1273.  
  1274.   .returnall:
  1275.         mov     ebx, net_sockets
  1276.   .next_socket:
  1277.         mov     ebx, [ebx + SOCKET.NextPtr]
  1278.         test    ebx, ebx
  1279.         jz      .done
  1280.         mov     eax, [ebx + SOCKET.Number]
  1281.         stosd
  1282.         jmp     .next_socket
  1283.   .done:
  1284.         xor     eax, eax
  1285.         stosd
  1286.         mov     dword[esp+32], eax
  1287.         ret
  1288.  
  1289.   .invalid:
  1290.         mov     dword[esp+32], -1
  1291.         mov     dword[esp+28], EINVAL
  1292.         ret
  1293.  
  1294.  
  1295. ;-----------------------------------------------------------------
  1296. ;
  1297. ; SOCKET_find_port
  1298. ;
  1299. ; Fills in the local port number for TCP and UDP sockets
  1300. ; This procedure always works because the number of sockets is
  1301. ; limited to a smaller number then the number of possible ports
  1302. ;
  1303. ;  IN:  eax = socket pointer
  1304. ;  OUT: /
  1305. ;
  1306. ;-----------------------------------------------------------------
  1307. align 4
  1308. SOCKET_find_port:
  1309.  
  1310.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_find_port\n"
  1311.  
  1312.         push    ebx esi ecx
  1313.  
  1314.         cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
  1315.         je      .udp
  1316.  
  1317.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
  1318.         je      .tcp
  1319.  
  1320.         pop     ecx esi ebx
  1321.         ret
  1322.  
  1323.   .udp:
  1324.         mov     bx, [last_UDP_port]
  1325.         call    .findit
  1326.         mov     [last_UDP_port], bx
  1327.  
  1328.         pop     ecx esi ebx
  1329.         ret
  1330.  
  1331.   .tcp:
  1332.         mov     bx, [last_TCP_port]
  1333.         call    .findit
  1334.         mov     [last_TCP_port], bx
  1335.  
  1336.         pop     ecx esi ebx
  1337.         ret
  1338.  
  1339.  
  1340.   .restart:
  1341.         mov     bx, MIN_EPHEMERAL_PORT_N
  1342.   .findit:
  1343.         cmp     bx, MAX_EPHEMERAL_PORT_N
  1344.         je      .restart
  1345.  
  1346.         add     bh, 1
  1347.         adc     bl, 0
  1348.  
  1349.         call    SOCKET_check_port
  1350.         jz      .findit
  1351.         ret
  1352.  
  1353.  
  1354.  
  1355. ;-----------------------------------------------------------------
  1356. ;
  1357. ; SOCKET_check_port (to be used with AF_INET only!)
  1358. ;
  1359. ; Checks if a local port number is unused
  1360. ; If the proposed port number is unused, it is filled in in the socket structure
  1361. ;
  1362. ;  IN:  eax = socket ptr (to find out if its a TCP/UDP socket)
  1363. ;        bx = proposed socket number (network byte order)
  1364. ;
  1365. ;  OUT:  ZF = set on error
  1366. ;
  1367. ;-----------------------------------------------------------------
  1368. align 4
  1369. SOCKET_check_port:
  1370.  
  1371.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_port: "
  1372.  
  1373.         pusha
  1374.         mov     ecx, socket_mutex
  1375.         call    mutex_lock
  1376.         popa
  1377.  
  1378.         mov     ecx, [eax + SOCKET.Protocol]
  1379.         mov     edx, [eax + IP_SOCKET.LocalIP]
  1380.         mov     esi, net_sockets
  1381.  
  1382.   .next_socket:
  1383.         mov     esi, [esi + SOCKET.NextPtr]
  1384.         or      esi, esi
  1385.         jz      .port_ok
  1386.  
  1387.         cmp     [esi + SOCKET.Protocol], ecx
  1388.         jne     .next_socket
  1389.  
  1390.         cmp     [esi + IP_SOCKET.LocalIP], edx
  1391.         jne     .next_socket
  1392.  
  1393.         cmp     [esi + UDP_SOCKET.LocalPort], bx
  1394.         jne     .next_socket
  1395.  
  1396.         pusha
  1397.         mov     ecx, socket_mutex
  1398.         call    mutex_unlock
  1399.         popa
  1400.  
  1401.         DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x already in use\n", bx  ; FIXME: find a way to print big endian values with debugf
  1402.         ret
  1403.  
  1404.   .port_ok:
  1405.         pusha
  1406.         mov     ecx, socket_mutex
  1407.         call    mutex_unlock
  1408.         popa
  1409.  
  1410.         DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x is free\n", bx         ; FIXME: find a way to print big endian values with debugf
  1411.         mov     [eax + UDP_SOCKET.LocalPort], bx
  1412.         or      bx, bx                                  ; clear the zero-flag
  1413.         ret
  1414.  
  1415.  
  1416.  
  1417. ;-----------------------------------------------------------------
  1418. ;
  1419. ; SOCKET_input
  1420. ;
  1421. ; Updates a (stateless) socket with received data
  1422. ;
  1423. ; Note: the mutex should already be set !
  1424. ;
  1425. ;  IN:  eax = socket ptr
  1426. ;       ecx = data size
  1427. ;       esi = ptr to data
  1428. ;       [esp] = ptr to buf
  1429. ;       [esp + 4] = buf size
  1430. ;
  1431. ;  OUT: /
  1432. ;
  1433. ;-----------------------------------------------------------------
  1434. align 4
  1435. SOCKET_input:
  1436.  
  1437.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
  1438.  
  1439.         mov     [esp+4], ecx
  1440.         push    esi
  1441.         mov     esi, esp
  1442.  
  1443.         add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full
  1444.  
  1445.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: success\n"
  1446.         add     esp, sizeof.socket_queue_entry
  1447.  
  1448.         pusha
  1449.         lea     ecx, [eax + SOCKET.mutex]
  1450.         call    mutex_unlock
  1451.         popa
  1452.  
  1453.         jmp     SOCKET_notify
  1454.  
  1455.   .full:
  1456.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket %x is full!\n", eax
  1457.  
  1458.         pusha
  1459.         lea     ecx, [eax + SOCKET.mutex]
  1460.         call    mutex_unlock
  1461.         popa
  1462.  
  1463.         call    NET_packet_free
  1464.         add     esp, 8
  1465.  
  1466.         ret
  1467.  
  1468.  
  1469. ;--------------------------
  1470. ;
  1471. ; eax = ptr to ring struct (just a buffer of the right size)
  1472. ;
  1473. align 4
  1474. SOCKET_ring_create:
  1475.  
  1476.         push    esi
  1477.         mov     esi, eax
  1478.  
  1479.         push    edx
  1480.         stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
  1481.         pop     edx
  1482.  
  1483.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_created: %x\n", eax
  1484.  
  1485.         pusha
  1486.         lea     ecx, [esi + RING_BUFFER.mutex]
  1487.         call    mutex_init
  1488.         popa
  1489.  
  1490.         mov     [esi + RING_BUFFER.start_ptr], eax
  1491.         mov     [esi + RING_BUFFER.write_ptr], eax
  1492.         mov     [esi + RING_BUFFER.read_ptr], eax
  1493.         mov     [esi + RING_BUFFER.size], 0
  1494.         add     eax, SOCKET_MAXDATA
  1495.         mov     [esi + RING_BUFFER.end_ptr], eax
  1496.         mov     eax, esi
  1497.         pop     esi
  1498.  
  1499.         ret
  1500.  
  1501. ;-----------------------------------------------------------------
  1502. ;
  1503. ; SOCKET_ring_write
  1504. ;
  1505. ; Adds data to a stream socket, and updates write pointer and size
  1506. ;
  1507. ;  IN:  eax = ptr to ring struct
  1508. ;       ecx = data size
  1509. ;       esi = ptr to data
  1510. ;
  1511. ;  OUT: ecx = number of bytes stored
  1512. ;
  1513. ;-----------------------------------------------------------------
  1514. align 4
  1515. SOCKET_ring_write:
  1516.  
  1517.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
  1518.  
  1519. ; lock mutex
  1520.         pusha
  1521.         lea     ecx, [eax + RING_BUFFER.mutex]
  1522.         call    mutex_lock                                      ; TODO: check what registers this function actually destroys
  1523.         popa
  1524.  
  1525. ; calculate available size
  1526.         mov     edi, SOCKET_MAXDATA
  1527.         sub     edi, [eax + RING_BUFFER.size]                   ; available buffer size in edi
  1528.         cmp     ecx, edi
  1529.         jbe     .copy
  1530.         mov     ecx, edi
  1531.   .copy:
  1532.         mov     edi, [eax + RING_BUFFER.write_ptr]
  1533.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
  1534.  
  1535. ; update write ptr
  1536.         push    edi
  1537.         add     edi, ecx
  1538.         cmp     edi, [eax + RING_BUFFER.end_ptr]
  1539.         jb      @f
  1540.         sub     edi, SOCKET_MAXDATA                             ; WRAP
  1541.   @@:
  1542.         mov     [eax + RING_BUFFER.write_ptr], edi
  1543.         pop     edi
  1544.  
  1545. ; update size
  1546.         add     [eax + RING_BUFFER.size], ecx
  1547.  
  1548. ; copy the data
  1549.         push    ecx
  1550.         shr     ecx, 1
  1551.         jnc     .nb
  1552.         movsb
  1553.   .nb:
  1554.         shr     ecx, 1
  1555.         jnc     .nw
  1556.         movsw
  1557.   .nw:
  1558.         test    ecx, ecx
  1559.         jz      .nd
  1560.         rep movsd
  1561.   .nd:
  1562.         pop     ecx
  1563.  
  1564. ; unlock mutex
  1565.         push    eax ecx
  1566.         lea     ecx, [eax + RING_BUFFER.mutex]
  1567.         call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
  1568.         pop     ecx eax
  1569.  
  1570.         ret
  1571.  
  1572. ;-----------------------------------------------------------------
  1573. ;
  1574. ; SOCKET_ring_read
  1575. ;
  1576. ;  IN:  eax = ring struct ptr
  1577. ;       ecx = bytes to read
  1578. ;       edx = offset
  1579. ;       edi = ptr to buffer start
  1580. ;
  1581. ;  OUT: eax = unchanged
  1582. ;       ecx = number of bytes read (0 on error)
  1583. ;       edx = destroyed
  1584. ;       esi = destroyed
  1585. ;       edi = ptr to buffer end
  1586. ;
  1587. ;-----------------------------------------------------------------
  1588. align 4
  1589. SOCKET_ring_read:
  1590.  
  1591.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
  1592.  
  1593.         pusha
  1594.         lea     ecx, [eax + RING_BUFFER.mutex]
  1595.         call    mutex_lock                                      ; TODO: check what registers this function actually destroys
  1596.         popa
  1597.  
  1598.         mov     esi, [eax + RING_BUFFER.read_ptr]
  1599.         add     esi, edx                                        ; esi = start_ptr + offset
  1600.  
  1601.         neg     edx
  1602.         add     edx, [eax + RING_BUFFER.size]                   ; edx = snd.size - offset
  1603.         jle     .no_data_at_all
  1604.  
  1605.         pusha
  1606.         lea     ecx, [eax + RING_BUFFER.mutex]
  1607.         call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
  1608.         popa
  1609.  
  1610.         cmp     ecx, edx
  1611.         ja      .less_data
  1612.  
  1613.   .copy:
  1614.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
  1615.         push    ecx
  1616.         shr     ecx, 1
  1617.         jnc     .nb
  1618.         movsb
  1619.   .nb:
  1620.         shr     ecx, 1
  1621.         jnc     .nw
  1622.         movsw
  1623.   .nw:
  1624.         test    ecx, ecx
  1625.         jz      .nd
  1626.         rep movsd
  1627.   .nd:
  1628.         pop     ecx
  1629.         ret
  1630.  
  1631.   .no_data_at_all:
  1632.         pusha
  1633.         lea     ecx, [eax + RING_BUFFER.mutex]
  1634.         call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
  1635.         popa
  1636.  
  1637.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: no data at all!\n"
  1638.         xor     ecx, ecx
  1639.         ret
  1640.  
  1641.   .less_data:
  1642.         mov     ecx, edx
  1643.         jmp     .copy
  1644.  
  1645.  
  1646. ;-----------------------------------------------------------------
  1647. ;
  1648. ; SOCKET_ring_free
  1649. ;
  1650. ; Free's some bytes from the ringbuffer
  1651. ;
  1652. ;  IN:  eax = ptr to ring struct
  1653. ;       ecx = data size
  1654. ;
  1655. ;  OUT: ecx = number of bytes free-ed
  1656. ;
  1657. ;-----------------------------------------------------------------
  1658. align 4
  1659. SOCKET_ring_free:
  1660.  
  1661.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
  1662.  
  1663.         push    eax ecx
  1664.         lea     ecx, [eax + RING_BUFFER.mutex]
  1665.         call    mutex_lock                                      ; TODO: check what registers this function actually destroys
  1666.         pop     ecx eax
  1667.  
  1668.         sub     [eax + RING_BUFFER.size], ecx
  1669.         jb      .error
  1670.         add     [eax + RING_BUFFER.read_ptr], ecx
  1671.  
  1672.         mov     edx, [eax + RING_BUFFER.end_ptr]
  1673.         cmp     [eax + RING_BUFFER.read_ptr], edx
  1674.         jb      @f
  1675.         sub     [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA
  1676.        @@:
  1677.  
  1678.         push    eax ecx
  1679.         lea     ecx, [eax + RING_BUFFER.mutex]                  ; TODO: check what registers this function actually destroys
  1680.         call    mutex_unlock
  1681.         pop     ecx eax
  1682.  
  1683.         ret
  1684.  
  1685.   .error:       ; we could free all available bytes, but that would be stupid, i guess..
  1686.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: buffer=%x error!\n", eax
  1687.         add     [eax + RING_BUFFER.size], ecx
  1688.  
  1689.         push    eax
  1690.         lea     ecx, [eax + RING_BUFFER.mutex]
  1691.         call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
  1692.         pop     eax
  1693.  
  1694.         xor     ecx, ecx
  1695.         ret
  1696.  
  1697.  
  1698. ;-----------------------------------------------------------------
  1699. ;
  1700. ; SOCKET_block
  1701. ;
  1702. ; Suspends the thread attached to a socket
  1703. ;
  1704. ;  IN:  eax = socket ptr
  1705. ;  OUT: eax = unchanged
  1706. ;
  1707. ;-----------------------------------------------------------------
  1708. align 4
  1709. SOCKET_block:
  1710.  
  1711.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: %x\n", eax
  1712.  
  1713.         pushf
  1714.         push    eax
  1715.         cli
  1716.  
  1717.         ; Set the 'socket is blocked' flag
  1718.         or      [eax + SOCKET.state], SS_BLOCKED
  1719.  
  1720.         ; Suspend the thread
  1721.         push    edx
  1722.         mov     edx, [TASK_BASE]
  1723.         mov     [edx + TASKDATA.state], 1               ; Suspended
  1724.  
  1725.         ; Remember the thread ID so we can wake it up again
  1726.         mov     edx, [edx + TASKDATA.pid]
  1727.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: suspending thread: %u\n", edx
  1728.         mov     [eax + SOCKET.TID], edx
  1729.         pop     edx
  1730.  
  1731.         call    change_task
  1732.         pop     eax
  1733.         popf
  1734.  
  1735.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: continueing\n"
  1736.  
  1737.         ret
  1738.  
  1739.  
  1740. ;-----------------------------------------------------------------
  1741. ;
  1742. ; SOCKET_notify
  1743. ;
  1744. ; notify's the owner of a socket that something happened
  1745. ;
  1746. ;  IN:  eax = socket ptr
  1747. ;  OUT: eax = unchanged
  1748. ;
  1749. ;-----------------------------------------------------------------
  1750. align 4
  1751. SOCKET_notify:
  1752.  
  1753.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: %x\n", eax
  1754.  
  1755.         call    SOCKET_check
  1756.         jz      .error
  1757.  
  1758.         test    [eax + SOCKET.state], SS_BLOCKED
  1759.         jnz     .unblock
  1760.  
  1761. ;        test    [eax + SOCKET.options], SO_NONBLOCK
  1762. ;        jz      .error
  1763.  
  1764.         push    eax ecx esi
  1765.  
  1766. ; socket exists and is of non blocking type.
  1767. ; We'll try to flag an event to the thread
  1768.  
  1769.         mov     eax, [eax + SOCKET.TID]
  1770.         test    eax, eax
  1771.         jz      .done
  1772.         mov     ecx, 1
  1773.         mov     esi, TASK_DATA + TASKDATA.pid
  1774.  
  1775.   .next_pid:
  1776.         cmp     [esi], eax
  1777.         je      .found_pid
  1778.         inc     ecx
  1779.         add     esi, 0x20
  1780.         cmp     ecx, [TASK_COUNT]
  1781.         jbe     .next_pid
  1782. ; PID not found, TODO: close socket!
  1783.         jmp     .done
  1784.  
  1785.   .found_pid:
  1786.         shl     ecx, 8
  1787.         or      [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
  1788.  
  1789.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: poking thread %u!\n", eax
  1790.         jmp     .done
  1791.  
  1792.   .unblock:
  1793.         push    eax ecx esi
  1794.         ; Clear the 'socket is blocked' flag
  1795.         and     [eax + SOCKET.state], not SS_BLOCKED
  1796.  
  1797.         ; Find the thread's TASK_DATA
  1798.         mov     eax, [eax + SOCKET.TID]
  1799.         test    eax, eax
  1800.         jz      .error
  1801.         xor     ecx, ecx
  1802.         inc     ecx
  1803.         mov     esi, TASK_DATA
  1804.   .next:
  1805.         cmp     [esi + TASKDATA.pid], eax
  1806.         je      .found
  1807.         inc     ecx
  1808.         add     esi, 0x20
  1809.         cmp     ecx, [TASK_COUNT]
  1810.         jbe     .next
  1811.         jmp     .error
  1812.   .found:
  1813.  
  1814.         ; Run the thread
  1815.         mov     [esi + TASKDATA.state], 0       ; Running
  1816.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Unblocked socket!\n"
  1817.  
  1818.   .done:
  1819.         pop     esi ecx eax
  1820.  
  1821.   .error:
  1822.         ret
  1823.  
  1824.  
  1825. ;--------------------------------------------------------------------
  1826. ;
  1827. ; SOCKET_alloc
  1828. ;
  1829. ; Allocate memory for socket data and put new socket into the list
  1830. ; Newly created socket is initialized with calling PID and number and
  1831. ; put into beginning of list (which is a fastest way).
  1832. ;
  1833. ; IN:  /
  1834. ; OUT: eax = 0 on error, socket ptr otherwise
  1835. ;      edi = socket number
  1836. ;       ZF = cleared on error
  1837. ;
  1838. ;--------------------------------------------------------------------
  1839. align 4
  1840. SOCKET_alloc:
  1841.  
  1842.         push    ebx
  1843.  
  1844.         stdcall kernel_alloc, SOCKETBUFFSIZE
  1845.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: ptr=%x\n", eax
  1846.         or      eax, eax
  1847.         jz      .exit
  1848.  
  1849. ; zero-initialize allocated memory
  1850.         push    eax
  1851.         mov     edi, eax
  1852.         mov     ecx, SOCKETBUFFSIZE / 4
  1853.         xor     eax, eax
  1854.         rep stosd
  1855.         pop     eax
  1856.  
  1857. ; set send-and receive procedures to return -1
  1858.         mov     [eax + SOCKET.snd_proc], .not_yet
  1859.         mov     [eax + SOCKET.rcv_proc], .not_yet
  1860.  
  1861.         pusha
  1862.         mov     ecx, socket_mutex
  1863.         call    mutex_lock
  1864.         popa
  1865.  
  1866. ; find first free socket number and use it
  1867.         mov     edi, [last_socket_num]
  1868.   .next_socket_number:
  1869.         inc     edi
  1870.         jz      .next_socket_number     ; avoid socket nr 0
  1871.         cmp     edi, -1
  1872.         je      .next_socket_number     ; avoid socket nr -1
  1873.         mov     ebx, net_sockets
  1874.   .next_socket:
  1875.         mov     ebx, [ebx + SOCKET.NextPtr]
  1876.         test    ebx, ebx
  1877.         jz      .last_socket
  1878.  
  1879.         cmp     [ebx + SOCKET.Number], edi
  1880.         jne     .next_socket
  1881.         jmp     .next_socket_number
  1882.  
  1883.   .last_socket:
  1884.         mov     [last_socket_num], edi
  1885.         mov     [eax + SOCKET.Number], edi
  1886.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: number=%u\n", edi
  1887.  
  1888. ; Fill in PID
  1889.         mov     ebx, [TASK_BASE]
  1890.         mov     ebx, [ebx + TASKDATA.pid]
  1891.         mov     [eax + SOCKET.PID], ebx
  1892.         mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
  1893.  
  1894. ; init mutex
  1895.         pusha
  1896.         lea     ecx, [eax + SOCKET.mutex]
  1897.         call    mutex_init
  1898.         popa
  1899.  
  1900. ; add socket to the list by re-arranging some pointers
  1901.         mov     ebx, [net_sockets + SOCKET.NextPtr]
  1902.  
  1903.         mov     [eax + SOCKET.PrevPtr], net_sockets
  1904.         mov     [eax + SOCKET.NextPtr], ebx
  1905.  
  1906.         test    ebx, ebx
  1907.         jz      @f
  1908.  
  1909.         pusha
  1910.         lea     ecx, [ebx + SOCKET.mutex]
  1911.         call    mutex_lock
  1912.         popa
  1913.  
  1914.         mov     [ebx + SOCKET.PrevPtr], eax
  1915.  
  1916.         pusha
  1917.         lea     ecx, [ebx + SOCKET.mutex]
  1918.         call    mutex_unlock
  1919.         popa
  1920.        @@:
  1921.  
  1922.         mov     [net_sockets + SOCKET.NextPtr], eax
  1923.         or      eax, eax                ; used to clear zero flag
  1924.  
  1925.         pusha
  1926.         mov     ecx, socket_mutex
  1927.         call    mutex_unlock
  1928.         popa
  1929.  
  1930.   .exit:
  1931.         pop     ebx
  1932.  
  1933.         ret
  1934.  
  1935.   .not_yet:
  1936.         mov     dword[esp+20], ENOTCONN
  1937.         mov     dword[esp+32], -1
  1938.         ret
  1939.  
  1940.  
  1941. ;----------------------------------------------------
  1942. ;
  1943. ; SOCKET_free
  1944. ;
  1945. ; Free socket data memory and remove socket from the list
  1946. ; Caller should lock and unlock socket_mutex
  1947. ;
  1948. ; IN:  eax = socket ptr
  1949. ; OUT: /
  1950. ;
  1951. ;----------------------------------------------------
  1952. align 4
  1953. SOCKET_free:
  1954.  
  1955.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: %x\n", eax
  1956.  
  1957.         call    SOCKET_check
  1958.         jz      .error
  1959.  
  1960.         push    ebx
  1961.  
  1962.         pusha
  1963.         lea     ecx, [eax + SOCKET.mutex]
  1964.         call    mutex_lock
  1965.         popa
  1966.  
  1967.         cmp     [eax + SOCKET.Domain], AF_INET4
  1968.         jnz     .no_tcp
  1969.  
  1970.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
  1971.         jnz     .no_tcp
  1972.  
  1973.         mov     ebx, eax
  1974.         stdcall kernel_free, [ebx + STREAM_SOCKET.rcv.start_ptr]
  1975.         stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
  1976.         mov     eax, ebx
  1977.   .no_tcp:
  1978.  
  1979.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: freeing socket %x\n", eax
  1980.         push    eax                             ; this will be passed to kernel_free
  1981.         mov     ebx, [eax + SOCKET.NextPtr]
  1982.         mov     eax, [eax + SOCKET.PrevPtr]
  1983.  
  1984.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
  1985.  
  1986.         test    eax, eax
  1987.         jz      @f
  1988.         mov     [eax + SOCKET.NextPtr], ebx
  1989.        @@:
  1990.  
  1991.         test    ebx, ebx
  1992.         jz      @f
  1993.         mov     [ebx + SOCKET.PrevPtr], eax
  1994.        @@:
  1995.  
  1996.         call    kernel_free
  1997.         pop     ebx
  1998.  
  1999.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: success!\n"
  2000.  
  2001.   .error:
  2002.         ret
  2003.  
  2004. ;------------------------------------
  2005. ;
  2006. ; SOCKET_fork
  2007. ;
  2008. ; Create a child socket
  2009. ;
  2010. ; IN:  socket nr in ebx
  2011. ; OUT: child socket nr in eax
  2012. ;
  2013. ;-----------------------------------
  2014. align 4
  2015. SOCKET_fork:
  2016.  
  2017.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_fork: %x\n", ebx
  2018.  
  2019. ; Exit if backlog queue is full
  2020.         mov     eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
  2021.         cmp     ax, [ebx + SOCKET.backlog]
  2022.         jae     .fail
  2023.  
  2024. ; Allocate new socket
  2025.         push    ebx
  2026.         call    SOCKET_alloc
  2027.         pop     ebx
  2028.         jz      .fail
  2029.  
  2030.         push    eax
  2031.         mov     esi, esp
  2032.         add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2
  2033.         pop     eax
  2034.  
  2035. ; Copy structure from current socket to new
  2036. ; We start at PID to preserve the socket num, 2 pointers and mutex
  2037. ; TID will be filled in later
  2038.         lea     esi, [ebx + SOCKET.PID]
  2039.         lea     edi, [eax + SOCKET.PID]
  2040.         mov     ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
  2041.         rep movsd
  2042.  
  2043.         and     [eax + SOCKET.options], not SO_ACCEPTCON
  2044.  
  2045. ; Notify owner of parent socket
  2046.         push    eax
  2047.         mov     eax, ebx
  2048.         call    SOCKET_notify
  2049.         pop     eax
  2050.  
  2051.         ret
  2052.  
  2053.   .fail2:
  2054.         add     esp, 4+4+4
  2055.   .fail:
  2056.         DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_fork: failed\n"
  2057.         xor     eax, eax
  2058.         ret
  2059.  
  2060.  
  2061. ;---------------------------------------------------
  2062. ;
  2063. ; SOCKET_num_to_ptr
  2064. ;
  2065. ; Get socket structure address by its number
  2066. ;
  2067. ; IN:  ecx = socket number
  2068. ; OUT: eax = 0 on error, socket ptr otherwise
  2069. ;       ZF = set on error
  2070. ;
  2071. ;---------------------------------------------------
  2072. align 4
  2073. SOCKET_num_to_ptr:
  2074.  
  2075.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_num_to_ptr: num=%u ", ecx
  2076.  
  2077.         pusha
  2078.         mov     ecx, socket_mutex
  2079.         call    mutex_lock
  2080.         popa
  2081.  
  2082.         mov     eax, net_sockets
  2083.  
  2084.   .next_socket:
  2085.         mov     eax, [eax + SOCKET.NextPtr]
  2086.         or      eax, eax
  2087.         jz      .error
  2088.                 diff16 "tetten", 0, $
  2089.         cmp     [eax + SOCKET.Number], ecx
  2090.         jne     .next_socket
  2091.  
  2092.         test    eax, eax
  2093.  
  2094.         pusha
  2095.         mov     ecx, socket_mutex
  2096.         call    mutex_unlock
  2097.         popa
  2098.  
  2099.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ptr=%x\n", eax
  2100.         ret
  2101.  
  2102.   .error:
  2103.         pusha
  2104.         mov     ecx, socket_mutex
  2105.         call    mutex_unlock
  2106.         popa
  2107.  
  2108.         DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_num_to_ptr: not found\n", eax
  2109.         ret
  2110.  
  2111.  
  2112. ;---------------------------------------------------
  2113. ;
  2114. ; SOCKET_ptr_to_num
  2115. ;
  2116. ; Get socket number by its address
  2117. ;
  2118. ; IN:  eax = socket ptr
  2119. ; OUT: eax = 0 on error, socket num otherwise
  2120. ;       ZF = set on error
  2121. ;
  2122. ;---------------------------------------------------
  2123. align 4
  2124. SOCKET_ptr_to_num:
  2125.  
  2126.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ptr_to_num: ptr=%x ", eax
  2127.  
  2128.         call    SOCKET_check
  2129.         jz      .error
  2130.  
  2131.         mov     eax, [eax + SOCKET.Number]
  2132.  
  2133.         DEBUGF  DEBUG_NETWORK_VERBOSE, "num=%u\n", eax
  2134.         ret
  2135.  
  2136.   .error:
  2137.         DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_ptr_to_num: not found\n", eax
  2138.         ret
  2139.  
  2140.  
  2141. ;---------------------------------------------------
  2142. ;
  2143. ; SOCKET_check
  2144. ;
  2145. ; checks if the given value is really a socket ptr
  2146. ;
  2147. ; IN:  eax = socket ptr
  2148. ; OUT: eax = 0 on error, unchanged otherwise
  2149. ;       ZF = set on error
  2150. ;
  2151. ;---------------------------------------------------
  2152. align 4
  2153. SOCKET_check:
  2154.  
  2155.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check: %x\n", eax
  2156.  
  2157.         push    ebx
  2158.         mov     ebx, net_sockets
  2159.  
  2160.   .next_socket:
  2161.         mov     ebx, [ebx + SOCKET.NextPtr]
  2162.         or      ebx, ebx
  2163.         jz      .done
  2164.         cmp     ebx, eax
  2165.         jnz     .next_socket
  2166.  
  2167.   .done:
  2168.         mov     eax, ebx
  2169.         test    eax, eax
  2170.         pop     ebx
  2171.  
  2172.         ret
  2173.  
  2174.  
  2175.  
  2176. ;---------------------------------------------------
  2177. ;
  2178. ; SOCKET_check_owner
  2179. ;
  2180. ; checks if the caller application owns the socket
  2181. ;
  2182. ; IN:  eax = socket ptr
  2183. ; OUT:  ZF = true/false
  2184. ;
  2185. ;---------------------------------------------------
  2186. align 4
  2187. SOCKET_check_owner:
  2188.  
  2189.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_owner: %x\n", eax
  2190.  
  2191.         push    ebx
  2192.         mov     ebx, [TASK_BASE]
  2193.         mov     ebx, [ebx + TASKDATA.pid]
  2194.         cmp     [eax + SOCKET.PID], ebx
  2195.         pop     ebx
  2196.  
  2197.         ret
  2198.  
  2199.  
  2200.  
  2201.  
  2202. ;------------------------------------------------------
  2203. ;
  2204. ; SOCKET_process_end
  2205. ;
  2206. ; Kernel calls this function when a certain process ends
  2207. ; This function will check if the process had any open sockets
  2208. ; And update them accordingly
  2209. ;
  2210. ; IN:  edx = pid
  2211. ; OUT: /
  2212. ;
  2213. ;------------------------------------------------------
  2214. align 4
  2215. SOCKET_process_end:
  2216.  
  2217.         cmp     [net_sockets + SOCKET.NextPtr], 0       ; Are there any active sockets at all?
  2218.         je      .quickret                               ; nope, exit immediately
  2219.  
  2220. ; TODO: run the following code in another thread, to avoid deadlock
  2221.  
  2222.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: %x\n", edx
  2223.  
  2224.         pusha
  2225.         mov     ecx, socket_mutex
  2226.         call    mutex_lock
  2227.         popa
  2228.  
  2229.         push    ebx
  2230.         mov     ebx, net_sockets
  2231.  
  2232.   .next_socket:
  2233.         mov     ebx, [ebx + SOCKET.NextPtr]
  2234.   .next_socket_test:
  2235.         test    ebx, ebx
  2236.         jz      .done
  2237.  
  2238.         cmp     [ebx + SOCKET.PID], edx
  2239.         jne     .next_socket
  2240.  
  2241.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: killing socket %x\n", ebx
  2242.  
  2243.         mov     [ebx + SOCKET.PID], 0
  2244.         mov     eax, ebx
  2245.         mov     ebx, [ebx + SOCKET.NextPtr]
  2246.  
  2247.         pusha
  2248.         cmp     [eax + SOCKET.Domain], AF_INET4
  2249.         jne     .free
  2250.  
  2251.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
  2252.         jne     .free
  2253.  
  2254.         call    TCP_close
  2255.         jmp     .closed
  2256.  
  2257.   .free:
  2258.         call    SOCKET_free
  2259.  
  2260.   .closed:
  2261.         popa
  2262.         jmp     .next_socket_test
  2263.  
  2264.   .done:
  2265.         pop     ebx
  2266.  
  2267.         pusha
  2268.         mov     ecx, socket_mutex
  2269.         call    mutex_unlock
  2270.         popa
  2271.  
  2272.   .quickret:
  2273.         ret
  2274.  
  2275.  
  2276.  
  2277.  
  2278. ;-----------------------------------------------------------------
  2279. ;
  2280. ; SOCKET_is_connecting
  2281. ;
  2282. ;  IN:  eax = socket ptr
  2283. ;  OUT: /
  2284. ;
  2285. ;-----------------------------------------------------------------
  2286.  
  2287. align 4
  2288. SOCKET_is_connecting:
  2289.  
  2290.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connecting: %x\n", eax
  2291.  
  2292.         and     [eax + SOCKET.state], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
  2293.         or      [eax + SOCKET.state], SS_ISCONNECTING
  2294.  
  2295.         ret
  2296.  
  2297.  
  2298.  
  2299. ;-----------------------------------------------------------------
  2300. ;
  2301. ; SOCKET_is_connected
  2302. ;
  2303. ;  IN:  eax = socket ptr
  2304. ;  OUT: /
  2305. ;
  2306. ;-----------------------------------------------------------------
  2307.  
  2308. align 4
  2309. SOCKET_is_connected:
  2310.  
  2311.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connected: %x\n", eax
  2312.  
  2313.         and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
  2314.         or      [eax + SOCKET.state], SS_ISCONNECTED
  2315.  
  2316.         jmp     SOCKET_notify
  2317.  
  2318.  
  2319.  
  2320.  
  2321. ;-----------------------------------------------------------------
  2322. ;
  2323. ; SOCKET_is_disconnecting
  2324. ;
  2325. ;  IN:  eax = socket ptr
  2326. ;  OUT: /
  2327. ;
  2328. ;-----------------------------------------------------------------
  2329.  
  2330. align 4
  2331. SOCKET_is_disconnecting:
  2332.  
  2333.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnecting: %x\n", eax
  2334.  
  2335.         and     [eax + SOCKET.state], not (SS_ISCONNECTING)
  2336.         or      [eax + SOCKET.state], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
  2337.  
  2338.         jmp     SOCKET_notify
  2339.  
  2340.  
  2341.  
  2342. ;-----------------------------------------------------------------
  2343. ;
  2344. ; SOCKET_is_disconnected
  2345. ;
  2346. ;  IN:  eax = socket ptr
  2347. ;  OUT: /
  2348. ;
  2349. ;-----------------------------------------------------------------
  2350.  
  2351. align 4
  2352. SOCKET_is_disconnected:
  2353.  
  2354.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnected: %x\n", eax
  2355.  
  2356.         and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
  2357.         or      [eax + SOCKET.state], SS_CANTRCVMORE + SS_CANTSENDMORE
  2358.  
  2359.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
  2360.         je      .tcp
  2361.  
  2362.         cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
  2363.         je      .udp
  2364.  
  2365.         jmp     SOCKET_notify
  2366.  
  2367.   .tcp:
  2368.   .udp:
  2369.         mov     [eax + UDP_SOCKET.LocalPort], 0         ; UDP and TCP structs store localport at the same offset
  2370.         mov     [eax + UDP_SOCKET.RemotePort], 0
  2371.  
  2372.         jmp     SOCKET_notify
  2373.  
  2374.  
  2375. ;-----------------------------------------------------------------
  2376. ;
  2377. ; SOCKET_cant_recv_more
  2378. ;
  2379. ;  IN:  eax = socket ptr
  2380. ;  OUT: /
  2381. ;
  2382. ;-----------------------------------------------------------------
  2383.  
  2384. align 4
  2385. SOCKET_cant_recv_more:
  2386.  
  2387.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_recv_more: %x\n", eax
  2388.  
  2389.         or      [eax + SOCKET.state], SS_CANTRCVMORE
  2390.  
  2391.         call    SOCKET_notify
  2392.  
  2393.         ret
  2394.  
  2395.  
  2396.  
  2397. ;-----------------------------------------------------------------
  2398. ;
  2399. ; SOCKET_cant_send_more
  2400. ;
  2401. ;  IN:  eax = socket ptr
  2402. ;  OUT: /
  2403. ;
  2404. ;-----------------------------------------------------------------
  2405.  
  2406. align 4
  2407. SOCKET_cant_send_more:
  2408.  
  2409.         DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_send_more: %x\n", eax
  2410.  
  2411.         or      [eax + SOCKET.state], SS_CANTSENDMORE
  2412.         mov     [eax + SOCKET.snd_proc], .notconn
  2413.  
  2414.         call    SOCKET_notify
  2415.  
  2416.         ret
  2417.  
  2418.   .notconn:
  2419.         mov     dword[esp+20], ENOTCONN
  2420.         mov     dword[esp+32], -1
  2421.         ret