Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2011. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;    Written by hidnplayr@kolibrios.org,                          ;;
  7. ;;     and Clevermouse.                                            ;;
  8. ;;                                                                 ;;
  9. ;;       Based on code by mike.dld                                 ;;
  10. ;;                                                                 ;;
  11. ;;         GNU GENERAL PUBLIC LICENSE                              ;;
  12. ;;          Version 2, June 1991                                   ;;
  13. ;;                                                                 ;;
  14. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  15.  
  16. $Revision: 2302 $
  17.  
  18.  
  19. virtual at 0
  20.  
  21.         SOCKET:
  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.         .lock                   dd ? ; lock mutex
  27.  
  28.         .PID                    dd ? ; application process id
  29.         .Domain                 dd ? ; INET/UNIX/..
  30.         .Type                   dd ? ; RAW/STREAM/DGRAP
  31.         .Protocol               dd ? ; ICMP/IPv4/ARP/TCP/UDP
  32.         .errorcode              dd ?
  33.  
  34.         .options                dd ?
  35.         .state                  dd ?
  36.         .backlog                dw ? ; how many incomming connections that can be queued
  37.  
  38.         .snd_proc               dd ?
  39.         .rcv_proc               dd ?
  40.  
  41.         .end:
  42. end virtual
  43.  
  44. virtual at SOCKET.end
  45.  
  46.         IP_SOCKET:
  47.         .LocalIP                rd 4
  48.         .RemoteIP               rd 4
  49.  
  50.         .end:
  51. end virtual
  52.  
  53. virtual at IP_SOCKET.end
  54.  
  55.         TCP_SOCKET:
  56.  
  57.         .LocalPort              dw ?
  58.         .RemotePort             dw ?
  59.  
  60.         .t_state                dd ? ; TCB state
  61.         .t_rxtshift             dd ?
  62.         .t_rxtcur               dd ?
  63.         .t_dupacks              dd ?
  64.         .t_maxseg               dd ?
  65.         .t_force                dd ?
  66.         .t_flags                dd ?
  67.  
  68. ;---------------
  69. ; RFC783 page 21
  70.  
  71. ; send sequence
  72.         .SND_UNA                dd ? ; sequence number of unack'ed sent Packets
  73.         .SND_NXT                dd ? ; next send sequence number to use
  74.         .SND_UP                 dd ?
  75.         .SND_WL1                dd ? ; window minus one
  76.         .SND_WL2                dd ? ;
  77.         .ISS                    dd ? ; initial send sequence number
  78.         .SND_WND                dd ? ; send window
  79.  
  80. ; receive sequence
  81.         .RCV_WND                dw ? ; receive window
  82.         .RCV_NXT                dd ? ; next receive sequence number to use
  83.         .RCV_UP                 dd ?
  84.         .IRS                    dd ? ; initial receive sequence number
  85.  
  86. ;---------------------
  87. ; Additional variables
  88.  
  89. ; receive variables
  90.         .RCV_ADV                dd ?
  91.  
  92. ; retransmit variables
  93.         .SND_MAX                dd ?
  94.  
  95. ; congestion control
  96.         .SND_CWND               dd ?
  97.         .SND_SSTHRESH           dd ?
  98.  
  99. ;----------------------
  100. ; Transmit timing stuff
  101.         .t_idle                 dd ?
  102.         .t_rtt                  dd ?
  103.         .t_rtseq                dd ?
  104.         .t_srtt                 dd ?
  105.         .t_rttvar               dd ?
  106.         .t_rttmin               dd ?
  107.         .max_sndwnd             dd ?
  108.  
  109. ;-----------------
  110. ; Out-of-band data
  111.         .t_oobflags             dd ?
  112.         .t_iobc                 dd ?
  113.         .t_softerror            dd ?
  114.  
  115.  
  116. ;---------
  117. ; RFC 1323
  118.         .SND_SCALE              db ? ; Scale factor
  119.         .RCV_SCALE              db ?
  120.         .request_r_scale        db ?
  121.         .requested_s_scale      dd ?
  122.  
  123.         .ts_recent              dd ?
  124.         .ts_recent_age          dd ?
  125.         .last_ack_sent          dd ?
  126.  
  127.  
  128. ;-------
  129. ; Timers
  130.         .timer_retransmission   dw ? ; rexmt
  131.         .timer_persist          dw ?
  132.         .timer_keepalive        dw ? ; keepalive/syn timeout
  133.         .timer_timed_wait       dw ? ; also used as 2msl timer
  134.  
  135.         .end:
  136. end virtual
  137.  
  138. virtual at IP_SOCKET.end
  139.  
  140.         UDP_SOCKET:
  141.  
  142.         .LocalPort              dw ?
  143.         .RemotePort             dw ?
  144.         .firstpacket            db ?
  145.  
  146.         .end:
  147. end virtual
  148.  
  149. virtual at IP_SOCKET.end
  150.  
  151.         ICMP_SOCKET:
  152.  
  153.         .Identifier             dw ?
  154.  
  155.         .end:
  156. end virtual
  157.  
  158. struc   RING_BUFFER {
  159.         .start_ptr              dd ? ; Pointer to start of buffer
  160.         .end_ptr                dd ? ; pointer to end of buffer
  161.         .read_ptr               dd ? ; Read pointer
  162.         .write_ptr              dd ? ; Write pointer
  163.         .size                   dd ? ; Number of bytes buffered
  164.         .end:
  165. }
  166.  
  167. virtual at 0
  168.  
  169.         RING_BUFFER     RING_BUFFER
  170.  
  171. end virtual
  172.  
  173. virtual at TCP_SOCKET.end
  174.  
  175.  STREAM_SOCKET:
  176.         .rcv    rd     RING_BUFFER.end/4
  177.         .snd    rd     RING_BUFFER.end/4
  178.         .end:
  179.  
  180. end virtual
  181.  
  182. struct  socket_queue_entry
  183.         .data_ptr       dd ?
  184.         .buf_ptr        dd ?
  185.         .data_size      dd ?
  186.         .size:
  187. ends
  188.  
  189.  
  190. SOCKETBUFFSIZE          equ 4096     ; in bytes
  191.  
  192. SOCKET_QUEUE_SIZE       equ 10       ; maximum number ofincoming packets queued for 1 socket
  193. ; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
  194. SOCKET_QUEUE_LOCATION   equ (SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*socket_queue_entry.size - queue.data)
  195.  
  196. uglobal
  197.         net_sockets     rd 4
  198.         last_socket_num dd ?
  199.         last_UDP_port   dw ? ; These values give the number of the last used ephemeral port
  200.         last_TCP_port   dw ? ;
  201. endg
  202.  
  203.  
  204. ;-----------------------------------------------------------------
  205. ;
  206. ; SOCKET_init
  207. ;
  208. ;-----------------------------------------------------------------
  209. macro   SOCKET_init {
  210.  
  211.         xor     eax, eax
  212.         mov     edi, net_sockets
  213.         mov     ecx, 5
  214.         rep     stosd
  215.  
  216.        @@:
  217.         pseudo_random eax
  218.         cmp     ax, MIN_EPHEMERAL_PORT
  219.         jb      @r
  220.         cmp     ax, MAX_EPHEMERAL_PORT
  221.         ja      @r
  222.         mov     [last_UDP_port], ax
  223.  
  224.        @@:
  225.         pseudo_random eax
  226.         cmp     ax, MIN_EPHEMERAL_PORT
  227.         jb      @r
  228.         cmp     ax, MAX_EPHEMERAL_PORT
  229.         ja      @r
  230.         mov     [last_TCP_port], ax
  231.  
  232. }
  233.  
  234.  
  235. ;-----------------------------------------------------------------
  236. ;
  237. ; Socket API (function 74)
  238. ;
  239. ;-----------------------------------------------------------------
  240. align 16
  241. sock_sysfn_table:
  242.         dd      SOCKET_open     ; 0
  243.         dd      SOCKET_close    ; 1
  244.         dd      SOCKET_bind     ; 2
  245.         dd      SOCKET_listen   ; 3
  246.         dd      SOCKET_connect  ; 4
  247.         dd      SOCKET_accept   ; 5
  248.         dd      SOCKET_send     ; 6
  249.         dd      SOCKET_receive  ; 7
  250.         dd      SOCKET_set_opt  ; 8
  251.         dd      SOCKET_get_opt  ; 9
  252.  
  253. SOCKET_SYSFUNCS = ($ - sock_sysfn_table)/4
  254.  
  255.  
  256. align 4
  257. sys_socket:
  258.         cmp     ebx, SOCKET_SYSFUNCS-1
  259.         ja      @f
  260.         jmp     dword [sock_sysfn_table + 4*ebx]
  261.        @@:
  262.         cmp     ebx, 255
  263.         jz      SOCKET_debug
  264.  
  265. s_error:
  266.         DEBUGF  1,"socket error\n"
  267.         mov     dword [esp+32], -1
  268.  
  269.         ret
  270.  
  271.  
  272.  
  273. ;-----------------------------------------------------------------
  274. ;
  275. ; SOCKET_open
  276. ;
  277. ;  IN:  domain in ecx
  278. ;       type in edx
  279. ;       protocol in esi
  280. ;  OUT: eax is socket num, -1 on error
  281. ;
  282. ;-----------------------------------------------------------------
  283. align 4
  284. SOCKET_open:
  285.  
  286.         DEBUGF  1,"SOCKET_open: domain: %u, type: %u protocol: %x\n", ecx, edx, esi
  287.  
  288.         call    SOCKET_alloc
  289.         jz      s_error
  290.  
  291.         mov     [esp+32], edi                   ; return socketnumber
  292.  
  293.         mov     [eax + SOCKET.Domain], ecx
  294.         mov     [eax + SOCKET.Type], edx
  295.         mov     [eax + SOCKET.Protocol], esi
  296.  
  297.         cmp     ecx, AF_INET4
  298.         jne     .no_inet4
  299.  
  300.         cmp     edx, SOCK_DGRAM
  301.         je      .udp
  302.  
  303.         cmp     edx, SOCK_STREAM
  304.         je      .tcp
  305.  
  306.         cmp     edx, SOCK_RAW
  307.         je      .raw
  308.  
  309.   .no_inet4:
  310.         ret
  311.  
  312. align 4
  313.   .raw:
  314.         test    esi, esi       ; IP_PROTO_IP
  315.         jz      .ip
  316.  
  317.         cmp     esi, IP_PROTO_ICMP
  318.         je      .icmp
  319.  
  320.         cmp     esi, IP_PROTO_UDP
  321.         je      .udp
  322.  
  323.         cmp     esi, IP_PROTO_TCP
  324.         je      .tcp
  325.  
  326.         ret
  327.  
  328. align 4
  329.   .udp:
  330.         mov     [eax + SOCKET.Protocol], IP_PROTO_UDP
  331.         mov     [eax + SOCKET.snd_proc], SOCKET_send_udp
  332.         mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
  333.         ret
  334.  
  335. align 4
  336.   .tcp:
  337.         mov     [eax + SOCKET.Protocol], IP_PROTO_TCP
  338.         mov     [eax + SOCKET.snd_proc], SOCKET_send_tcp
  339.         mov     [eax + SOCKET.rcv_proc], SOCKET_receive_tcp
  340.  
  341.  
  342.         mov     [eax + TCP_SOCKET.t_maxseg], 1480       ;;;;; FIXME
  343.         ret
  344.  
  345.  
  346. align 4
  347.   .ip:
  348.         mov     [eax + SOCKET.snd_proc], SOCKET_send_ip
  349.         mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
  350.         ret
  351.  
  352.  
  353. align 4
  354.   .icmp:
  355.         mov     [eax + SOCKET.snd_proc], SOCKET_send_icmp
  356.         mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
  357.         ret
  358.  
  359.  
  360.  
  361. ;-----------------------------------------------------------------
  362. ;
  363. ; SOCKET_bind
  364. ;
  365. ;  IN:  socket number in ecx
  366. ;       pointer to sockaddr struct in edx
  367. ;       length of that struct in esi
  368. ;  OUT: 0 on success
  369. ;
  370. ;-----------------------------------------------------------------
  371. align 4
  372. SOCKET_bind:
  373.  
  374.         DEBUGF  1,"socket_bind: socknum: %u sockaddr: %x, length: %u\n", ecx, edx, esi
  375.  
  376.         call    SOCKET_num_to_ptr
  377.         jz      s_error
  378.  
  379.         cmp     esi, 2
  380.         jb      s_error
  381.  
  382.         cmp     word [edx], AF_INET4
  383.         je      .af_inet4
  384.  
  385.         cmp     word [edx], AF_UNIX
  386.         je      .af_unix
  387.  
  388.         jmp     s_error
  389.  
  390.   .af_unix:
  391.         ; TODO: write code here
  392.  
  393.         mov     dword [esp+32], 0
  394.         ret
  395.  
  396.   .af_inet4:
  397.  
  398.         DEBUGF  1,"af_inet4\n"
  399.  
  400.         cmp     esi, 6
  401.         jb      s_error
  402.  
  403.         pushw   [edx + 2]
  404.         pop     [eax + UDP_SOCKET.LocalPort]
  405.  
  406.         pushd   [edx + 4]
  407.         pop     [eax + IP_SOCKET.LocalIP]
  408.  
  409.         DEBUGF  1,"local ip: %u.%u.%u.%u\n",\
  410.         [eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
  411.         [eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
  412.  
  413.         mov     dword [esp+32], 0
  414.         ret
  415.  
  416.  
  417.  
  418.  
  419. ;-----------------------------------------------------------------
  420. ;
  421. ; SOCKET_connect
  422. ;
  423. ;  IN:  socket number in ecx
  424. ;       pointer to sockaddr struct in edx
  425. ;       length of that struct in esi
  426. ;  OUT: 0 on success
  427. ;
  428. ;-----------------------------------------------------------------
  429. align 4
  430. SOCKET_connect:
  431.  
  432.         DEBUGF  1,"SOCKET_connect: socknum: %u sockaddr: %x, length: %u\n", ecx, edx, esi
  433.  
  434.         call    SOCKET_num_to_ptr
  435.         jz      s_error
  436.  
  437.         cmp     esi, 8
  438.         jb      s_error
  439.  
  440.         cmp     word [edx], AF_INET4
  441.         je      .af_inet4
  442.  
  443.         jmp     s_error
  444.  
  445.   .af_inet4:
  446.         cmp     [eax + IP_SOCKET.LocalIP], 0
  447.         jne     @f
  448.         push    [IP_LIST]
  449.         pop     [eax + IP_SOCKET.LocalIP]
  450.        @@:
  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.         cmp     [eax + SOCKET.Protocol], IP_PROTO_IP
  459.         je      .ip
  460.  
  461.         cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
  462.         je      .ip
  463.  
  464.         jmp     s_error
  465.  
  466. align 4
  467.   .udp:
  468.         lea     ebx, [eax + SOCKET.lock]
  469.         call    wait_mutex
  470.  
  471.         pushw   [edx + 2]
  472.         pop     [eax + UDP_SOCKET.RemotePort]
  473.  
  474.         pushd   [edx + 4]
  475.         pop     [eax + IP_SOCKET.RemoteIP]
  476.  
  477.         cmp     [eax + UDP_SOCKET.LocalPort], 0
  478.         jne     @f
  479.         call    SOCKET_find_port
  480.        @@:
  481.  
  482.         mov     [eax + UDP_SOCKET.firstpacket], 0
  483.  
  484.         push    eax
  485.         init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
  486.         pop     eax
  487.  
  488.         mov     [eax + SOCKET.lock], 0
  489.         mov     dword [esp+32], 0
  490.         ret
  491.  
  492. align 4
  493.   .tcp:
  494.         lea     ebx, [eax + SOCKET.lock]
  495.         call    wait_mutex
  496.  
  497.         pushw   [edx + 2]
  498.         pop     [eax + TCP_SOCKET.RemotePort]
  499.  
  500.         pushd   [edx + 4]
  501.         pop     [eax + IP_SOCKET.RemoteIP]
  502.  
  503.         cmp     [eax + TCP_SOCKET.LocalPort], 0
  504.         jne     @f
  505.         call    SOCKET_find_port
  506.        @@:
  507.  
  508.         mov     [eax + TCP_SOCKET.timer_persist], 0
  509.         mov     [eax + TCP_SOCKET.t_state], TCPS_SYN_SENT
  510.         push    [TCP_sequence_num]
  511.         add     [TCP_sequence_num], 6400
  512.         pop     [eax + TCP_SOCKET.ISS]
  513.         mov     [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init
  514.  
  515.         TCP_sendseqinit eax
  516.  
  517. ;        mov     [ebx + TCP_SOCKET.timer_retransmission],   ;; todo: create macro to set retransmission timer
  518.  
  519.         mov     ebx, eax
  520.  
  521.         lea     eax, [ebx + STREAM_SOCKET.snd]
  522.         call    SOCKET_ring_create
  523.  
  524.         lea     eax, [ebx + STREAM_SOCKET.rcv]
  525.         call    SOCKET_ring_create
  526.  
  527.         mov     [ebx + SOCKET.lock], 0
  528.  
  529.         mov     eax, ebx
  530.         call    TCP_output
  531.  
  532.         mov     dword [esp+32], 0
  533.         ret
  534.  
  535. align 4
  536.   .ip:
  537.         lea     ebx, [eax + SOCKET.lock]
  538.         call    wait_mutex
  539.  
  540.         pushd   [edx + 4]
  541.         pop     [eax + IP_SOCKET.RemoteIP]
  542.  
  543.         push    eax
  544.         init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
  545.         pop     eax
  546.  
  547.         mov     [eax + SOCKET.lock], 0
  548.         mov     dword [esp+32], 0
  549.         ret
  550.  
  551.  
  552. ;-----------------------------------------------------------------
  553. ;
  554. ; SOCKET_listen
  555. ;
  556. ;  IN:  socket number in ecx
  557. ;       backlog in edx
  558. ;  OUT: eax is socket num, -1 on error
  559. ;
  560. ;-----------------------------------------------------------------
  561. align 4
  562. SOCKET_listen:
  563.  
  564.         DEBUGF  1,"SOCKET_listen: socknum: %u backlog: %u\n", ecx, edx
  565.  
  566.         call    SOCKET_num_to_ptr
  567.         jz      s_error
  568.  
  569.         cmp     [eax + SOCKET.Domain], AF_INET4
  570.         jne     s_error
  571.  
  572.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
  573.         jne     s_error
  574.  
  575.         cmp     [eax + TCP_SOCKET.LocalPort], 0
  576.         je      s_error
  577.  
  578.         cmp     [eax + IP_SOCKET.LocalIP], 0
  579.         jne     @f
  580.         push    [IP_LIST]
  581.         pop     [eax + IP_SOCKET.LocalIP]
  582.        @@:
  583.  
  584.         cmp     edx, MAX_backlog
  585.         jbe     @f
  586.         mov     edx, MAX_backlog
  587.        @@:
  588.  
  589.         mov     [eax + SOCKET.backlog], dx
  590.         or      [eax + SOCKET.options], SO_ACCEPTCON
  591.         mov     [eax + TCP_SOCKET.t_state], TCPS_LISTEN
  592.  
  593.         push    eax
  594.         init_queue (eax + SOCKET_QUEUE_LOCATION)                ; Set up sockets queue
  595.         pop     eax
  596.  
  597.         mov     dword [esp+32], 0
  598.  
  599.         ret
  600.  
  601.  
  602. ;-----------------------------------------------------------------
  603. ;
  604. ; SOCKET_accept
  605. ;
  606. ;  IN:  socket number in ecx
  607. ;       addr in edx
  608. ;       addrlen in esi
  609. ;  OUT: eax is socket num, -1 on error
  610. ;
  611. ;-----------------------------------------------------------------
  612. align 4
  613. SOCKET_accept:
  614.  
  615.         DEBUGF  1,"SOCKET_accept: socknum: %u sockaddr: %x, length: %u\n", ecx, edx, esi
  616.  
  617.         call    SOCKET_num_to_ptr
  618.         jz      s_error
  619.  
  620.         test    [eax + SOCKET.options], SO_ACCEPTCON
  621.         jz      s_error
  622.  
  623.         cmp     [eax + SOCKET.Domain], AF_INET4
  624.         jne     s_error
  625.  
  626.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
  627.         jne     s_error
  628.  
  629.         get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, s_error
  630.  
  631.         mov     eax, [esi]
  632.         call    SOCKET_ptr_to_num
  633.         jz      s_error
  634.         mov     dword [esp+32], eax
  635.         ret
  636.  
  637.  
  638. ;-----------------------------------------------------------------
  639. ;
  640. ; SOCKET_close
  641. ;
  642. ;  IN:  socket number in ecx
  643. ;  OUT: eax is socket num, -1 on error
  644. ;
  645. ;-----------------------------------------------------------------
  646. align 4
  647. SOCKET_close:
  648.  
  649.         DEBUGF  1,"SOCKET_close: socknum: %u\n", ecx
  650.  
  651.         call    SOCKET_num_to_ptr
  652.         jz      s_error
  653.  
  654.         cmp     [eax + SOCKET.Domain], AF_INET4
  655.         jne     s_error
  656.  
  657.         cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
  658.         je      .free
  659.  
  660.         cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
  661.         je      .free
  662.  
  663.         cmp     [eax + SOCKET.Protocol], IP_PROTO_IP
  664.         je      .free
  665.  
  666.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
  667.         je      .tcp
  668.  
  669.         jmp     s_error
  670.  
  671.   .tcp:
  672.         cmp     [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED    ; state must be LISTEN, SYN_SENT or CLOSED
  673.         jb      .free
  674.  
  675.         call    TCP_output
  676.         mov     dword [esp+32], 0
  677.  
  678.         ret
  679.  
  680.   .free:
  681.         call    SOCKET_free
  682.         mov     dword [esp+32], 0
  683.  
  684.         ret
  685.  
  686.  
  687. ;-----------------------------------------------------------------
  688. ;
  689. ; SOCKET_receive
  690. ;
  691. ;  IN:  socket number in ecx
  692. ;       addr to buffer in edx
  693. ;       length of buffer in esi
  694. ;       flags in edi
  695. ;  OUT: eax is number of bytes copied, -1 on error
  696. ;
  697. ;-----------------------------------------------------------------
  698. align 4
  699. SOCKET_receive:
  700.  
  701.         DEBUGF  1,"SOCKET_receive: socknum: %u bufaddr: %x, buflength: %u, flags: %x, ", ecx, edx, esi, edi
  702.  
  703.         call    SOCKET_num_to_ptr
  704.         jz      s_error
  705.  
  706.         jmp     [eax + SOCKET.rcv_proc]
  707.  
  708.  
  709. align 4
  710. SOCKET_receive_dgram:
  711.  
  712.         DEBUGF  1,"SOCKET_receive: DGRAM\n"
  713.  
  714.         mov     ebx, esi
  715.         mov     edi, edx                                        ; addr to buffer
  716.  
  717.         get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, socket_queue_entry.size, s_error       ; destroys esi and ecx
  718.  
  719.         mov     ecx, [esi + socket_queue_entry.data_size]
  720.         DEBUGF  1,"Got %u bytes of data\n", ecx
  721.  
  722.         cmp     ecx, ebx
  723.         ja      .too_small
  724.  
  725.         push    [esi + socket_queue_entry.buf_ptr]              ; save the buffer addr so we can clear it later
  726.         mov     esi, [esi + socket_queue_entry.data_ptr]
  727.         DEBUGF  1,"Source buffer: %x, real addr: %x\n", [esp], esi
  728.         mov     dword[esp+32+4], ecx                            ; return number of bytes copied
  729.  
  730. ; copy the data
  731.         shr     ecx, 1
  732.         jnc     .nb
  733.         movsb
  734.   .nb:
  735.         shr     ecx, 1
  736.         jnc     .nw
  737.         movsw
  738.   .nw:
  739.         test    ecx, ecx
  740.         jz      .nd
  741.         rep     movsd
  742.   .nd:
  743.  
  744.         call    kernel_free                                     ; remove the packet
  745.         ret
  746.  
  747.   .too_small:
  748.  
  749.         DEBUGF  1,"Buffer too small...\n"
  750.         jmp     s_error
  751.  
  752. align 4
  753. SOCKET_receive_tcp:
  754.  
  755.         DEBUGF  1,"SOCKET_receive: TCP\n"
  756.  
  757.         mov     ecx, esi
  758.         mov     edi, edx
  759.         add     eax, STREAM_SOCKET.rcv
  760.         call    SOCKET_ring_read
  761.         call    SOCKET_ring_free
  762.  
  763.         mov     dword[esp+32], ecx                              ; return number of bytes copied
  764.  
  765.         ret
  766.  
  767.  
  768. ;-----------------------------------------------------------------
  769. ;
  770. ; SOCKET_send
  771. ;
  772. ;
  773. ;  IN:  socket number in ecx
  774. ;       pointer to data in edx
  775. ;       datalength in esi
  776. ;       flags in edi
  777. ;  OUT: -1 on error
  778. ;
  779. ;-----------------------------------------------------------------
  780. align 4
  781. SOCKET_send:
  782.  
  783.         DEBUGF  1,"SOCKET_send: socknum: %u data ptr: %x, length: %u, flags: %x, ", ecx, edx, esi, edi
  784.  
  785.         call    SOCKET_num_to_ptr
  786.         jz      s_error
  787.  
  788.         mov     ecx, esi
  789.         mov     esi, edx
  790.  
  791.         jmp     [eax + SOCKET.snd_proc]
  792.  
  793.  
  794. align 4
  795. SOCKET_send_udp:
  796.  
  797.         DEBUGF  1,"SOCKET_send: UDP\n"
  798.  
  799.         call    UDP_output
  800.  
  801.         mov     dword [esp+32], 0
  802.         ret
  803.  
  804.  
  805. align 4
  806. SOCKET_send_tcp:
  807.  
  808.         DEBUGF  1,"SOCKET_send: TCP\n"
  809.  
  810.         push    eax
  811.         add     eax, STREAM_SOCKET.snd
  812.         call    SOCKET_ring_write
  813.         pop     eax
  814.  
  815.         call    TCP_output
  816.  
  817.         mov     [esp+32], eax
  818.         ret
  819.  
  820.  
  821. align 4
  822. SOCKET_send_ip:
  823.  
  824.         DEBUGF  1,"type: IP\n"
  825.  
  826.         call    IPv4_output_raw
  827.  
  828.         mov     [esp+32], eax
  829.         ret
  830.  
  831. align 4
  832. SOCKET_send_icmp:
  833.  
  834.         DEBUGF  1,"SOCKET_send: ICMP\n"
  835.  
  836.         call    ICMP_output_raw
  837.  
  838.         mov     dword [esp+32], 0
  839.         ret
  840.  
  841.  
  842.  
  843.  
  844. ;-----------------------------------------------------------------
  845. ;
  846. ; SOCKET_get_options
  847. ;
  848. ;  IN:  ecx = socket number
  849. ;       edx = pointer to the options:
  850. ;               dd      level, optname, optval, optlen
  851. ;  OUT: -1 on error
  852. ;
  853. ; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
  854. ; TODO: find best way to notify that send()'ed data were acknowledged
  855. ; Also pseudo-optname -3 is valid and returns socket state, one of TCPS_*.
  856. ;
  857. ;-----------------------------------------------------------------
  858. align 4
  859. SOCKET_get_opt:
  860.  
  861.         DEBUGF  1,"SOCKET_get_opt\n"
  862.  
  863.         call    SOCKET_num_to_ptr
  864.         jz      s_error
  865.  
  866.         cmp     dword [edx], IP_PROTO_TCP
  867.         jne     s_error
  868.         cmp     dword [edx+4], -2
  869.         je      @f
  870.         cmp     dword [edx+4], -3
  871.         jne     s_error
  872. @@:
  873. ;        mov     eax, [edx+12]
  874. ;        test    eax, eax
  875. ;        jz      .fail
  876. ;        cmp     dword [eax], 4
  877. ;        mov     dword [eax], 4
  878. ;        jb      .fail
  879. ;        stdcall net_socket_num_to_addr, ecx
  880. ;        test    eax, eax
  881. ;        jz      .fail
  882. ;        ; todo: check that eax is really TCP socket
  883. ;        mov     ecx, [eax + TCP_SOCKET.last_ack_number]
  884. ;        cmp     dword [edx+4], -2
  885. ;        jz      @f
  886. ;        mov     ecx, [eax + TCP_SOCKET.state]
  887. @@:
  888.         mov     eax, [edx+8]
  889.         test    eax, eax
  890.         jz      @f
  891.         mov     [eax], ecx
  892. @@:
  893.         mov     dword [esp+32], 0
  894.         ret
  895.  
  896.  
  897.  
  898.  
  899. align 4
  900. SOCKET_set_opt:
  901.  
  902.         ret
  903.  
  904.  
  905.  
  906. ;-----------------------------------------------------------------
  907. ;
  908. ; SOCKET_debug
  909. ;
  910. ;  Copies socket variables to application buffer
  911. ;
  912. ;  IN:  ecx = socket number
  913. ;       edx = pointer to buffer
  914. ;
  915. ;  OUT: -1 on error
  916. ;-----------------------------------------------------------------
  917. align 4
  918. SOCKET_debug:
  919.  
  920.         DEBUGF  1,"socket_debug\n"
  921.  
  922.         call    SOCKET_num_to_ptr
  923.         jz      s_error
  924.  
  925.         mov     esi, eax
  926.         mov     edi, edx
  927.         mov     ecx, SOCKETBUFFSIZE/4
  928.         rep     movsd
  929.  
  930.         mov     dword [esp+32], 0
  931.         ret
  932.  
  933.  
  934. ;-----------------------------------------------------------------
  935. ;
  936. ; SOCKET_find_port
  937. ;
  938. ; Fills in the local port number for TCP and UDP sockets
  939. ; This procedure always works because the number of sockets is
  940. ; limited to a smaller number then the number of possible ports
  941. ;
  942. ;  IN:  eax = socket pointer
  943. ;  OUT: /
  944. ;
  945. ;-----------------------------------------------------------------
  946. align 4
  947. SOCKET_find_port:
  948.  
  949.         DEBUGF  1,"SOCKET_find_port\n"
  950.  
  951.         push    ebx esi ecx
  952.  
  953.         cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
  954.         je      .udp
  955.  
  956.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
  957.         je      .tcp
  958.  
  959.         jmp     .error
  960.  
  961.   .done:
  962.         mov     [eax + UDP_SOCKET.LocalPort], bx
  963.   .error:
  964.         pop     ecx esi ebx
  965.         ret
  966.  
  967.   .udp:
  968.         mov     bx, [last_UDP_port]
  969.         call    .findit
  970.         mov     [last_UDP_port], bx
  971.         jmp     .done
  972.  
  973.   .tcp:
  974.         mov     bx, [last_TCP_port]
  975.         call    .findit
  976.         mov     [last_TCP_port], bx
  977.         jmp     .done
  978.  
  979.  
  980.   .restart:
  981.         mov     bx, MIN_EPHEMERAL_PORT
  982.   .findit:
  983.         inc     bx
  984.  
  985.         cmp     bx, MAX_EPHEMERAL_PORT
  986.         jz      .restart
  987.  
  988.         call    SOCKET_check_port
  989.         jz      .findit
  990.  
  991.         ret
  992.  
  993.  
  994.  
  995. ;-----------------------------------------------------------------
  996. ;
  997. ; SOCKET_check_port (to be used with AF_INET only!)
  998. ;
  999. ; Checks if a local port number is unused
  1000. ; If the proposed port number is unused, it is filled in in the socket structure
  1001. ;
  1002. ;  IN:  eax = socket ptr (to find out if its a TCP/UDP socket)
  1003. ;        bx = proposed socket number
  1004. ;
  1005. ;  OUT:  ZF = cleared on error
  1006. ;
  1007. ;-----------------------------------------------------------------
  1008. align 4
  1009. SOCKET_check_port:
  1010.  
  1011.         DEBUGF  1,"SOCKET_check_port\n"
  1012.  
  1013.         mov     ecx, [eax + SOCKET.Protocol]
  1014.         mov     esi, net_sockets
  1015.  
  1016.   .next_socket:
  1017.         mov     esi, [esi + SOCKET.NextPtr]
  1018.         or      esi, esi
  1019.         jz      .port_ok
  1020.  
  1021.         cmp     [esi + SOCKET.Protocol], ecx
  1022.         jne     .next_socket
  1023.  
  1024.         cmp     [esi + UDP_SOCKET.LocalPort], bx
  1025.         jne     .next_socket
  1026.  
  1027.         DEBUGF  1,"local port %u already in use\n", bx
  1028.         ret
  1029.  
  1030.   .port_ok:
  1031.         mov     [eax + UDP_SOCKET.LocalPort], bx
  1032.         or      bx, bx                                  ; set the zero-flag
  1033.  
  1034.         ret
  1035.  
  1036.  
  1037.  
  1038. ;-----------------------------------------------------------------
  1039. ;
  1040. ; SOCKET_input
  1041. ;
  1042. ; Updates a (stateless) socket with received data
  1043. ;
  1044. ; Note: the mutex should already be set !
  1045. ;
  1046. ;  IN:  eax = socket ptr
  1047. ;       ebx = pointer to device struct
  1048. ;       ecx = data size
  1049. ;       esi = ptr to data
  1050. ;       [esp] = ptr to buf
  1051. ;       [esp + 4] = buf size
  1052. ;
  1053. ;  OUT: /
  1054. ;
  1055. ;-----------------------------------------------------------------
  1056. align 4
  1057. SOCKET_input:
  1058.  
  1059.         DEBUGF  1,"SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
  1060.  
  1061.         mov     dword[esp+4], ecx
  1062.         push    esi
  1063.         mov     esi, esp
  1064.  
  1065.         add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, socket_queue_entry.size, SOCKET_input.full
  1066.  
  1067.         DEBUGF  1,"SOCKET_input: queued packet successfully\n"
  1068.         add     esp, socket_queue_entry.size
  1069.         mov     [eax + SOCKET.lock], 0
  1070.         jmp     SOCKET_notify_owner
  1071.  
  1072.   .full:
  1073.         DEBUGF  2,"SOCKET_input: socket %x is full!\n", eax
  1074.         mov     [eax + SOCKET.lock], 0
  1075.         call    kernel_free
  1076.         add     esp, 8
  1077.  
  1078.         ret
  1079.  
  1080.  
  1081. ;--------------------------
  1082. ;
  1083. ; eax = ptr to ring struct (just a buffer of the right size)
  1084. ;
  1085. align 4
  1086. SOCKET_ring_create:
  1087.  
  1088.         push    esi
  1089.         mov     esi, eax
  1090.  
  1091.         push    edx
  1092.         stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
  1093.         pop     edx
  1094.  
  1095.         DEBUGF  1,"SOCKET_ring_created: %x\n", eax
  1096.         mov     [esi + RING_BUFFER.start_ptr], eax
  1097.         mov     [esi + RING_BUFFER.write_ptr], eax
  1098.         mov     [esi + RING_BUFFER.read_ptr], eax
  1099.         mov     [esi + RING_BUFFER.size], 0
  1100.         add     eax,  SOCKET_MAXDATA
  1101.         mov     [esi + RING_BUFFER.end_ptr], eax
  1102.         mov     eax, esi
  1103.         pop     esi
  1104.  
  1105.         ret
  1106.  
  1107. ;-----------------------------------------------------------------
  1108. ;
  1109. ; SOCKET_ring_write
  1110. ;
  1111. ; Adds data to a stream socket, and updates write pointer and size
  1112. ;
  1113. ;  IN:  eax = ptr to ring struct
  1114. ;       ecx = data size
  1115. ;       esi = ptr to data
  1116. ;
  1117. ;  OUT: ecx = number of bytes stored
  1118. ;
  1119. ;-----------------------------------------------------------------
  1120. align 4
  1121. SOCKET_ring_write:
  1122.  
  1123.         DEBUGF  1,"SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
  1124.  
  1125.         add     [eax + RING_BUFFER.size], ecx
  1126.         cmp     [eax + RING_BUFFER.size], SOCKET_MAXDATA
  1127.         ja      .too_large
  1128.  
  1129.   .copy:
  1130.         mov     edi, [eax + RING_BUFFER.write_ptr]
  1131.         DEBUGF  2,"SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
  1132.  
  1133.         push    ecx
  1134.         shr     ecx, 1
  1135.         jnc     .nb
  1136.         movsb
  1137.   .nb:
  1138.         shr     ecx, 1
  1139.         jnc     .nw
  1140.         movsw
  1141.   .nw:
  1142.         test    ecx, ecx
  1143.         jz      .nd
  1144.         rep     movsd
  1145.   .nd:
  1146.         pop     ecx
  1147.  
  1148.         cmp     edi, [eax + RING_BUFFER.end_ptr]
  1149.         jae     .wrap
  1150.         mov     [eax + RING_BUFFER.write_ptr], edi
  1151.  
  1152.         ret
  1153.  
  1154.   .wrap:
  1155.         sub     edi, SOCKET_MAXDATA
  1156.         mov     [eax + RING_BUFFER.write_ptr], edi
  1157.  
  1158.         ret
  1159.  
  1160.   .too_large:
  1161.         mov     ecx, SOCKET_MAXDATA                             ; calculate number of bytes available in buffer
  1162.         sub     ecx, [eax + RING_BUFFER.size]
  1163.         jae     .full
  1164.  
  1165.         mov     [eax + RING_BUFFER.size], SOCKET_MAXDATA        ; update size, we will fill buffer completely
  1166.         jmp     .copy
  1167.  
  1168.   .full:
  1169.         DEBUGF  2,"SOCKET_ring_write: ring buffer is full!\n"
  1170.         xor     ecx, ecx
  1171.         ret
  1172.  
  1173.  
  1174. ;-----------------------------------------------------------------
  1175. ;
  1176. ; SOCKET_ring_read
  1177. ;
  1178. ; reads the data, BUT DOES NOT CLEAR IT FROM MEMORY YET
  1179. ;
  1180. ;  IN:  eax = ptr to ring struct
  1181. ;       ecx = buffer size
  1182. ;       edi = ptr to buffer
  1183. ;
  1184. ;  OUT: ecx = number of bytes read
  1185. ;
  1186. ;-----------------------------------------------------------------
  1187. align 4
  1188. SOCKET_ring_read:
  1189.  
  1190.         DEBUGF  1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u\n", eax, edi, ecx
  1191.  
  1192.         cmp     ecx, [eax + RING_BUFFER.size]
  1193.         ja      .less_data
  1194.  
  1195.   .copy:
  1196.         mov     esi, [eax + RING_BUFFER.read_ptr]
  1197.  
  1198.         DEBUGF  2,"SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
  1199.         push    ecx
  1200.         shr     ecx, 1
  1201.         jnc     .nb
  1202.         movsb
  1203.   .nb:
  1204.         shr     ecx, 1
  1205.         jnc     .nw
  1206.         movsw
  1207.   .nw:
  1208.         test    ecx, ecx
  1209.         jz      .nd
  1210.         rep     movsd
  1211.   .nd:
  1212.         pop     ecx
  1213.  
  1214.   .no_data_at_all:
  1215.         ret
  1216.  
  1217.   .less_data:
  1218.         mov     ecx, [eax + RING_BUFFER.size]
  1219. ;        test    ecx, ecx
  1220. ;        jz      .no_data_at_all
  1221.         jmp     .copy
  1222.  
  1223.  
  1224. ;-----------------------------------------------------------------
  1225. ;
  1226. ; SOCKET_ring_free
  1227. ;
  1228. ; Free's some bytes from the ringbuffer
  1229. ;
  1230. ;  IN:  eax = ptr to ring struct
  1231. ;       ecx = data size
  1232. ;
  1233. ;  OUT: ecx = number of bytes free-ed
  1234. ;
  1235. ;-----------------------------------------------------------------
  1236. align 4
  1237. SOCKET_ring_free:
  1238.  
  1239.         DEBUGF  1,"SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
  1240.  
  1241.         sub     [eax + RING_BUFFER.size], ecx
  1242.         jb      .sumthinwong
  1243.         add     [eax + RING_BUFFER.read_ptr], ecx
  1244.  
  1245.         mov     edx, [eax + RING_BUFFER.end_ptr]
  1246.         cmp     [eax + RING_BUFFER.read_ptr], edx
  1247.         jb      @f
  1248.         sub     [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA
  1249.        @@:
  1250.         ret
  1251.  
  1252.   .sumthinwong:                ; we could free all available bytes, but that would be stupid, i guess..
  1253.         add     [eax + RING_BUFFER.size], ecx
  1254.         xor     ecx, ecx
  1255.         ret
  1256.  
  1257.  
  1258. ;-----------------------------------------------------------------
  1259. ;
  1260. ; SOCKET_notify_owner
  1261. ;
  1262. ; notify's the owner of a socket that something happened
  1263. ;
  1264. ;  IN:  eax = socket ptr
  1265. ;  OUT: /
  1266. ;
  1267. ;-----------------------------------------------------------------
  1268. align 4
  1269. SOCKET_notify_owner:
  1270.  
  1271.         DEBUGF  1,"SOCKET_notify_owner: %x\n", eax
  1272.  
  1273.         call    SOCKET_check
  1274.         jz      .error
  1275.  
  1276.         push    eax ecx esi
  1277.  
  1278. ; socket exists, now try to flag an event to the application
  1279.  
  1280.         mov     eax, [eax + SOCKET.PID]
  1281.         mov     ecx, 1
  1282.         mov     esi, TASK_DATA + TASKDATA.pid
  1283.  
  1284.        .next_pid:
  1285.         cmp     [esi], eax
  1286.         je      .found_pid
  1287.         inc     ecx
  1288.         add     esi, 0x20
  1289.         cmp     ecx, [TASK_COUNT]
  1290.         jbe     .next_pid
  1291.  
  1292. ; PID not found, TODO: close socket!
  1293.  
  1294.         jmp     .error2
  1295.  
  1296.        .found_pid:
  1297.         shl     ecx, 8
  1298.         or      [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
  1299.         mov     [check_idle_semaphore], 200
  1300.  
  1301.         DEBUGF  1,"SOCKET_notify_owner: succes!\n"
  1302.  
  1303.   .error2:
  1304.         pop     esi ecx eax
  1305.  
  1306.   .error:
  1307.  
  1308.         ret
  1309.  
  1310.  
  1311. ;--------------------------------------------------------------------
  1312. ;
  1313. ; SOCKET_alloc
  1314. ;
  1315. ; Allocate memory for socket data and put new socket into the list
  1316. ; Newly created socket is initialized with calling PID and number and
  1317. ; put into beginning of list (which is a fastest way).
  1318. ;
  1319. ; IN:  /
  1320. ; OUT: eax = 0 on error, socket ptr otherwise
  1321. ;      edi = socket number
  1322. ;       ZF = cleared on error
  1323. ;
  1324. ;--------------------------------------------------------------------
  1325. align 4
  1326. SOCKET_alloc:
  1327.  
  1328.         push    ecx ebx
  1329.  
  1330.         stdcall kernel_alloc, SOCKETBUFFSIZE
  1331.         DEBUGF  1, "SOCKET_alloc: ptr=%x\n", eax
  1332.         or      eax, eax
  1333.         jz      .exit
  1334.  
  1335. ; zero-initialize allocated memory
  1336.         push    eax edi
  1337.         mov     edi, eax
  1338.         mov     ecx, SOCKETBUFFSIZE / 4
  1339.         xor     eax, eax
  1340.         rep     stosd
  1341.         pop     edi eax
  1342.  
  1343. ; set send-and receive procedures to return -1
  1344.         mov     [eax + SOCKET.snd_proc], s_error
  1345.         mov     [eax + SOCKET.rcv_proc], s_error
  1346.  
  1347. ; find first free socket number and use it
  1348.         mov     ecx, [last_socket_num]
  1349.   .next_socket_number:
  1350.         inc     ecx
  1351.         jz      .next_socket_number     ; avoid socket nr 0
  1352.         cmp     ecx, -1
  1353.         je      .next_socket_number     ; avoid socket nr -1
  1354.         mov     ebx, net_sockets
  1355.   .next_socket:
  1356.         mov     ebx, [ebx + SOCKET.NextPtr]
  1357.         test    ebx, ebx
  1358.         jz      .last_socket
  1359.  
  1360.         cmp     [ebx + SOCKET.Number], ecx
  1361.         jne     .next_socket
  1362.         jmp     .next_socket_number
  1363.  
  1364.   .last_socket:
  1365.         mov     [last_socket_num], ecx
  1366.         mov     [eax + SOCKET.Number], ecx
  1367.         DEBUGF  1, "SOCKET_alloc: number=%u\n", ecx
  1368.         mov     edi, ecx
  1369.  
  1370. ; Fill in PID
  1371.         mov     ebx, [TASK_BASE]
  1372.         mov     ebx, [ebx + TASKDATA.pid]
  1373.         mov     [eax + SOCKET.PID], ebx
  1374.  
  1375. ; add socket to the list by re-arranging some pointers
  1376.         mov     ebx, [net_sockets + SOCKET.NextPtr]
  1377.  
  1378.         mov     [eax + SOCKET.PrevPtr], net_sockets
  1379.         mov     [eax + SOCKET.NextPtr], ebx
  1380.  
  1381.         test    ebx, ebx
  1382.         jz      @f
  1383.         add     ebx, SOCKET.lock        ; lock the next socket
  1384.         call    wait_mutex
  1385.         sub     ebx, SOCKET.lock
  1386.         mov     [ebx + SOCKET.PrevPtr], eax
  1387.         mov     [ebx + SOCKET.lock], 0  ; and unlock it again
  1388.        @@:
  1389.  
  1390.         mov     [net_sockets + SOCKET.NextPtr], eax
  1391.         or      eax, eax                ; used to clear zero flag
  1392.   .exit:
  1393.         pop     ebx ecx
  1394.  
  1395.         ret
  1396.  
  1397.  
  1398. ;----------------------------------------------------
  1399. ;
  1400. ; SOCKET_free
  1401. ;
  1402. ; Free socket data memory and remove socket from the list
  1403. ;
  1404. ; IN:  eax = socket ptr
  1405. ; OUT: /
  1406. ;
  1407. ;----------------------------------------------------
  1408. align 4
  1409. SOCKET_free:
  1410.  
  1411.         DEBUGF  1, "SOCKET_free: %x\n", eax
  1412.  
  1413.         call    SOCKET_check
  1414.         jz      .error
  1415.  
  1416.         push    ebx
  1417.         lea     ebx, [eax + SOCKET.lock]
  1418.         call    wait_mutex
  1419.  
  1420.         DEBUGF  1, "SOCKET_free: freeing socket..\n"
  1421.  
  1422.         cmp     [eax + SOCKET.Domain], AF_INET4
  1423.         jnz     .no_tcp
  1424.  
  1425.         cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
  1426.         jnz     .no_tcp
  1427.  
  1428.         mov     ebx, eax
  1429.         stdcall kernel_free, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.start_ptr]
  1430.         stdcall kernel_free, [ebx + STREAM_SOCKET.snd + RING_BUFFER.start_ptr]
  1431.         mov     eax, ebx
  1432.   .no_tcp:
  1433.  
  1434.         push    eax                             ; this will be passed to kernel_free
  1435.         mov     ebx, [eax + SOCKET.NextPtr]
  1436.         mov     eax, [eax + SOCKET.PrevPtr]
  1437.  
  1438.         DEBUGF  1, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
  1439.  
  1440.         test    eax, eax
  1441.         jz      @f
  1442.         mov     [eax + SOCKET.NextPtr], ebx
  1443.        @@:
  1444.  
  1445.         test    ebx, ebx
  1446.         jz      @f
  1447.         mov     [ebx + SOCKET.PrevPtr], eax
  1448.        @@:
  1449.  
  1450.         call    kernel_free
  1451.         pop     ebx
  1452.  
  1453.         DEBUGF  1, "SOCKET_free: success!\n"
  1454.  
  1455.   .error:
  1456.         ret
  1457.  
  1458. ;------------------------------------
  1459. ;
  1460. ; SOCKET_fork
  1461. ;
  1462. ; Create a child socket
  1463. ;
  1464. ; IN:  socket nr in ebx
  1465. ; OUT: child socket nr in eax
  1466. ;
  1467. ;-----------------------------------
  1468. align 4
  1469. SOCKET_fork:
  1470.  
  1471.         DEBUGF  1,"SOCKET_fork: %x\n", ebx
  1472.  
  1473. ; Exit if backlog queue is full
  1474.         mov     eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
  1475.         cmp     ax, [ebx + SOCKET.backlog]
  1476.         jae     .fail
  1477.  
  1478. ; Allocate new socket
  1479.         call    SOCKET_alloc
  1480.         jz      .fail
  1481.  
  1482.         push    esi ecx edi
  1483.         push    eax
  1484.         mov     esi, esp
  1485.         add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2
  1486.         pop     eax
  1487.  
  1488. ; Copy structure from current socket to new
  1489. ; We start at PID to preserve the socket num, and the 2 pointers at beginning of socket
  1490.         lea     esi, [ebx + SOCKET.PID]
  1491.         lea     edi, [eax + SOCKET.PID]
  1492.         mov     ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
  1493.         rep     movsd
  1494.  
  1495.         and     [eax + SOCKET.options], not SO_ACCEPTCON
  1496.         pop     edi ecx esi
  1497.  
  1498.         ret
  1499.  
  1500.   .fail2:
  1501.         add     esp, 4+4+4
  1502.   .fail:
  1503.         DEBUGF  1,"SOCKET_fork: failed\n"
  1504.         xor     eax, eax
  1505.         ret
  1506.  
  1507.  
  1508. ;---------------------------------------------------
  1509. ;
  1510. ; SOCKET_num_to_ptr
  1511. ;
  1512. ; Get socket structure address by its number
  1513. ;
  1514. ; IN:  ecx = socket number
  1515. ; OUT: eax = 0 on error, socket ptr otherwise
  1516. ;       ZF = set on error
  1517. ;
  1518. ;---------------------------------------------------
  1519. align 4
  1520. SOCKET_num_to_ptr:
  1521.  
  1522.         DEBUGF  1,"SOCKET_num_to_ptr: %u ", ecx
  1523.  
  1524.         mov     eax, net_sockets
  1525.  
  1526.   .next_socket:
  1527.         mov     eax, [eax + SOCKET.NextPtr]
  1528.         or      eax, eax
  1529.         jz      .error
  1530.         cmp     [eax + SOCKET.Number], ecx
  1531.         jne     .next_socket
  1532.  
  1533.         test    eax, eax
  1534.  
  1535.         DEBUGF  1,"(%x)\n", eax
  1536.   .error:
  1537.         ret
  1538.  
  1539.  
  1540. ;---------------------------------------------------
  1541. ;
  1542. ; SOCKET_ptr_to_num
  1543. ;
  1544. ; Get socket number by its address
  1545. ;
  1546. ; IN:  eax = socket ptr
  1547. ; OUT: eax = 0 on error, socket num otherwise
  1548. ;       ZF = set on error
  1549. ;
  1550. ;---------------------------------------------------
  1551. align 4
  1552. SOCKET_ptr_to_num:
  1553.  
  1554.         DEBUGF  1,"SOCKET_ptr_to_num: %x ", eax
  1555.  
  1556.         call    SOCKET_check
  1557.         jz      .error
  1558.  
  1559.         mov     eax, [eax + SOCKET.Number]
  1560.  
  1561.         DEBUGF  1,"(%u)\n", eax
  1562.  
  1563.   .error:
  1564.         ret
  1565.  
  1566.  
  1567. ;---------------------------------------------------
  1568. ;
  1569. ; SOCKET_check
  1570. ;
  1571. ; checks if the given value is really a socket ptr
  1572. ;
  1573. ; IN:  eax = socket ptr
  1574. ; OUT: eax = 0 on error, unchanged otherwise
  1575. ;       ZF = set on error
  1576. ;
  1577. ;---------------------------------------------------
  1578. align 4
  1579. SOCKET_check:
  1580.  
  1581.         DEBUGF  1,"SOCKET_check: %x\n", eax
  1582.  
  1583.         push    ebx
  1584.         mov     ebx, net_sockets
  1585.  
  1586.   .next_socket:
  1587.         mov     ebx, [ebx + SOCKET.NextPtr]
  1588.         or      ebx, ebx
  1589.         jz      .done
  1590.         cmp     ebx, eax
  1591.         jnz     .next_socket
  1592.  
  1593.   .done:
  1594.         mov     eax, ebx
  1595.         test    eax, eax
  1596.         pop     ebx
  1597.  
  1598.         ret
  1599.  
  1600.  
  1601.  
  1602. ;---------------------------------------------------
  1603. ;
  1604. ; SOCKET_check_owner
  1605. ;
  1606. ; checks if the caller application owns the socket
  1607. ;
  1608. ; IN:  eax = socket ptr
  1609. ; OUT:  ZF = true/false
  1610. ;
  1611. ;---------------------------------------------------
  1612. align 4
  1613. SOCKET_check_owner:
  1614.  
  1615.         DEBUGF  1,"SOCKET_check_owner: %x\n", eax
  1616.  
  1617.         push    ebx
  1618.         mov     ebx, [TASK_BASE]
  1619.         mov     ebx, [ecx + TASKDATA.pid]
  1620.         cmp     [eax + SOCKET.PID], ebx
  1621.         pop      ebx
  1622.  
  1623.         ret
  1624.  
  1625.  
  1626.  
  1627.  
  1628. ;------------------------------------------------------
  1629. ;
  1630. ; SOCKET_process_end
  1631. ;
  1632. ; Kernel calls this function when a certain process ends
  1633. ; This function will check if the process had any open sockets
  1634. ; And update them accordingly
  1635. ;
  1636. ; IN:  eax = pid
  1637. ; OUT: /
  1638. ;
  1639. ;------------------------------------------------------
  1640. align 4
  1641. SOCKET_process_end:
  1642.  
  1643.         DEBUGF  1,"SOCKET_process_end: %x\n", eax
  1644.  
  1645.         push    ebx
  1646.         mov     ebx, net_sockets
  1647.  
  1648.   .next_socket:
  1649.  
  1650.         mov     ebx, [ebx + SOCKET.NextPtr]
  1651.   .test_socket:
  1652.         test    ebx, ebx
  1653.         jz      .done
  1654.  
  1655.         cmp     [ebx + SOCKET.PID], eax
  1656.         jne     .next_socket
  1657.  
  1658.         DEBUGF  1,"closing socket %x", eax, ebx
  1659.  
  1660.         mov     [ebx + SOCKET.PID], 0
  1661.  
  1662.         cmp     [ebx + SOCKET.Protocol], IP_PROTO_UDP
  1663.         je      .udp
  1664.  
  1665.         cmp     [ebx + SOCKET.Protocol], IP_PROTO_TCP
  1666.         je      .tcp
  1667.  
  1668.         jmp     .next_socket    ; kill all sockets for given PID
  1669.  
  1670.   .udp:
  1671.         mov     eax, ebx
  1672.         mov     ebx, [ebx + SOCKET.NextPtr]
  1673.         call    SOCKET_free
  1674.         jmp     .test_socket
  1675.  
  1676.   .tcp:
  1677.  
  1678.         ;;; TODO
  1679.  
  1680.         jmp     .next_socket
  1681.  
  1682.   .done:
  1683.         pop     ebx
  1684.  
  1685.         ret
  1686.  
  1687.  
  1688.  
  1689.  
  1690. ;-----------------------------------------------------------------
  1691. ;
  1692. ; SOCKET_is_connecting
  1693. ;
  1694. ;  IN:  eax = socket ptr
  1695. ;  OUT: /
  1696. ;
  1697. ;-----------------------------------------------------------------
  1698.  
  1699. align 4
  1700. SOCKET_is_connecting:
  1701.  
  1702.  
  1703.         and     [eax + SOCKET.options], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
  1704.         or      [eax + SOCKET.options], SS_ISCONNECTING
  1705.  
  1706.         jmp     SOCKET_notify_owner
  1707.  
  1708.  
  1709.  
  1710. ;-----------------------------------------------------------------
  1711. ;
  1712. ; SOCKET_is_connected
  1713. ;
  1714. ;  IN:  eax = socket ptr
  1715. ;  OUT: /
  1716. ;
  1717. ;-----------------------------------------------------------------
  1718.  
  1719. align 4
  1720. SOCKET_is_connected:
  1721.  
  1722.  
  1723.         and     [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
  1724.         or      [eax + SOCKET.options], SS_ISCONNECTED
  1725.  
  1726.         jmp     SOCKET_notify_owner
  1727.  
  1728.  
  1729.  
  1730.  
  1731. ;-----------------------------------------------------------------
  1732. ;
  1733. ; SOCKET_is_disconnecting
  1734. ;
  1735. ;  IN:  eax = socket ptr
  1736. ;  OUT: /
  1737. ;
  1738. ;-----------------------------------------------------------------
  1739.  
  1740. align 4
  1741. SOCKET_is_disconnecting:
  1742.  
  1743.         and     [eax + SOCKET.options], not (SS_ISCONNECTING)
  1744.         or      [eax + SOCKET.options], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
  1745.  
  1746.         jmp     SOCKET_notify_owner
  1747.  
  1748.  
  1749.  
  1750. ;-----------------------------------------------------------------
  1751. ;
  1752. ; SOCKET_is_disconnected
  1753. ;
  1754. ;  IN:  eax = socket ptr
  1755. ;  OUT: /
  1756. ;
  1757. ;-----------------------------------------------------------------
  1758.  
  1759. align 4
  1760. SOCKET_is_disconnected:
  1761.  
  1762.         and     [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
  1763.         or      [eax + SOCKET.options], SS_CANTRCVMORE + SS_CANTSENDMORE
  1764.  
  1765.         jmp     SOCKET_notify_owner
  1766.  
  1767.  
  1768. ;-----------------------------------------------------------------
  1769. ;
  1770. ; SOCKET_cant_recv_more
  1771. ;
  1772. ;  IN:  eax = socket ptr
  1773. ;  OUT: /
  1774. ;
  1775. ;-----------------------------------------------------------------
  1776.  
  1777. align 4
  1778. SOCKET_cant_recv_more:
  1779.  
  1780.         or      [eax + SOCKET.options], SS_CANTRCVMORE
  1781.  
  1782.         ret
  1783.  
  1784.  
  1785.  
  1786. ;-----------------------------------------------------------------
  1787. ;
  1788. ; SOCKET_cant_send_more
  1789. ;
  1790. ;  IN:  eax = socket ptr
  1791. ;  OUT: /
  1792. ;
  1793. ;-----------------------------------------------------------------
  1794.  
  1795. align 4
  1796. SOCKET_cant_send_more:
  1797.  
  1798.         or      [eax + SOCKET.options], SS_CANTSENDMORE
  1799.  
  1800.         ret