Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;  SOCKET.INC                                                  ;;
  7. ;;                                                              ;;
  8. ;;  Sockets constants, structures and functions                 ;;
  9. ;;                                                              ;;
  10. ;;  Last revision: 11.11.2006                                   ;;
  11. ;;                                                              ;;
  12. ;;  This file contains the following:                           ;;
  13. ;;    is_localport_unused                                       ;;
  14. ;;    get_free_socket                                           ;;
  15. ;;    socket_open                                               ;;
  16. ;;    socket_open_tcp                                           ;;
  17. ;;    socket_close                                              ;;
  18. ;;    socket_close_tcp                                          ;;
  19. ;;    socket_poll                                               ;;
  20. ;;    socket_status                                             ;;
  21. ;;    socket_read                                               ;;
  22. ;;    socket_write                                              ;;
  23. ;;    socket_write_tcp                                          ;;
  24. ;;                                                              ;;
  25. ;;                                                              ;;
  26. ;;  Changes history:                                            ;;
  27. ;;   22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net          ;;
  28. ;;   11.11.2006 - [Johnny_B] and [smb]                          ;;
  29. ;;                                                              ;;
  30. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  31.  
  32. $Revision: 907 $
  33.  
  34.  
  35. ;
  36. ;  Socket Descriptor + Buffer
  37. ;
  38. ;    0                   1                   2                   3
  39. ;    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  40. ;
  41. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  42. ;  0|                    Status ( of this buffer )                  |
  43. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  44. ;  4|  Application Process ID                                       |
  45. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  46. ;  8|                  Local IP Address                             |
  47. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  48. ; 12| Local IP Port                 | Unused ( set to 0 )           |
  49. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  50. ; 16|                  Remote IP Address                            |
  51. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  52. ; 20| Remote IP Port                | Unused ( set to 0 )           |
  53. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  54. ; 24|   Rx Data Count                                   INTEL format|
  55. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  56. ; 28|                 TCB STATE                         INTEL format|
  57. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  58. ; 32|   TCB Timer (seconds)                             INTEL format|
  59. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  60. ; 36| ISS (Inital Sequence # used by this connection )   INET format|
  61. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  62. ; 40| IRS ( Inital Receive Sequence # )                  INET format|
  63. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  64. ; 44| SND.UNA  Seq # of unack'ed sent packets            INET format|
  65. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  66. ; 48| SND.NXT  Next send seq # to use                    INET format|
  67. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  68. ; 52| SND.WND  Send window                               INET format|
  69. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  70. ; 56| RCV.NXT  Next expected receive sequence #          INET format|
  71. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  72. ; 60| RCV.WND  Receive window                            INET format|
  73. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  74. ; 64| SEG.LEN  Segment length                           INTEL format|
  75. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  76. ; 68| SEG.WND  Segment window                           INTEL format|
  77. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  78. ; 72| Retransmit queue # NOW WINDOW SIZE TIMER          INTEL format|
  79. ;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  80. ; 76|       RX Data Buffer                                          |
  81. ;   +-+-+-..........                                               -+
  82.  
  83.  
  84. ; so, define struct
  85. struc SOCKET
  86. {
  87.    .Status                  dd   ?  ;+00 - Status ( of this buffer )
  88.    .PID                     dd   ?  ;+04 - Application Process ID
  89.    .LocalIP                 dd   ?  ;+08 - Local IP Address
  90.    .LocalPort               dw   ?  ;+12 - Local Port
  91.    .RemoteIP                dd   ?  ;+16 - Remote IP Address
  92.    .RemotePort              dw   ?  ;+20 - Remote Port
  93.    .OrigRemoteIP            dd   ?
  94.    .OrigRemotePort          dw   ?
  95.    .rxDataCount             dd   ?  ;+24 - Rx Data Count
  96.    .TCBState                dd   ?  ;+28 - TCB STATE
  97.    .TCBTimer                dd   ?  ;+32 - TCB Timer (seconds)
  98.    .ISS                     dd   ?  ;+36 - Initial Send Sequence
  99.    .IRS                     dd   ?  ;+40 - Initial Receive Sequence
  100.    .SND_UNA                 dd   ?  ;+44 - Sequence number of unack'ed sent packets
  101.    .SND_NXT                 dd   ?  ;+48 - Next send sequence number to use
  102.    .SND_WND                 dd   ?  ;+52 - Send window
  103.    .RCV_NXT                 dd   ?  ;+56 - Next receive sequence number to use
  104.    .RCV_WND                 dd   ?  ;+60 - Receive window
  105.    .SEG_LEN                 dd   ?  ;+64 - Segment length
  106.    .SEG_WND                 dd   ?  ;+68 - Segment window
  107.    .wndsizeTimer            dd   ?  ;+72 - Retransmit queue # NOW WINDOW SIZE TIMER
  108.    .PrevPtr                 dd   ?
  109.    .NextPtr                 dd   ?
  110.    .rxData                  dd   ?  ;+76 - receive data buffer here
  111. }
  112.  
  113. virtual at 0
  114.   SOCKET SOCKET
  115. end virtual
  116.  
  117. ; simple macro calcing real memory address of SOCKET struct by socket's
  118. ;macro   Index2RealAddr reg
  119. ;{
  120. ;        shl     reg, 12
  121. ;    add     reg, sockets
  122. ;}
  123.  
  124. ;Constants
  125. ; current socket statuses
  126. SOCK_EMPTY         =     0        ; socket not in use
  127. SOCK_OPEN          =     1        ; open issued, but no data sent
  128.  
  129. ; TCP opening modes
  130. SOCKET_PASSIVE     equ     0
  131. SOCKET_ACTIVE      equ     1
  132.  
  133. proc net_socket_alloc stdcall uses ebx ecx edx edi
  134.         stdcall kernel_alloc, SOCKETBUFFSIZE
  135.         DEBUGF  1, "K : net_socket_alloc (0x%x)\n", eax
  136.         or      eax, eax
  137.         jz      .exit
  138.  
  139.         push    eax
  140.         mov     edi, eax
  141.         mov     ecx, SOCKETBUFFSIZE / 4
  142.         cld
  143.         xor     eax, eax
  144.         rep     stosd
  145.         pop     eax
  146.  
  147.         mov     ebx, net_sockets
  148.         push    [ebx + SOCKET.NextPtr]
  149.         mov     [ebx + SOCKET.NextPtr], eax
  150.         mov     [eax + SOCKET.PrevPtr], ebx
  151.         pop     ebx
  152.         mov     [eax + SOCKET.NextPtr], ebx
  153.         or      ebx, ebx
  154.         jz      @f
  155.         mov     [ebx + SOCKET.PrevPtr], eax
  156.  
  157.     @@: mov     ebx, [TASK_BASE]
  158.         mov     ebx, [ebx + TASKDATA.pid]
  159.         mov     [eax + SOCKET.PID], ebx
  160.  
  161.   .exit:
  162.         ret
  163. endp
  164.  
  165. proc net_socket_free stdcall uses ebx ecx edx, sock:DWORD
  166.         mov     eax, [sock]
  167.         DEBUGF  1, "K : net_socket_free (0x%x)\n", eax
  168.         or      eax, eax
  169.         jz      .error
  170.  
  171.         mov     ebx, net_sockets
  172.         mov     ecx, [TASK_BASE]
  173.         mov     ecx, [ecx + TASKDATA.pid]
  174.   .next_socket:
  175.         mov     ebx, [ebx + SOCKET.NextPtr]
  176.         or      ebx, ebx
  177.         jz      .error
  178.         cmp     ebx, eax
  179.         jne     .next_socket
  180.         ;cmp     [ebx + SOCKET.PID], ecx
  181.         ;jne     .next_socket
  182.  
  183.         mov     ebx, [eax + SOCKET.NextPtr]
  184.         mov     eax, [eax + SOCKET.PrevPtr]
  185.         mov     [eax + SOCKET.NextPtr], ebx
  186.         or      ebx, ebx
  187.         jz      @f
  188.         mov     [ebx + SOCKET.PrevPtr], eax
  189.  
  190.     @@: stdcall kernel_free, [sock]
  191.         ret
  192.  
  193.   .error:
  194.         DEBUGF  1, "K :   failed\n"
  195.         ret
  196. endp
  197.  
  198. proc net_socket_num_to_addr stdcall uses ebx ecx, x:DWORD
  199. ; FIXME: do real transform
  200.         mov     eax, [x]
  201.         mov     ebx, net_sockets
  202.         mov     ecx, [TASK_BASE]
  203.         mov     ecx, [ecx + TASKDATA.pid]
  204.   .next_socket:
  205.         mov     ebx, [ebx + SOCKET.NextPtr]
  206.         or      ebx, ebx
  207.         jz      .error
  208.         cmp     ebx, eax
  209.         jne     .next_socket
  210.         ;cmp     [ebx + SOCKET.PID], ecx
  211.         ;jne     .next_socket
  212.         ret
  213.  
  214.   .error:
  215.         xor     eax, eax
  216.         ret
  217. endp
  218.  
  219. proc net_socket_addr_to_num stdcall uses ebx ecx, x:DWORD
  220. ; FIXME: do real transform
  221.         mov     eax, [x]
  222.         mov     ebx, net_sockets
  223.         mov     ecx, [TASK_BASE]
  224.         mov     ecx, [ecx + TASKDATA.pid]
  225.   .next_socket:
  226.         mov     ebx, [ebx + SOCKET.NextPtr]
  227.         or      ebx, ebx
  228.         jz      .error
  229.         cmp     ebx, eax
  230.         jne     .next_socket
  231.         ;cmp     [ebx + SOCKET.PID], ecx
  232.         ;jne     .next_socket
  233.         ret
  234.  
  235.   .error:
  236.         xor     eax, eax
  237.         ret
  238. endp
  239.  
  240. ;***************************************************************************
  241. ;   Function
  242. ;      is_localport_unused
  243. ;
  244. ;   Description
  245. ;         scans through all the active sockets , looking to see if the
  246. ;      port number specified in bx is in use as a localport number.
  247. ;      This is useful when you want a to generate a unique local port
  248. ;      number.
  249. ;          On return, eax = 1 for free, 0 for in use
  250. ;
  251. ;***************************************************************************
  252. proc is_localport_unused stdcall
  253.  
  254.         xchg    bl, bh
  255.  
  256.         xor     eax, eax                        ; Assume the return value is 'free'
  257.         inc     al
  258.         mov     edx, net_sockets
  259.  
  260.   .next_socket:
  261.         mov     edx, [edx + SOCKET.NextPtr]
  262.         or      edx, edx
  263.         jz      .exit
  264.         cmp     [edx + SOCKET.LocalPort], bx
  265.         jne     .next_socket                    ; Return back if the port is not occupied
  266.  
  267.         dec     al                              ; return 'in use'
  268.  
  269.   .exit:
  270.         ret
  271. endp
  272.  
  273.  
  274. ;***************************************************************************
  275. ;   Function
  276. ;      socket_open
  277. ;
  278. ;   Description
  279. ;       find a free socket
  280. ;       local port in ebx
  281. ;       remote port in ecx
  282. ;       remote ip in edx
  283. ;       return socket # in eax, -1 if none available
  284. ;
  285. ;***************************************************************************
  286. proc socket_open stdcall
  287.         call    net_socket_alloc
  288.         or      eax, eax
  289.         jz      .error
  290.  
  291.         DEBUGF  1, "K : socket_open (0x%x)\n", eax
  292.  
  293.         push    eax
  294.  
  295.         mov     [eax + SOCKET.Status], SOCK_OPEN
  296.         xchg    bh, bl
  297.         mov     [eax + SOCKET.LocalPort], bx
  298.         xchg    ch, cl
  299.         mov     [eax + SOCKET.RemotePort], cx
  300.         mov     ebx, [stack_ip]
  301.         mov     [eax + SOCKET.LocalIP], ebx
  302.         mov     [eax + SOCKET.RemoteIP], edx
  303.  
  304.         ;pop     eax      ; Get the socket number back, so we can return it
  305.         stdcall net_socket_addr_to_num
  306.         ret
  307.  
  308.   .error:
  309.         DEBUGF  1, "K : socket_open (fail)\n"
  310.         or      eax, -1
  311.         ret
  312. endp
  313.  
  314.  
  315. ;***************************************************************************
  316. ;   Function
  317. ;      socket_open_tcp
  318. ;
  319. ;   Description
  320. ;       Opens a TCP socket in PASSIVE or ACTIVE mode
  321. ;       find a free socket
  322. ;       local port in ebx ( intel format )
  323. ;       remote port in ecx ( intel format )
  324. ;       remote ip in edx ( in Internet byte order )
  325. ;       Socket open mode in esi  ( SOCKET_PASSIVE or SOCKET_ACTIVE )
  326. ;       return socket # in eax, -1 if none available
  327. ;
  328. ;***************************************************************************
  329. proc socket_open_tcp stdcall
  330. local sockAddr dd ?
  331.  
  332.         cmp     esi, SOCKET_PASSIVE
  333.         jne     .skip_port_check
  334.  
  335.         push    ebx
  336.         mov     eax, ebx
  337.         xchg    al, ah
  338.         mov     ebx, net_sockets
  339.  
  340.   .next_socket:
  341.         mov     ebx, [ebx + SOCKET.NextPtr]
  342.         or      ebx, ebx
  343.         jz      .last_socket
  344.         cmp     [ebx + SOCKET.TCBState], TCB_LISTEN
  345.         jne     .next_socket
  346.         cmp     [ebx + SOCKET.LocalPort], ax
  347.         jne     .next_socket
  348.  
  349.         xchg    al, ah
  350.         DEBUGF  1, "K : error: port %u is listened by 0x%x\n", ax, ebx
  351.         pop     ebx
  352.         jmp     .error
  353.  
  354.   .last_socket:
  355.         pop     ebx
  356.  
  357.   .skip_port_check:
  358.         call    net_socket_alloc
  359.         or      eax, eax
  360.         jz      .error
  361.  
  362.         DEBUGF  1, "K : socket_open_tcp (0x%x)\n", eax
  363.  
  364.         mov     [sockAddr], eax
  365.  
  366.         ; TODO - check this works!
  367.         ;xxx: already 0 (intialized by net_socket_alloc)
  368.         ;mov     [eax + SOCKET.wndsizeTimer], 0     ; Reset the window timer.
  369.  
  370.         xchg    bh, bl
  371.         mov     [eax + SOCKET.LocalPort], bx
  372.         xchg    ch, cl
  373.         mov     [eax + SOCKET.RemotePort], cx
  374.         mov     [eax + SOCKET.OrigRemotePort], cx
  375.         mov     ebx, [stack_ip]
  376.         mov     [eax + SOCKET.LocalIP], ebx
  377.         mov     [eax + SOCKET.RemoteIP], edx
  378.         mov     [eax + SOCKET.OrigRemoteIP], edx
  379.  
  380.         mov     ebx, TCB_LISTEN
  381.         cmp     esi, SOCKET_PASSIVE
  382.         je      @f
  383.         mov     ebx, TCB_SYN_SENT
  384.     @@: mov     [eax + SOCKET.TCBState], ebx            ; Indicate the state of the TCB
  385.  
  386.         cmp     ebx, TCB_LISTEN
  387.         je      .exit
  388.  
  389.         ; Now, if we are in active mode, then we have to send a SYN to the specified remote port
  390.         mov     eax, EMPTY_QUEUE
  391.         call    dequeue
  392.         cmp     ax, NO_BUFFER
  393.         je      .exit
  394.  
  395.         push    eax
  396.  
  397.         mov     bl, TH_SYN
  398.         xor     ecx, ecx
  399.         stdcall build_tcp_packet, [sockAddr]
  400.  
  401.         mov     eax, NET1OUT_QUEUE
  402.         mov     edx, [stack_ip]
  403.         mov     ecx, [sockAddr]
  404.         cmp     edx, [ecx + SOCKET.RemoteIP]
  405.         jne     .not_local
  406.         mov     eax, IPIN_QUEUE
  407.  
  408.   .not_local:
  409.         ; Send it.
  410.         pop     ebx
  411.         call    queue
  412.  
  413.         mov     esi, [sockAddr]
  414.  
  415.         ; increment SND.NXT in socket
  416.         add     esi, SOCKET.SND_NXT
  417.         call    inc_inet_esi
  418.  
  419.   .exit:
  420.         mov     ebx, [sockAddr]
  421.         mov     [ebx + SOCKET.Status], SOCK_OPEN
  422.         ;pop     eax      ; Get the socket number back, so we can return it
  423.         stdcall net_socket_addr_to_num, ebx
  424.         ret
  425.  
  426.   .error:
  427.         DEBUGF  1, "K : socket_open_tcp (fail)\n"
  428.         or      eax, -1
  429.         ret
  430. endp
  431.  
  432.  
  433. ;***************************************************************************
  434. ;   Function
  435. ;      socket_close
  436. ;
  437. ;   Description
  438. ;       socket # in ebx
  439. ;       returns 0 for ok, -1 for socket not open (fail)
  440. ;
  441. ;***************************************************************************
  442. proc socket_close stdcall
  443.         DEBUGF  1, "K : socket_close (0x%x)\n", ebx
  444.         stdcall net_socket_num_to_addr, ebx
  445.         or      eax, eax
  446.         jz      .error
  447.  
  448.         cmp     [eax + SOCKET.Status], dword SOCK_EMPTY
  449.         jz      .error
  450.  
  451.         ; Clear the socket varaibles
  452.         stdcall net_socket_free, eax
  453. ;        mov     edi, eax
  454. ;        xor     eax, eax
  455. ;        mov     ecx, SOCKETHEADERSIZE
  456. ;        cld
  457. ;        rep     stosb
  458.  
  459.         xor     eax, eax
  460.         ret
  461.  
  462.   .error:
  463.         DEBUGF  1, "K : socket_close (fail)\n"
  464.         or      eax, -1
  465.         ret
  466. endp
  467.  
  468.  
  469. ;***************************************************************************
  470. ;   Function
  471. ;      socket_close_tcp
  472. ;
  473. ;   Description
  474. ;       socket # in ebx
  475. ;       returns 0 for ok, -1 for socket not open (fail)
  476. ;
  477. ;***************************************************************************
  478. proc socket_close_tcp stdcall
  479. local sockAddr dd ?
  480.         DEBUGF  1, "K : socket_close_tcp (0x%x)\n", ebx
  481.         ; first, remove any resend entries
  482.         pusha
  483.  
  484.         mov     esi, resendQ
  485.         mov     ecx, 0
  486.  
  487.   .next_resendq:
  488.         cmp     ecx, NUMRESENDENTRIES
  489.         je      .last_resendq       ; None left
  490.         ;cmp     [esi], bl                               ; XTODO: bl -> ebx
  491.         cmp     [esi + 4], ebx
  492.         je      @f                  ; found one
  493.         inc     ecx
  494.         add     esi, 8
  495.         jmp     .next_resendq
  496.  
  497.     ;@@: mov     byte[esi], 0xff                         ; XTODO: 0xff -> 0
  498.     @@: mov     dword[esi + 4], 0
  499.         inc     ecx
  500.         add     esi, 8
  501.         jmp     .next_resendq
  502.  
  503.   .last_resendq:
  504.         popa
  505.  
  506.         stdcall net_socket_num_to_addr, ebx
  507.         or      eax, eax
  508.         jz      .error
  509.  
  510.         mov     ebx, eax
  511.         mov     [sockAddr], eax
  512.         cmp     [ebx + SOCKET.Status], SOCK_EMPTY
  513.         je      .error
  514.  
  515.         cmp     [ebx + SOCKET.TCBState], TCB_LISTEN             ;xxx
  516.         je      .destroy_tcb                                    ;xxx
  517.         cmp     [ebx + SOCKET.TCBState], TCB_SYN_SENT           ;xxx
  518.         je      .destroy_tcb                                    ;xxx
  519.  
  520.         ; Now construct the response, and queue for sending by IP
  521.         mov     eax, EMPTY_QUEUE
  522.         call    dequeue
  523.         cmp     ax, NO_BUFFER
  524.         je      .error
  525.  
  526.         push    eax
  527.  
  528. ;xxx    mov     bl, TH_FIN + TH_ACK
  529.         mov     bl, TH_FIN                                      ;xxx
  530.         xor     ecx, ecx
  531.         xor     esi, esi
  532.         stdcall build_tcp_packet, [sockAddr]
  533.  
  534.         mov      ebx, [sockAddr]
  535.         ; increament SND.NXT in socket
  536.         lea     esi, [ebx + SOCKET.SND_NXT]
  537.         call    inc_inet_esi
  538.  
  539.         ; Get the socket state
  540.         mov     eax, [ebx + SOCKET.TCBState]
  541. ;xxx    cmp     eax, TCB_LISTEN
  542. ;xxx    je      .destroy_tcb
  543. ;xxx    cmp     eax, TCB_SYN_SENT
  544. ;xxx    je      .destroy_tcb
  545.         cmp     eax, TCB_SYN_RECEIVED
  546.         je      .fin_wait_1
  547.         cmp     eax, TCB_ESTABLISHED
  548.         je      .fin_wait_1
  549.  
  550.         ; assume CLOSE WAIT
  551.         ; Send a fin, then enter last-ack state
  552.         ; TODO: check if it's really a TCB_CLOSE_WAIT
  553.         mov     [ebx + SOCKET.TCBState], TCB_LAST_ACK
  554.         jmp     .send
  555.  
  556.   .fin_wait_1:
  557.         ; Send a fin, then enter finwait2 state
  558.         mov     [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1
  559.  
  560.   .send:
  561.         mov     eax, NET1OUT_QUEUE
  562.         mov     edx, [stack_ip]
  563.         mov     ecx, [sockAddr]
  564.         cmp     edx, [ecx + SOCKET.RemoteIP]
  565.         jne     .not_local
  566.         mov     eax, IPIN_QUEUE
  567.  
  568.   .not_local:
  569.         ; Send it.
  570.         pop     ebx
  571.         call    queue
  572.         jmp     .exit
  573.  
  574.   .destroy_tcb:
  575. ;xxx    pop     eax
  576.  
  577.         ; Clear the socket variables
  578. ;xxx    stdcall net_socket_free, [sockAddr]
  579.         stdcall net_socket_free, ebx
  580.  
  581.   .exit:
  582.         xor     eax, eax
  583.         ret
  584.  
  585.   .error:
  586.         DEBUGF  1, "K : socket_close_tcp (fail)\n"
  587.         or      eax, -1
  588.         ret
  589. endp
  590.  
  591.  
  592. ;***************************************************************************
  593. ;   Function
  594. ;      socket_poll
  595. ;
  596. ;   Description
  597. ;       socket # in ebx
  598. ;       returns count in eax.
  599. ;
  600. ;***************************************************************************
  601. proc socket_poll stdcall
  602. ;        DEBUGF  1, "socket_poll(0x%x)\n", ebx
  603.         stdcall net_socket_num_to_addr, ebx
  604.         or      eax, eax
  605.         jz      .error
  606.  
  607.         mov     eax, [eax + SOCKET.rxDataCount]
  608.         ret
  609.  
  610.   .error:
  611.         ;or      eax, -1
  612.         xor     eax, eax
  613.         ret
  614. endp
  615.  
  616.  
  617. ;***************************************************************************
  618. ;   Function
  619. ;      socket_status
  620. ;
  621. ;   Description
  622. ;       socket # in ebx
  623. ;       returns TCB state in eax.
  624. ;
  625. ;***************************************************************************
  626. proc socket_status stdcall
  627. ;;       DEBUGF  1, "socket_status(0x%x)\n", ebx
  628.         stdcall net_socket_num_to_addr, ebx
  629.         or      eax, eax
  630.         jz      .error
  631.  
  632.         mov     eax, [eax + SOCKET.TCBState]
  633.         ret
  634.  
  635.   .error:
  636.         ;or      eax, -1
  637.         xor     eax, eax
  638.         ret
  639. endp
  640.  
  641. ;    Index2RealAddr ebx
  642. ;    mov     eax, [ebx + SOCKET.TCBState]
  643. ;
  644. ;    ret
  645.  
  646.  
  647. ;***************************************************************************
  648. ;   Function
  649. ;      socket_read
  650. ;
  651. ;   Description
  652. ;       socket # in ebx
  653. ;       returns # of bytes remaining in eax, data in bl
  654. ;
  655. ;***************************************************************************
  656. proc socket_read stdcall
  657. ;        DEBUGF  1, "socket_read(0x%x)\n", ebx
  658.         stdcall net_socket_num_to_addr, ebx
  659.         or      eax, eax
  660.         jz      .error
  661.  
  662.         mov     ebx, eax
  663.         mov     eax, [ebx + SOCKET.rxDataCount]         ; get count of bytes
  664.         test    eax, eax
  665.         jz      .error
  666.  
  667.         dec     eax
  668.         mov     esi, ebx            ; esi is address of socket
  669.         mov     [ebx + SOCKET.rxDataCount], eax         ; store new count
  670.         ;movzx   ebx, byte[ebx + SOCKET.rxData]  ; get the byte
  671.         movzx   ebx, byte[ebx + SOCKETHEADERSIZE]  ; get the byte
  672.         add     esi, SOCKETHEADERSIZE
  673.         mov     edi, esi
  674.         inc     esi
  675.  
  676.         mov     ecx, (SOCKETBUFFSIZE - SOCKETHEADERSIZE) / 4
  677.         lea     edi, [ebx + SOCKETHEADERSIZE]
  678.         lea     esi, [edi + 1]
  679.         cld
  680.         rep     movsd
  681.  
  682.         ret
  683.  
  684.   .error:
  685.         ;or      eax, -1
  686.         xor     eax, eax
  687.         xor     ebx, ebx
  688.         ret
  689. endp
  690.  
  691.  
  692. ;***************************************************************************
  693. ;   Function
  694. ;      socket_read_packet
  695. ;
  696. ;   Description
  697. ;       socket # in ebx
  698. ;       datapointer # in ecx
  699. ;       buffer size in edx
  700. ;       returns # of bytes copied in eax
  701. ;
  702. ;***************************************************************************
  703. proc socket_read_packet stdcall
  704. ;        DEBUGF  1, "socket_read_packet(0x%x)\n", ebx
  705.         stdcall net_socket_num_to_addr, ebx                ; get real socket address
  706.         or      eax, eax
  707.         jz      .error
  708.  
  709.         mov     ebx, eax
  710.         mov     eax, [ebx + SOCKET.rxDataCount]            ; get count of bytes
  711.         test    eax, eax                                   ; if count of bytes is zero..
  712.         jz      .exit                                      ; exit function (eax will be zero)
  713.  
  714.         test    edx, edx                                   ; if buffer size is zero, copy all data
  715.         jz      .copy_all_bytes
  716.         cmp     edx, eax                                   ; if buffer size is larger then the bytes of data, copy all data
  717.         jge     .copy_all_bytes
  718.  
  719.         sub     eax, edx                                   ; store new count (data bytes in buffer - bytes we're about to copy)
  720.         mov     [ebx + SOCKET.rxDataCount], eax            ;
  721.         push    eax
  722.         mov     eax, edx                                   ; number of bytes we want to copy must be in eax
  723.         call    .start_copy                                ; copy to the application
  724.  
  725.         mov     esi, ebx                                   ; now we're going to copy the remaining bytes to the beginning
  726.         add     esi, SOCKETHEADERSIZE                      ; we dont need to copy the header
  727.         mov     edi, esi                                   ; edi is where we're going to copy to
  728.         add     esi, edx                                   ; esi is from where we copy
  729.         pop     ecx                                        ; count of bytes we have left
  730.         push    ecx                                        ; push it again so we can re-use it later
  731.         shr     ecx, 2                                     ; divide eax by 4
  732.         cld
  733.         rep     movsd                                      ; copy all full dwords
  734.         pop     ecx
  735.         and     ecx, 3
  736.         rep     movsb                                      ; copy remaining bytes
  737.  
  738.   .exit:
  739.         ret                                                ; at last, exit
  740.  
  741.   .error:
  742.         ;or      eax, -1
  743.         xor     eax, eax
  744.         ret
  745.  
  746.   .copy_all_bytes:
  747.         xor     esi, esi
  748.         mov     [ebx + SOCKET.rxDataCount], esi            ; store new count (zero)
  749.         call    .start_copy
  750.         ret
  751.  
  752.   .start_copy:
  753.         mov     edi, ecx
  754.         mov     esi, ebx
  755.         add     esi, SOCKETHEADERSIZE                      ; we dont need to copy the header
  756.         mov     ecx, eax                                   ; eax is count of bytes
  757.         push    ecx
  758.         shr     ecx, 2                                     ; divide eax by 4
  759.         cld                                                ; copy all full dwords
  760.         rep     movsd
  761.         pop     ecx
  762.         and     ecx, 3
  763.         rep     movsb                                      ; copy the rest bytes
  764.         retn                                               ; exit, or go back to shift remaining bytes if any
  765. endp
  766.  
  767.  
  768. ;***************************************************************************
  769. ;   Function
  770. ;      socket_write
  771. ;
  772. ;   Description
  773. ;       socket in ebx
  774. ;       # of bytes to write in ecx
  775. ;       pointer to data in edx
  776. ;       returns 0 in eax ok, -1 == failed ( invalid socket, or
  777. ;       could not queue IP packet )
  778. ;
  779. ;***************************************************************************
  780. proc socket_write stdcall
  781. ;        DEBUGF  1, "socket_write(0x%x)\n", ebx
  782.         stdcall net_socket_num_to_addr, ebx                ; get real socket address
  783.         or      eax, eax
  784.         jz      .error
  785.  
  786.         mov     ebx, eax
  787.  
  788.         ; If the socket is invalid, return with an error code
  789.         cmp     [ebx + SOCKET.Status], SOCK_EMPTY
  790.         je      .error
  791.  
  792.         mov     eax, EMPTY_QUEUE
  793.         call    dequeue
  794.         cmp     ax, NO_BUFFER
  795.         je      .error
  796.  
  797.         ; Save the queue entry number
  798.         push    eax
  799.  
  800.         ; save the pointers to the data buffer & size
  801.         push    edx
  802.         push    ecx
  803.  
  804.         ; convert buffer pointer eax to the absolute address
  805.         mov     ecx, IPBUFFSIZE
  806.         mul     ecx
  807.         add     eax, IPbuffs
  808.  
  809.         mov     edx, eax
  810.  
  811.         ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
  812.  
  813.         ; Fill in the IP header (some data is in the socket descriptor)
  814.         mov     eax, [ebx + SOCKET.LocalIP]
  815.         mov     [edx + IP_PACKET.SourceAddress], eax
  816.         mov     eax, [ebx + SOCKET.RemoteIP]
  817.         mov     [edx + IP_PACKET.DestinationAddress], eax
  818.  
  819.         mov     [edx + IP_PACKET.VersionAndIHL], 0x45
  820.         mov     [edx + IP_PACKET.TypeOfService], 0
  821.  
  822.         pop     eax                   ; Get the UDP data length
  823.         push    eax
  824.  
  825.         add     eax, 20 + 8           ; add IP header and UDP header lengths
  826.         xchg    al, ah
  827.         mov     [edx + IP_PACKET.TotalLength], ax
  828.         xor     eax, eax
  829.         mov     [edx + IP_PACKET.Identification], ax
  830.         mov     [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040
  831.         mov     [edx + IP_PACKET.TimeToLive], 0x20
  832.         mov     [edx + IP_PACKET.Protocol], PROTOCOL_UDP
  833.  
  834.         ; Checksum left unfilled
  835.         mov     [edx + IP_PACKET.HeaderChecksum], ax
  836.  
  837.         ; Fill in the UDP header (some data is in the socket descriptor)
  838.         mov     ax, [ebx + SOCKET.LocalPort]
  839.         mov     [edx + 20 + UDP_PACKET.SourcePort], ax
  840.  
  841.         mov     ax, [ebx + SOCKET.RemotePort]
  842.         mov     [edx + 20 + UDP_PACKET.DestinationPort], ax
  843.  
  844.         pop     eax
  845.         push    eax
  846.  
  847.         add     eax, 8
  848.         xchg    al, ah
  849.         mov     [edx + 20 + UDP_PACKET.Length], ax
  850.  
  851.         ; Checksum left unfilled
  852.         xor     eax, eax
  853.         mov     [edx + 20 + UDP_PACKET.Checksum], ax
  854.  
  855.         pop     ecx                  ; count of bytes to send
  856.         mov     ebx, ecx             ; need the length later
  857.         pop     eax                  ; get callers ptr to data to send
  858.  
  859.         ; Get the address of the callers data
  860.         mov     edi, [TASK_BASE]
  861.         add     edi, TASKDATA.mem_start
  862.         add     eax, [edi]
  863.         mov     esi, eax
  864.  
  865.         mov     edi, edx
  866.         add     edi, 28
  867.         cld
  868.         rep     movsb               ; copy the data across
  869.  
  870.         ; we have edx as IPbuffer ptr.
  871.         ; Fill in the UDP checksum
  872.         ; First, fill in pseudoheader
  873.         mov     eax, [edx + IP_PACKET.SourceAddress]
  874.         mov     [pseudoHeader], eax
  875.         mov     eax, [edx + IP_PACKET.DestinationAddress]
  876.         mov     [pseudoHeader + 4], eax
  877.         mov     word[pseudoHeader + 8], PROTOCOL_UDP shl 8 + 0      ; 0 + protocol
  878.         add     ebx, 8
  879.         mov     eax, ebx
  880.         xchg    al, ah
  881.         mov     [pseudoHeader + 10], ax
  882.  
  883.         mov     eax, pseudoHeader
  884.         mov     [checkAdd1], eax
  885.         mov     [checkSize1], word 12
  886.         mov     eax, edx
  887.         add     eax, 20
  888.         mov     [checkAdd2], eax
  889.         mov     eax, ebx
  890.         mov     [checkSize2], ax      ; was eax!! mjh 8/7/02
  891.  
  892.         call    checksum
  893.  
  894.         ; store it in the UDP checksum ( in the correct order! )
  895.         mov     ax, [checkResult]
  896.  
  897.         ; If the UDP checksum computes to 0, we must make it 0xffff
  898.         ; (0 is reserved for 'not used')
  899.         test    ax, ax
  900.         jnz     @f
  901.         mov     ax, 0xffff
  902.  
  903.     @@: xchg    al, ah
  904.         mov     [edx + 20 + UDP_PACKET.Checksum], ax
  905.  
  906.         ; Fill in the IP header checksum
  907.         GET_IHL ecx,edx              ; get IP-Header length
  908.         stdcall checksum_jb,edx,ecx  ; buf_ptr, buf_size
  909.         xchg    al, ah
  910.         mov     [edx + IP_PACKET.HeaderChecksum], ax
  911.  
  912.         ; Check destination IP address.
  913.         ; If it is the local host IP, route it back to IP_RX
  914.  
  915.         pop     ebx
  916.  
  917.         mov     eax, NET1OUT_QUEUE
  918.         mov     ecx, [edx + SOCKET.RemoteIP]
  919.         mov     edx, [stack_ip]
  920.         cmp     edx, ecx
  921.         jne     .not_local
  922.         mov     eax, IPIN_QUEUE
  923.  
  924.   .not_local:
  925.         ; Send it.
  926.         call    queue
  927.  
  928.         xor     eax, eax
  929.         ret
  930.  
  931.   .error:
  932.         or      eax, -1
  933.         ret
  934. endp
  935.  
  936.  
  937. ;***************************************************************************
  938. ;   Function
  939. ;      socket_write_tcp
  940. ;
  941. ;   Description
  942. ;       socket in ebx
  943. ;       # of bytes to write in ecx
  944. ;       pointer to data in edx
  945. ;       returns 0 in eax ok, -1 == failed ( invalid socket, or
  946. ;       could not queue IP packet )
  947. ;
  948. ;***************************************************************************
  949. proc socket_write_tcp stdcall
  950. local sockAddr dd ?
  951.  
  952. ;        DEBUGF  1, "socket_write_tcp(0x%x)\n", ebx
  953.         stdcall net_socket_num_to_addr, ebx
  954.         or      eax, eax
  955.         jz      .error
  956.  
  957.         mov     ebx, eax
  958.         mov     [sockAddr], ebx
  959.  
  960.         ; If the socket is invalid, return with an error code
  961.         cmp     [ebx + SOCKET.Status], SOCK_EMPTY
  962.         je      .error
  963.  
  964.         ; If the sockets window timer is nonzero, do not queue packet
  965.         ; TODO - done
  966.         cmp     [ebx + SOCKET.wndsizeTimer], 0
  967.         jne     .error
  968.  
  969.         mov     eax, EMPTY_QUEUE
  970.         call    dequeue
  971.         cmp     ax, NO_BUFFER
  972.         je      .error
  973.  
  974.         push    eax
  975.  
  976.         ; Get the address of the callers data
  977.         mov     edi, [TASK_BASE]
  978.         add     edi, TASKDATA.mem_start
  979.         add     edx, [edi]
  980.         mov     esi, edx
  981.  
  982.         pop     eax
  983.         push    eax
  984.  
  985.         push    ecx
  986.         mov     bl, TH_ACK
  987.         stdcall build_tcp_packet, [sockAddr]
  988.         pop     ecx
  989.  
  990.         ; Check destination IP address.
  991.         ; If it is the local host IP, route it back to IP_RX
  992.  
  993.         pop     ebx
  994.         push    ecx
  995.  
  996.         mov     eax, NET1OUT_QUEUE
  997.         mov     edx, [stack_ip]
  998.         mov     ecx, [sockAddr]
  999.         cmp     edx, [ecx + SOCKET.RemoteIP]
  1000.         jne     .not_local
  1001.         mov     eax, IPIN_QUEUE
  1002.  
  1003.   .not_local:
  1004.         pop     ecx
  1005.         push    ebx                 ; save ipbuffer number
  1006.  
  1007.         call    queue
  1008.  
  1009.         mov     esi, [sockAddr]
  1010.  
  1011.         ; increament SND.NXT in socket
  1012.         ; Amount to increment by is in ecx
  1013.         add     esi, SOCKET.SND_NXT
  1014.         call    add_inet_esi
  1015.  
  1016.         pop     ebx
  1017.  
  1018.         ; Copy the IP buffer to a resend queue
  1019.         ; If there isn't one, dont worry about it for now
  1020.         mov     esi, resendQ
  1021.         mov     ecx, 0
  1022.  
  1023.   .next_resendq:
  1024.         cmp     ecx, NUMRESENDENTRIES
  1025.         je      .exit              ; None found
  1026.         ;cmp     byte[esi], 0xff                                 ; XTODO: 0xff -> 0
  1027.         cmp     dword[esi + 4], 0
  1028.         je      @f                 ; found one
  1029.         inc     ecx
  1030.         add     esi, 8
  1031.         jmp     .next_resendq
  1032.  
  1033.     @@: push    ebx
  1034.  
  1035.         ; OK, we have a buffer descriptor ptr in esi.
  1036.         ; resend entry # in ecx
  1037.         ;  Populate it
  1038.         ;  socket #
  1039.         ;  retries count
  1040.         ;  retry time
  1041.         ;  fill IP buffer associated with this descriptor
  1042.  
  1043.         stdcall net_socket_addr_to_num, [sockAddr]
  1044.         ;mov     [esi], al                               ; XTODO: al -> eax
  1045.         mov     [esi + 4], eax
  1046.         mov     byte[esi + 1], TCP_RETRIES
  1047.         mov     word[esi + 2], TCP_TIMEOUT
  1048.  
  1049.         inc     ecx
  1050.         ; Now get buffer location, and copy buffer across. argh! more copying,,
  1051.         mov     edi, resendBuffer - IPBUFFSIZE
  1052.  
  1053.     @@: add     edi, IPBUFFSIZE
  1054.         loop    @b
  1055.  
  1056.         ; we have dest buffer location in edi
  1057.         pop     eax
  1058.         ; convert source buffer pointer eax to the absolute address
  1059.         mov     ecx, IPBUFFSIZE
  1060.         mul     ecx
  1061.         add     eax, IPbuffs
  1062.         mov     esi, eax
  1063.  
  1064.         ; do copy
  1065.         mov     ecx, IPBUFFSIZE
  1066.         cld
  1067.         rep     movsb
  1068.  
  1069.   .exit:
  1070.         xor     eax, eax
  1071.         ret
  1072.  
  1073.   .error:
  1074.         or      eax, -1
  1075.         ret
  1076. endp
  1077.