Subversion Repositories Kolibri OS

Rev

Rev 1159 | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2008. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  SOCKET.INC                                                     ;;
  7. ;;                                                                 ;;
  8. ;;                                                                 ;;
  9. ;;    Written by hidnplayr@kolibrios.org                           ;;
  10. ;;    based on code by mike.dld                                    ;;
  11. ;;                                                                 ;;
  12. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  13. ;;             Version 2, June 1991                                ;;
  14. ;;                                                                 ;;
  15. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  16.  
  17. $Revision: 1019 $
  18.  
  19. align 4
  20. struct   SOCKET
  21.          .PrevPtr               dd ? ; pointer to previous socket in list
  22.          .NextPtr               dd ? ; pointer to next socket in list
  23.          .Number                dd ? ; socket number (unique within single process)
  24.          .PID                   dd ? ; application process id
  25.          .Domain                dd ? ; INET/UNIX/..
  26.          .Type                  dd ? ; RAW/UDP/TCP/...
  27.          .LocalIP               dd ? ; local IP address
  28.          .RemoteIP              dd ? ; remote IP address
  29.          .LocalPort             dw ? ; local port
  30.          .RemotePort            dw ? ; remote port
  31. ;         .OrigRemoteIP          dd ? ; original remote IP address (used to reset to LISTEN state)
  32. ;         .OrigRemotePort        dw ? ; original remote port (used to reset to LISTEN state)
  33.          .rxDataCount           dd ? ; rx data count
  34. ;         .TCBState              dd ? ; TCB state
  35. ;         .TCBTimer              dd ? ; TCB timer (seconds)
  36. ;         .ISS                   dd ? ; initial send sequence
  37. ;         .IRS                   dd ? ; initial receive sequence
  38. ;         .SND_UNA               dd ? ; sequence number of unack'ed sent Packets
  39. ;         .SND_NXT               dd ? ; bext send sequence number to use
  40. ;         .SND_WND               dd ? ; send window
  41. ;         .RCV_NXT               dd ? ; next receive sequence number to use
  42. ;         .RCV_WND               dd ? ; receive window
  43. ;         .SEG_LEN               dd ? ; segment length
  44. ;         .SEG_WND               dd ? ; segment window
  45.          .wndsizeTimer          dd ? ; window size timer
  46.          .lock                  dd ? ; lock mutex
  47.          .backlog               dw ? ; Backlog
  48.          .rxData:                    ; receive data buffer here
  49. ends
  50.  
  51. MAX_backlog     equ 20
  52.  
  53. ; socket buffers
  54. SOCKETBUFFSIZE          equ 4096  ; state + config + buffer.
  55. SOCKETHEADERSIZE        equ SOCKET.rxData ; thus 4096 - SOCKETHEADERSIZE bytes data
  56.  
  57. uglobal
  58.         net_sockets     rd 2
  59.         last_UDP_port   dw ? ; These values give the number of the last used ephemeral port
  60.         last_TCP_port   dw ? ;
  61. endg
  62.  
  63.  
  64. ;-----------------------------------------------
  65. ;
  66. ; SOCKET_init
  67. ;
  68. ;  -
  69. ;
  70. ;  IN:  /
  71. ;  OUT: /
  72. ;
  73. ;-----------------------------------------------
  74.  
  75. align 4
  76. socket_init:
  77.  
  78.         mov     [net_sockets], 0
  79.         mov     [net_sockets + 4], 0
  80.  
  81.         mov     [last_UDP_port], MIN_EPHEMERAL_PORT
  82.         mov     [last_TCP_port], MIN_EPHEMERAL_PORT
  83.  
  84.         ret
  85.  
  86.  
  87. ;-----------------------------------------------------------------------------
  88. ;
  89. ; Socket API (function 74)
  90. ;
  91. ;-----------------------------------------------------------------------------
  92.  
  93. align 4
  94. sys_socket:
  95.  
  96.         test    bl, bl
  97.         jz      socket_open     ; 0
  98.         dec     bl
  99.         jz      socket_close    ; 1
  100.         dec     bl
  101.         jz      socket_bind     ; 2
  102.         dec     bl
  103.         jz      socket_listen   ; 3
  104.         dec     bl
  105.         jz      socket_connect  ; 4
  106.         dec     bl
  107.         jz      socket_accept   ; 5
  108.         dec     bl
  109.         jz      socket_send     ; 6
  110.         dec     bl
  111.         jz      socket_recv     ; 7
  112.  
  113. error:
  114.         mov     dword [esp+32],-1
  115.  
  116.         ret
  117.  
  118.  
  119.  
  120.  
  121. ;-----------------------------------------------
  122. ;
  123. ; SOCKET_open
  124. ;
  125. ;
  126. ;  IN:  domain in ecx
  127. ;       type in edx
  128. ;       set esi to zero, it is reserved for future use
  129. ;  OUT: eax is socket num, -1 on error
  130. ;
  131. ;-----------------------------------------------
  132. socket_open:
  133.  
  134.         DEBUGF  1,"socket_open: domain: %u, type: %u",ecx, edx
  135.  
  136.         call    net_socket_alloc
  137.         or      eax, eax
  138.         jz      error
  139.  
  140.         mov     [eax + SOCKET.Domain], ecx
  141.         mov     [eax + SOCKET.Type], edx
  142.  
  143.         stdcall net_socket_addr_to_num, eax
  144.         DEBUGF  1,", socketnumber: %u\n", eax
  145.  
  146.         mov     [esp+32], eax
  147.  
  148.         ret
  149.  
  150.  
  151.  
  152.  
  153. ;-----------------------------------------------
  154. ;
  155. ; SOCKET_bind
  156. ;
  157. ;
  158. ;  IN:  socket number in ecx
  159. ;       pointer to sockaddr struct in edx
  160. ;       length of that struct in esi
  161. ;  OUT: 0 on success
  162. ;
  163. ;-----------------------------------------------
  164.  
  165. socket_bind:
  166.  
  167.         DEBUGF  1,"Socket_bind: socknum: %u sockaddr: %x, length: %u, ",ecx,edx,esi
  168.  
  169.         stdcall net_socket_num_to_addr, ecx
  170.         cmp     eax, -1
  171.         jz      error
  172.  
  173.         cmp     esi, 2
  174.         jl      error
  175.  
  176.         cmp     word [edx], AF_INET4
  177.         je      .af_inet4
  178.  
  179.         jmp     error
  180.  
  181.   .af_inet4:
  182.  
  183.         cmp     esi, 6
  184.         jl      error
  185.  
  186.         mov     bx, word [edx + 2]
  187.         DEBUGF  1,"local port: %u ",bx
  188.         test    bx, bx
  189.         jnz     .check_only
  190.  
  191.         mov     bx , [last_UDP_port]
  192.  
  193.   .find_port_loop:
  194.         inc     bx
  195.         inc     [last_UDP_port]
  196.  
  197.   .check_only:
  198.         mov     esi, net_sockets
  199.  
  200.   .next_udp_socket:
  201.         mov     esi, [esi + SOCKET.NextPtr]
  202.         or      esi, esi
  203.         jz      .udp_port_ok
  204.  
  205.         cmp     [esi + SOCKET.Type], IP_PROTO_UDP
  206.         jne     .next_udp_socket
  207.  
  208.         cmp     [esi + SOCKET.LocalPort], bx
  209.         jne     .next_udp_socket
  210.  
  211.         cmp     word [edx + 2], 0
  212.         jne     error
  213.  
  214.         cmp     bx, MAX_EPHEMERAL_PORT
  215.         jle     .find_port_loop
  216.  
  217.         mov     [last_UDP_port], MIN_EPHEMERAL_PORT
  218.         jmp     error
  219.  
  220.   .udp_port_ok:
  221.         mov     word [eax + SOCKET.LocalPort], bx
  222.  
  223.         mov     ebx, dword [edx + 4]
  224.         mov     dword [eax + SOCKET.LocalIP], ebx
  225.  
  226.         DEBUGF  1,"local ip: %u.%u.%u.%u\n",\
  227.         [eax + SOCKET.LocalIP]:1,[eax + SOCKET.LocalIP + 1]:1,[eax + SOCKET.LocalIP + 2]:1,[eax + SOCKET.LocalIP + 3]:1
  228.  
  229.         mov     dword [esp+32],0
  230.         ret
  231.  
  232.  
  233.  
  234.  
  235. ;-----------------------------------------------
  236. ;
  237. ; SOCKET_connect
  238. ;
  239. ;
  240. ;  IN:  socket number in ecx
  241. ;       pointer to sockaddr struct in edx
  242. ;       length of that struct in esi
  243. ;  OUT: 0 on success
  244. ;
  245. ;-----------------------------------------------
  246. align 4
  247.  
  248. socket_connect:
  249.  
  250.         DEBUGF  1,"Socket_connect: socknum: %u sockaddr: %x, length: %u,",ecx,edx,esi
  251.  
  252.         stdcall net_socket_num_to_addr, ecx
  253.         cmp     eax, -1
  254.         jz      error
  255.  
  256.         cmp     esi, 2
  257.         jl      error
  258.  
  259.         cmp     word [edx], AF_INET4
  260.         je      .af_inet4
  261.  
  262.         jmp     error
  263.  
  264.   .af_inet4:
  265.  
  266.         cmp     esi, 8
  267.         jl      error
  268.  
  269.         cmp     [eax + SOCKET.Type], IP_PROTO_UDP
  270.         je      .udp
  271.  
  272.         cmp     [eax + SOCKET.Type], IP_PROTO_ICMP
  273.         je      .icmp
  274.  
  275. ;        cmp     [eax + SOCKET.Type], IP_PROTO_TCP
  276. ;        je      .tcp
  277.  
  278.         jmp     error
  279.  
  280.   .udp:
  281.  
  282.         mov     bx , word [edx + 2]
  283.         mov     word [eax + SOCKET.RemotePort], bx
  284.  
  285.         DEBUGF  1,"remote port: %u ",bx
  286.  
  287.         mov     ebx, dword [edx + 4]
  288.         mov     dword [eax + SOCKET.RemoteIP], ebx
  289.  
  290.         DEBUGF  1,"remote ip: %u.%u.%u.%u\n",[edx+4]:1,[edx+5]:1,[edx+6]:1,[edx+7]:1
  291.  
  292.         mov     dword [esp+32],0
  293.         ret
  294.  
  295.   .icmp:
  296.  
  297.  
  298.         ret
  299.  
  300.  
  301.  
  302.   .tcp:
  303.  
  304. ;local sockAddr dd ?
  305.  
  306. ;        cmp     esi, SOCKET_PASSIVE
  307. ;        jne     .skip_port_check
  308. ;
  309. ;        push    ebx
  310. ;        mov     eax, ebx
  311. ;        xchg    al, ah
  312. ;        mov     ebx, net_sockets
  313. ;
  314. ;  .next_socket:
  315. ;        mov     ebx, [ebx + SOCKET.NextPtr]
  316. ;        or      ebx, ebx
  317. ;        jz      .last_socket
  318. ;        cmp     [ebx + SOCKET.TCBState], TCB_LISTEN
  319. ;        jne     .next_socket
  320. ;        cmp     [ebx + SOCKET.LocalPort], ax
  321. ;        jne     .next_socket
  322. ;
  323. ;        xchg    al, ah
  324. ;        DEBUGF  1, "K : error: port %u is listened by 0x%x\n", ax, ebx
  325. ;        pop     ebx
  326. ;        jmp     .error
  327. ;
  328. ;  .last_socket:
  329. ;        pop     ebx
  330. ;
  331. ;  .skip_port_check:
  332.  
  333. ;        mov     [eax + SOCKET.wndsizeTimer], 0     ; Reset the window timer.
  334. ;
  335. ;        xchg    bh, bl
  336. ;        mov     [eax + SOCKET.LocalPort], bx
  337. ;        xchg    ch, cl
  338. ;        mov     [eax + SOCKET.RemotePort], cx
  339. ;        mov     [eax + SOCKET.OrigRemotePort], cx
  340. ;        mov     ebx, [IP_LIST]
  341. ;        mov     [eax + SOCKET.LocalIP], ebx
  342. ;        mov     [eax + SOCKET.RemoteIP], edx
  343. ;        mov     [eax + SOCKET.OrigRemoteIP], edx
  344.  
  345. ;        mov     ebx, TCB_LISTEN
  346. ;        cmp     esi, SOCKET_PASSIVE
  347. ;        je      @f
  348. ;        mov     ebx, TCB_SYN_SENT
  349. ;    @@: mov     [eax + SOCKET.TCBState], ebx            ; Indicate the state of the TCB
  350.  
  351. ;        cmp     ebx, TCB_LISTEN
  352. ;        je      .exit
  353.  
  354.         ; Now, if we are in active mode, then we have to send a SYN to the specified remote port
  355. ;        mov     eax, EMPTY_QUEUE
  356. ;        call    dequeue
  357. ;        cmp     ax, NO_BUFFER
  358. ;        je      .exit
  359.  
  360. ;        push    eax
  361.  
  362. ;        mov     bl, TH_SYN
  363. ;        xor     ecx, ecx
  364. ;        stdcall build_tcp_Packet, [sockAddr]
  365.  
  366. ;        mov     eax, NET1OUT_QUEUE
  367. ;        mov     edx, [IP_LIST]
  368. ;        mov     ecx, [sockAddr]
  369. ;        cmp     edx, [ecx + SOCKET.RemoteIP]
  370. ;        jne     .not_local
  371. ;        mov     eax, IPIN_QUEUE
  372.  
  373. ;  .not_local:
  374.         ; Send it.
  375. ;        pop     ebx
  376. ;        call    queue
  377.  
  378.   .exit:
  379.         xor     eax, eax
  380.         ret
  381.  
  382.  
  383.  
  384.  
  385. ;-----------------------------------------------
  386. ;
  387. ; SOCKET_listen
  388. ;
  389. ;
  390. ;  IN:  socket number in ecx
  391. ;       backlog in edx
  392. ;  OUT: eax is socket num, -1 on error
  393. ;
  394. ;-----------------------------------------------
  395.  
  396. socket_listen:
  397.  
  398.         DEBUGF  1,"Socket_listen: socknum: %u backlog: %u\n",ecx,edx
  399.  
  400.         stdcall net_socket_num_to_addr, ecx
  401.         cmp     eax, -1
  402.         jz      error
  403.  
  404.         cmp     edx, MAX_backlog
  405.         jl      .ok
  406.         mov     dx , 20
  407.   .ok:
  408.  
  409.         mov     [eax + SOCKET.backlog], dx
  410.  
  411.         ; TODO: insert code for active connections like TCP
  412.  
  413.         mov     dword [esp+32], 0
  414.         ret
  415.  
  416.  
  417.  
  418.  
  419.  
  420.  
  421. ;-----------------------------------------------
  422. ;
  423. ; SOCKET_accept
  424. ;
  425. ;
  426. ;  IN:  socket number in ecx
  427. ;       addr in edx
  428. ;       addrlen in esi
  429. ;  OUT: eax is socket num, -1 on error
  430. ;
  431. ;-----------------------------------------------
  432.  
  433.  
  434. socket_accept:
  435.  
  436.         DEBUGF  1,"Socket_accept: socknum: %u sockaddr: %x, length: %u\n",ecx,edx,esi
  437.  
  438.         stdcall net_socket_num_to_addr, ecx
  439.         or      eax, eax
  440.         jz      error
  441.         mov     esi, eax
  442.  
  443.         cmp     [esi + SOCKET.backlog], 0
  444.         jz      error
  445.  
  446.         call    net_socket_alloc
  447.         or      eax, eax
  448.         jz      error
  449.         mov     edi, eax
  450.  
  451.         dec     [esi + SOCKET.backlog]
  452.  
  453.         mov     ecx, (SOCKET.rxData+3)/4
  454.         rep     movsd
  455.  
  456.         mov     [edi + SOCKET.backlog], 0
  457.  
  458.         ; TODO: fill in structure in ecx
  459.  
  460.         mov     [esi + SOCKET.RemoteIP], 0
  461.         mov     [esi + SOCKET.RemotePort], 0
  462.  
  463.         stdcall net_socket_addr_to_num, eax
  464.         mov     [esp+32], eax
  465.  
  466.         ret
  467.  
  468.  
  469.  
  470. ;-----------------------------------------------
  471. ;
  472. ; SOCKET_close
  473. ;
  474. ;
  475. ;  IN:  socket number in ecx
  476. ;  OUT: eax is socket num, -1 on error
  477. ;
  478. ;-----------------------------------------------
  479.  
  480. socket_close:
  481.  
  482.         DEBUGF  1,"Socket_close: socknum: %u\n",ecx
  483.  
  484.         stdcall net_socket_num_to_addr, ecx
  485.         or      eax, eax
  486.         jz      error
  487.  
  488.  
  489.         cmp     [eax + SOCKET.Type], IP_PROTO_UDP
  490.         je      .udp
  491.  
  492.         cmp     [eax + SOCKET.Type], IP_PROTO_ICMP
  493.         je      .icmp
  494.  
  495. ;        cmp     [eax + SOCKET.Type], IP_PROTO_TCP
  496. ;        je      .tcp
  497.  
  498.         jmp     error
  499.  
  500.   .udp:
  501.  
  502.         lea     ebx, [eax + SOCKET.lock]
  503.         call    wait_mutex
  504.         ; TODO: mark the socket for deletion, using the mutex
  505.  
  506.         stdcall net_socket_free, eax
  507.  
  508.         mov     dword [esp+32],0
  509.         ret
  510.  
  511.  
  512.   .icmp:
  513.  
  514.  
  515.  
  516.         ret
  517.  
  518.   .tcp:
  519.  
  520. if 1 = 0
  521. ;local sockAddr dd ?
  522.  
  523. ;        DEBUGF  1, "K : socket_close_tcp (0x%x)\n", ebx
  524.         ; first, remove any resend entries
  525.         pusha
  526.  
  527.         mov     esi, resendQ
  528.         mov     ecx, 0
  529.  
  530.   .next_resendq:
  531.         cmp     ecx, NUMRESENDENTRIES
  532.         je      .last_resendq       ; None left
  533.         cmp     [esi + 4], ebx
  534.         je      @f                  ; found one
  535.         inc     ecx
  536.         add     esi, 8
  537.         jmp     .next_resendq
  538.  
  539.     @@: mov     dword[esi + 4], 0
  540.         inc     ecx
  541.         add     esi, 8
  542.         jmp     .next_resendq
  543.  
  544.   .last_resendq:
  545.         popa
  546.  
  547.         mov     ebx, eax
  548. ;        mov     [sockAddr], eax
  549.  
  550.         cmp     [eax + SOCKET.TCBState], TCB_LISTEN
  551.         je      .destroy_tcb
  552.         cmp     [eax + SOCKET.TCBState], TCB_SYN_SENT
  553.         je      .destroy_tcb
  554.  
  555. ; Now construct the response, and queue for sending by IP
  556.         mov     eax, EMPTY_QUEUE
  557.         call    dequeue
  558.         cmp     ax, NO_BUFFER
  559.         je      .error
  560.  
  561.         push    eax
  562.  
  563.         mov     bl, TH_FIN
  564.         xor     ecx, ecx
  565.         xor     esi, esi
  566.         stdcall build_tcp_Packet, [sockAddr]
  567.  
  568.         mov      ebx, [sockAddr]
  569.         ; increament SND.NXT in socket
  570.         lea     esi, [ebx + SOCKET.SND_NXT]
  571.         call    inc_inet_esi
  572.  
  573.         ; Get the socket state
  574.         mov     eax, [ebx + SOCKET.TCBState]
  575.         cmp     eax, TCB_SYN_RECEIVED
  576.         je      .fin_wait_1
  577.         cmp     eax, TCB_ESTABLISHED
  578.         je      .fin_wait_1
  579.  
  580.         ; assume CLOSE WAIT
  581.         ; Send a fin, then enter last-ack state
  582.         mov     [ebx + SOCKET.TCBState], TCB_LAST_ACK
  583.         jmp     .send
  584.  
  585.   .fin_wait_1:
  586.         ; Send a fin, then enter finwait2 state
  587.         mov     [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1
  588.  
  589.   .send:
  590.         mov     eax, NET1OUT_QUEUE
  591.         mov     edx, [IP_LIST]
  592. ;        mov     ecx, [sockAddr]
  593.         cmp     edx, [ecx + SOCKET.RemoteIP]
  594.         jne     .not_local
  595.         mov     eax, IPIN_QUEUE
  596.  
  597.   .not_local:
  598.         ; Send it.
  599.         pop     ebx
  600.         call    queue
  601.         jmp     .exit
  602.  
  603.  
  604.   .destroy_tcb:
  605.  
  606.         stdcall net_socket_free, eax
  607.  
  608. end if
  609.  
  610.   .exit:
  611.         mov     dword [esp+32],0
  612.         ret
  613.  
  614.  
  615.  
  616.  
  617. ;-----------------------------------------------
  618. ;
  619. ; SOCKET_receive
  620. ;
  621. ;
  622. ;  IN:  socket number in ecx
  623. ;       addr in edx
  624. ;       addrlen in esi
  625. ;       flags in edi
  626. ;  OUT: eax is number of bytes copied, -1 on error
  627. ;
  628. ;-----------------------------------------------
  629.  
  630. socket_recv:
  631.  
  632.         DEBUGF  1,"Socket_receive: socknum: %u sockaddr: %x, length: %u, flags: %x\n",ecx,edx,esi,edi
  633.  
  634.         stdcall net_socket_num_to_addr, ecx                ; get real socket address
  635.         or      eax, eax
  636.         jz      error
  637.  
  638.         DEBUGF 1,"real socket address:%x\n", eax
  639.  
  640.         mov     dword[esp+32], -1
  641.  
  642.         mov     edi, edx
  643.  
  644.         lea     ebx, [eax + SOCKET.lock]
  645.         call    wait_mutex
  646.  
  647.         mov     ecx, [eax + SOCKET.rxDataCount]            ; get count of bytes
  648.         DEBUGF 1,"bytes in socket:%u\n", ecx
  649.         test    ecx, ecx                                   ; if count of bytes is zero..
  650.         jz      .exit                                      ; exit function (eax will be zero)
  651.  
  652.         cmp     ecx, esi                                   ; if buffer size is larger then the bytes of data, copy all data
  653.         jle     .copy_all_bytes
  654.  
  655.         sub     ecx, esi                                   ; store new count (data bytes in buffer - bytes we're about to copy)
  656.         mov     [eax + SOCKET.rxDataCount], ecx            ;
  657.         push    ecx
  658.         mov     edx, esi
  659.  
  660.         call    .start_copy                                ; copy to the application
  661.  
  662.         mov     dword[esp+32], edx
  663.  
  664.         lea     edi, [eax + SOCKET.rxData]                 ; Now shift the remaining bytes to start of buffer
  665.         lea     esi, [edi + edx]
  666.         mov     ecx, [esp]
  667.         shr     ecx, 2                                     ; divide eax by 4
  668.         rep     movsd                                      ; copy all full dwords
  669.         pop     ecx
  670.         and     ecx, 3
  671.         rep     movsb                                      ; copy remaining bytes
  672.  
  673.   .exit:
  674.         mov     [eax + SOCKET.lock], 0
  675.         ret
  676.  
  677.   .copy_all_bytes:
  678.         mov     dword[esp+32], ecx
  679.         mov     [eax + SOCKET.rxDataCount], 0             ; store new count (zero)
  680.         push    dword .exit                                ; this code results in same as commented out code
  681.  
  682.   .start_copy:
  683.         DEBUGF  1,"copying %u bytes\n",ecx
  684.  
  685.         lea     esi, [eax + SOCKET.rxData]
  686.         push    ecx
  687.         shr     ecx, 2                                     ; divide eax by 4
  688.         rep     movsd
  689.         pop     ecx
  690.         and     ecx, 3
  691.         rep     movsb                                      ; copy the rest bytes
  692.  
  693.         ret                                                ; exit, or go back to shift remaining bytes if any
  694.  
  695.  
  696.  
  697. ;-----------------------------------------------
  698. ;
  699. ; SOCKET_send
  700. ;
  701. ;
  702. ;  IN:  socket number in ecx
  703. ;       addr in edx
  704. ;       addrlen in esi
  705. ;       flags in edi
  706. ;  OUT: -1 on error
  707. ;
  708. ;-----------------------------------------------
  709.  
  710. socket_send:
  711.  
  712.         DEBUGF  1,"Socket_send: socknum: %u sockaddr: %x, length: %u, flags: %x, ",ecx,edx,esi,edi
  713.  
  714.         stdcall net_socket_num_to_addr, ecx                ; get real socket address
  715.         or      eax, eax
  716.         jz      error
  717.  
  718.         DEBUGF  1,"Socket type:%u\n", [eax + SOCKET.Type]:4
  719.  
  720.         cmp     [eax + SOCKET.Type], IP_PROTO_UDP
  721.         je      .udp
  722.  
  723.         cmp     [eax + SOCKET.Type], IP_PROTO_ICMP
  724.         je      .icmp
  725.  
  726. ;        cmp     [eax + SOCKET.Type], IP_PROTO_TCP
  727. ;        je      .tcp
  728.  
  729.         jmp     error
  730.  
  731.   .udp:
  732.  
  733.         DEBUGF  1,"type: UDP\n"
  734.  
  735.         mov     ecx, esi
  736.         mov     esi, edx
  737.         mov     edx, dword [eax + SOCKET.LocalPort] ; load local port and remote port at once
  738.  
  739.         DEBUGF  1,"local port: %u, remote port:%u\n",[eax + SOCKET.LocalPort]:2, [eax + SOCKET.RemotePort]:2
  740.         mov     ebx, [eax + SOCKET.LocalIP]
  741.         mov     eax, [eax + SOCKET.RemoteIP]
  742.  
  743.         call    UDP_create_Packet
  744.  
  745.         mov     [esp+32], eax
  746.         ret
  747.  
  748.   .icmp:
  749.         ; note: for ICMP sockets the SOCKET.LocalPort is used as the 'Identifier' value for ICMP packets
  750.         ; the application must add the header to the data, the kernel will fill in 'identifier' and 'checksum'
  751.  
  752.         sub     ecx, ICMP_Packet.Data
  753.         mov     esi, edx
  754.         push    ax
  755.         call    IPv4_get_frgmnt_num
  756.         mov     dx, ax
  757.         pop     ax
  758.         shl     edx, 16
  759.         mov     dh , [esi + ICMP_Packet.Type]
  760.         mov     dl , [esi + ICMP_Packet.Code]
  761.         mov     di , [esi + ICMP_Packet.Identifier]
  762. ;        mov     [eax + SOCKET.LocalPort], di            ; Set localport to the identifier number, so we can receive reply's
  763.         shl     edi, 16
  764.         mov     di , [esi + ICMP_Packet.SequenceNumber]
  765.         add     esi, ICMP_Packet.Data
  766.         mov     ebx, [eax + SOCKET.LocalIP]
  767.         mov     eax, [eax + SOCKET.RemoteIP]
  768.         call    ICMP_create_Packet
  769.  
  770.         mov     [esp+32], eax
  771.         ret
  772.  
  773.   .tcp:
  774.  
  775.         ret
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.  
  783.  
  784. ; Allocate memory for socket data and put new socket into the list
  785. ; Newly created socket is initialized with calling PID and number and
  786. ; put into beginning of list (which is a fastest way).
  787. ;
  788. ; @return socket structure address in EAX
  789. ;
  790. proc net_socket_alloc stdcall uses ebx ecx edx edi
  791.         stdcall kernel_alloc, SOCKETBUFFSIZE
  792.         DEBUGF  1, "K : net_socket_alloc (0x%x)\n", eax
  793.         ; check if we can allocate needed amount of memory
  794.         or      eax, eax
  795.         jz      .exit
  796.  
  797.         ; zero-initialize allocated memory
  798.         push    eax
  799.         mov     edi, eax
  800.         mov     ecx, SOCKETBUFFSIZE / 4
  801. ;        cld
  802.         xor     eax, eax
  803.         rep     stosd
  804.         pop     eax
  805.  
  806.         ; add socket to the list by changing pointers
  807.         mov     ebx, net_sockets
  808.         push    [ebx + SOCKET.NextPtr]
  809.         mov     [ebx + SOCKET.NextPtr], eax
  810.         mov     [eax + SOCKET.PrevPtr], ebx
  811.         pop     ebx
  812.         mov     [eax + SOCKET.NextPtr], ebx
  813.         or      ebx, ebx
  814.         jz      @f
  815.         mov     [ebx + SOCKET.PrevPtr], eax
  816.  
  817.     @@: ; set socket owner PID to the one of calling process
  818.         mov     ebx, [TASK_BASE]
  819.         mov     ebx, [ebx + TASKDATA.pid]
  820.         mov     [eax + SOCKET.PID], ebx
  821.  
  822.         ; find first free socket number and use it
  823.         ;mov     edx, ebx
  824.         mov     ebx, net_sockets
  825.         xor     ecx, ecx
  826.   .next_socket_number:
  827.         inc     ecx
  828.   .next_socket:
  829.         mov     ebx, [ebx + SOCKET.NextPtr]
  830.         or      ebx, ebx
  831.         jz      .last_socket_number
  832.         cmp     [ebx + SOCKET.Number], ecx
  833.         jne     .next_socket
  834.         ;cmp     [ebx + SOCKET.PID], edx
  835.         ;jne     .next_socket
  836.         mov     ebx, net_sockets
  837.         jmp     .next_socket_number
  838.  
  839.   .last_socket_number:
  840.         mov     [eax + SOCKET.Number], ecx
  841.  
  842.   .exit:
  843.         ret
  844. endp
  845.  
  846. ; Free socket data memory and pop socket off the list
  847. ;
  848. ; @param sockAddr is a socket structure address
  849. ;
  850. proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD
  851.         mov     eax, [sockAddr]
  852.         DEBUGF  1, "K : net_socket_free (0x%x)\n", eax
  853.         ; check if we got something similar to socket structure address
  854.         or      eax, eax
  855.         jz      .error
  856.  
  857.         ; make sure sockAddr is one of the socket addresses in the list
  858.         mov     ebx, net_sockets
  859.         ;mov     ecx, [TASK_BASE]
  860.         ;mov     ecx, [ecx + TASKDATA.pid]
  861.   .next_socket:
  862.         mov     ebx, [ebx + SOCKET.NextPtr]
  863.         or      ebx, ebx
  864.         jz      .error
  865.         cmp     ebx, eax
  866.         jne     .next_socket
  867.         ;cmp     [ebx + SOCKET.PID], ecx
  868.         ;jne     .next_socket
  869.  
  870.         ; okay, we found the correct one
  871.         ; remove it from the list first, changing pointers
  872.         mov     ebx, [eax + SOCKET.NextPtr]
  873.         mov     eax, [eax + SOCKET.PrevPtr]
  874.         mov     [eax + SOCKET.NextPtr], ebx
  875.         or      ebx, ebx
  876.         jz      @f
  877.         mov     [ebx + SOCKET.PrevPtr], eax
  878.  
  879.     @@: ; and finally free the memory structure used
  880.         stdcall kernel_free, [sockAddr]
  881.         ret
  882.  
  883.   .error:
  884.         DEBUGF  1, "K :   failed\n"
  885.         ret
  886. endp
  887.  
  888. ; Get socket structure address by its number
  889. ; Scan through sockets list to find the socket with specified number.
  890. ; This proc uses SOCKET.PID indirectly to check if socket is owned by
  891. ; calling process.
  892. ;
  893. ; @param sockNum is a socket number
  894. ; @return socket structure address or 0 (not found) in EAX
  895. ;
  896. proc net_socket_num_to_addr stdcall uses ebx ecx, sockNum:DWORD
  897.         mov     eax, [sockNum]
  898.         ; check if we got something similar to socket number
  899.         or      eax, eax
  900.         jz      .error
  901.  
  902.         ; scan through sockets list
  903.         mov     ebx, net_sockets
  904.         ;mov     ecx, [TASK_BASE]
  905.         ;mov     ecx, [ecx + TASKDATA.pid]
  906.   .next_socket:
  907.         mov     ebx, [ebx + SOCKET.NextPtr]
  908.         or      ebx, ebx
  909.         jz      .error
  910.         cmp     [ebx + SOCKET.Number], eax
  911.         jne     .next_socket
  912.         ;cmp     [ebx + SOCKET.PID], ecx
  913.         ;jne     .next_socket
  914.  
  915.         ; okay, we found the correct one
  916.         mov     eax, ebx
  917.         ret
  918.  
  919.   .error:
  920.         xor     eax, eax
  921.         ret
  922. endp
  923.  
  924. ; Get socket number by its structure address
  925. ; Scan through sockets list to find the socket with specified address.
  926. ; This proc uses SOCKET.PID indirectly to check if socket is owned by
  927. ; calling process.
  928. ;
  929. ; @param sockAddr is a socket structure address
  930. ; @return socket number (SOCKET.Number) or 0 (not found) in EAX
  931. ;
  932. proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD
  933.         mov     eax, [sockAddr]
  934.         ; check if we got something similar to socket structure address
  935.         or      eax, eax
  936.         jz      .error
  937.  
  938.         ; scan through sockets list
  939.         mov     ebx, net_sockets
  940.         ;mov     ecx, [TASK_BASE]
  941.         ;mov     ecx, [ecx + TASKDATA.pid]
  942.   .next_socket:
  943.         mov     ebx, [ebx + SOCKET.NextPtr]
  944.         or      ebx, ebx
  945.         jz      .error
  946.         cmp     ebx, eax
  947.         jne     .next_socket
  948.         ;cmp     [ebx + SOCKET.PID], ecx
  949.         ;jne     .next_socket
  950.  
  951.         ; okay, we found the correct one
  952.         mov     eax, [ebx + SOCKET.Number]
  953.         ret
  954.  
  955.   .error:
  956.         xor     eax, eax
  957.         ret
  958. endp
  959.