Subversion Repositories Kolibri OS

Rev

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

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