Subversion Repositories Kolibri OS

Rev

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