Subversion Repositories Kolibri OS

Rev

Rev 909 | 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: 915 $
  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.    .PrevPtr                 dd   ?
  88.    .NextPtr                 dd   ?
  89.    .Status                  dd   ?  ;+00 - Status ( of this buffer )
  90.    .PID                     dd   ?  ;+04 - Application Process ID
  91.    .LocalIP                 dd   ?  ;+08 - Local IP Address
  92.    .LocalPort               dw   ?  ;+12 - Local Port
  93.    .RemoteIP                dd   ?  ;+16 - Remote IP Address
  94.    .RemotePort              dw   ?  ;+20 - Remote Port
  95.    .OrigRemoteIP            dd   ?
  96.    .OrigRemotePort          dw   ?
  97.    .rxDataCount             dd   ?  ;+24 - Rx Data Count
  98.    .TCBState                dd   ?  ;+28 - TCB STATE
  99.    .TCBTimer                dd   ?  ;+32 - TCB Timer (seconds)
  100.    .ISS                     dd   ?  ;+36 - Initial Send Sequence
  101.    .IRS                     dd   ?  ;+40 - Initial Receive Sequence
  102.    .SND_UNA                 dd   ?  ;+44 - Sequence number of unack'ed sent packets
  103.    .SND_NXT                 dd   ?  ;+48 - Next send sequence number to use
  104.    .SND_WND                 dd   ?  ;+52 - Send window
  105.    .RCV_NXT                 dd   ?  ;+56 - Next receive sequence number to use
  106.    .RCV_WND                 dd   ?  ;+60 - Receive window
  107.    .SEG_LEN                 dd   ?  ;+64 - Segment length
  108.    .SEG_WND                 dd   ?  ;+68 - Segment window
  109.    .wndsizeTimer            dd   ?  ;+72 - Retransmit queue # NOW WINDOW SIZE TIMER
  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.         xor     eax, eax
  612.         ret
  613. endp
  614.  
  615.  
  616. ;***************************************************************************
  617. ;   Function
  618. ;      socket_status
  619. ;
  620. ;   Description
  621. ;       socket # in ebx
  622. ;       returns TCB state in eax.
  623. ;
  624. ;***************************************************************************
  625. proc socket_status stdcall
  626. ;;       DEBUGF  1, "socket_status(0x%x)\n", ebx
  627.         stdcall net_socket_num_to_addr, ebx
  628.         or      eax, eax
  629.         jz      .error
  630.  
  631.         mov     eax, [eax + SOCKET.TCBState]
  632.         ret
  633.  
  634.   .error:
  635.         xor     eax, eax
  636.         ret
  637. endp
  638.  
  639. ;    Index2RealAddr ebx
  640. ;    mov     eax, [ebx + SOCKET.TCBState]
  641. ;
  642. ;    ret
  643.  
  644.  
  645. ;***************************************************************************
  646. ;   Function
  647. ;      socket_read
  648. ;
  649. ;   Description
  650. ;       socket # in ebx
  651. ;       returns # of bytes remaining in eax, data in bl
  652. ;
  653. ;***************************************************************************
  654. proc socket_read stdcall
  655. ;        DEBUGF  1, "socket_read(0x%x)\n", ebx
  656.         stdcall net_socket_num_to_addr, ebx
  657.         or      eax, eax
  658.         jz      .error
  659.  
  660.         mov     ebx, eax
  661.         mov     eax, [ebx + SOCKET.rxDataCount]         ; get count of bytes
  662.         test    eax, eax
  663.         jz      .error
  664.  
  665.         dec     eax
  666.         mov     esi, ebx                                ; esi is address of socket
  667.         mov     [ebx + SOCKET.rxDataCount], eax         ; store new count
  668.         movzx   ebx, byte[ebx + SOCKET.rxData]          ; get the byte
  669.  
  670.         mov     ecx, SOCKETBUFFSIZE - SOCKET.rxData - 1
  671.         lea     edi, [esi + SOCKET.rxData]
  672.         lea     esi, [edi + 1]
  673.         cld
  674.         push    ecx
  675.         shr     ecx, 2
  676.         rep     movsd
  677.         pop     ecx
  678.         and     ecx, 3
  679.         rep     movsb
  680.  
  681.         ret
  682.  
  683.   .error:
  684.         xor     eax, eax
  685.         xor     ebx, ebx
  686.         ret
  687. endp
  688.  
  689.  
  690. ;***************************************************************************
  691. ;   Function
  692. ;      socket_read_packet
  693. ;
  694. ;   Description
  695. ;       socket # in ebx
  696. ;       datapointer # in ecx
  697. ;       buffer size in edx
  698. ;       returns # of bytes copied in eax
  699. ;
  700. ;***************************************************************************
  701. proc socket_read_packet stdcall
  702. ;        DEBUGF  1, "socket_read_packet(0x%x)\n", ebx
  703.         stdcall net_socket_num_to_addr, ebx                ; get real socket address
  704.         or      eax, eax
  705.         jz      .error
  706.  
  707.         mov     ebx, eax
  708.         mov     eax, [ebx + SOCKET.rxDataCount]            ; get count of bytes
  709.         test    eax, eax                                   ; if count of bytes is zero..
  710.         jz      .exit                                      ; exit function (eax will be zero)
  711.  
  712.         test    edx, edx                                   ; if buffer size is zero, copy all data
  713.         jz      .copy_all_bytes
  714.         cmp     edx, eax                                   ; if buffer size is larger then the bytes of data, copy all data
  715.         jge     .copy_all_bytes
  716.  
  717.         sub     eax, edx                                   ; store new count (data bytes in buffer - bytes we're about to copy)
  718.         mov     [ebx + SOCKET.rxDataCount], eax            ;
  719.         push    eax
  720.         mov     eax, edx                                   ; number of bytes we want to copy must be in eax
  721.         call    .start_copy                                ; copy to the application
  722.  
  723.         mov     esi, ebx                                   ; now we're going to copy the remaining bytes to the beginning
  724.         add     esi, SOCKET.rxData                         ; we dont need to copy the header
  725.         mov     edi, esi                                   ; edi is where we're going to copy to
  726.         add     esi, edx                                   ; esi is from where we copy
  727.         pop     ecx                                        ; count of bytes we have left
  728.         push    ecx                                        ; push it again so we can re-use it later
  729.         shr     ecx, 2                                     ; divide eax by 4
  730.         cld
  731.         rep     movsd                                      ; copy all full dwords
  732.         pop     ecx
  733.         and     ecx, 3
  734.         rep     movsb                                      ; copy remaining bytes
  735.  
  736.   .exit:
  737.         ret                                                ; at last, exit
  738.  
  739.   .error:
  740.         xor     eax, eax
  741.         ret
  742.  
  743.   .copy_all_bytes:
  744.         xor     esi, esi
  745.         mov     [ebx + SOCKET.rxDataCount], esi            ; store new count (zero)
  746.         call    .start_copy
  747.         ret
  748.  
  749.   .start_copy:
  750.         mov     edi, ecx
  751.         mov     esi, ebx
  752.         add     esi, SOCKET.rxData                         ; we dont need to copy the header
  753.         mov     ecx, eax                                   ; eax is count of bytes
  754.         push    ecx
  755.         shr     ecx, 2                                     ; divide eax by 4
  756.         cld                                                ; copy all full dwords
  757.         rep     movsd
  758.         pop     ecx
  759.         and     ecx, 3
  760.         rep     movsb                                      ; copy the rest bytes
  761.         retn                                               ; exit, or go back to shift remaining bytes if any
  762. endp
  763.  
  764.  
  765. ;***************************************************************************
  766. ;   Function
  767. ;      socket_write
  768. ;
  769. ;   Description
  770. ;       socket in ebx
  771. ;       # of bytes to write in ecx
  772. ;       pointer to data in edx
  773. ;       returns 0 in eax ok, -1 == failed ( invalid socket, or
  774. ;       could not queue IP packet )
  775. ;
  776. ;***************************************************************************
  777. proc socket_write stdcall
  778. ;        DEBUGF  1, "socket_write(0x%x)\n", ebx
  779.         stdcall net_socket_num_to_addr, ebx                ; get real socket address
  780.         or      eax, eax
  781.         jz      .error
  782.  
  783.         mov     ebx, eax
  784.  
  785.         ; If the socket is invalid, return with an error code
  786.         cmp     [ebx + SOCKET.Status], SOCK_EMPTY
  787.         je      .error
  788.  
  789.         mov     eax, EMPTY_QUEUE
  790.         call    dequeue
  791.         cmp     ax, NO_BUFFER
  792.         je      .error
  793.  
  794.         ; Save the queue entry number
  795.         push    eax
  796.  
  797.         ; save the pointers to the data buffer & size
  798.         push    edx
  799.         push    ecx
  800.  
  801.         ; convert buffer pointer eax to the absolute address
  802.         mov     ecx, IPBUFFSIZE
  803.         mul     ecx
  804.         add     eax, IPbuffs
  805.  
  806.         mov     edx, eax
  807.  
  808.         ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
  809.  
  810.         ; Fill in the IP header (some data is in the socket descriptor)
  811.         mov     eax, [ebx + SOCKET.LocalIP]
  812.         mov     [edx + IP_PACKET.SourceAddress], eax
  813.         mov     eax, [ebx + SOCKET.RemoteIP]
  814.         mov     [edx + IP_PACKET.DestinationAddress], eax
  815.  
  816.         mov     [edx + IP_PACKET.VersionAndIHL], 0x45
  817.         mov     [edx + IP_PACKET.TypeOfService], 0
  818.  
  819.         pop     eax                   ; Get the UDP data length
  820.         push    eax
  821.  
  822.         add     eax, 20 + 8           ; add IP header and UDP header lengths
  823.         xchg    al, ah
  824.         mov     [edx + IP_PACKET.TotalLength], ax
  825.         xor     eax, eax
  826.         mov     [edx + IP_PACKET.Identification], ax
  827.         mov     [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040
  828.         mov     [edx + IP_PACKET.TimeToLive], 0x20
  829.         mov     [edx + IP_PACKET.Protocol], PROTOCOL_UDP
  830.  
  831.         ; Checksum left unfilled
  832.         mov     [edx + IP_PACKET.HeaderChecksum], ax
  833.  
  834.         ; Fill in the UDP header (some data is in the socket descriptor)
  835.         mov     ax, [ebx + SOCKET.LocalPort]
  836.         mov     [edx + 20 + UDP_PACKET.SourcePort], ax
  837.  
  838.         mov     ax, [ebx + SOCKET.RemotePort]
  839.         mov     [edx + 20 + UDP_PACKET.DestinationPort], ax
  840.  
  841.         pop     eax
  842.         push    eax
  843.  
  844.         add     eax, 8
  845.         xchg    al, ah
  846.         mov     [edx + 20 + UDP_PACKET.Length], ax
  847.  
  848.         ; Checksum left unfilled
  849.         xor     eax, eax
  850.         mov     [edx + 20 + UDP_PACKET.Checksum], ax
  851.  
  852.         pop     ecx                  ; count of bytes to send
  853.         mov     ebx, ecx             ; need the length later
  854.         pop     eax                  ; get callers ptr to data to send
  855.  
  856.         ; Get the address of the callers data
  857.         mov     edi, [TASK_BASE]
  858.         add     edi, TASKDATA.mem_start
  859.         add     eax, [edi]
  860.         mov     esi, eax
  861.  
  862.         mov     edi, edx
  863.         add     edi, 28
  864.         cld
  865.         rep     movsb               ; copy the data across
  866.  
  867.         ; we have edx as IPbuffer ptr.
  868.         ; Fill in the UDP checksum
  869.         ; First, fill in pseudoheader
  870.         mov     eax, [edx + IP_PACKET.SourceAddress]
  871.         mov     [pseudoHeader], eax
  872.         mov     eax, [edx + IP_PACKET.DestinationAddress]
  873.         mov     [pseudoHeader + 4], eax
  874.         mov     word[pseudoHeader + 8], PROTOCOL_UDP shl 8 + 0      ; 0 + protocol
  875.         add     ebx, 8
  876.         mov     eax, ebx
  877.         xchg    al, ah
  878.         mov     [pseudoHeader + 10], ax
  879.  
  880.         mov     eax, pseudoHeader
  881.         mov     [checkAdd1], eax
  882.         mov     [checkSize1], word 12
  883.         mov     eax, edx
  884.         add     eax, 20
  885.         mov     [checkAdd2], eax
  886.         mov     eax, ebx
  887.         mov     [checkSize2], ax      ; was eax!! mjh 8/7/02
  888.  
  889.         call    checksum
  890.  
  891.         ; store it in the UDP checksum ( in the correct order! )
  892.         mov     ax, [checkResult]
  893.  
  894.         ; If the UDP checksum computes to 0, we must make it 0xffff
  895.         ; (0 is reserved for 'not used')
  896.         test    ax, ax
  897.         jnz     @f
  898.         mov     ax, 0xffff
  899.  
  900.     @@: xchg    al, ah
  901.         mov     [edx + 20 + UDP_PACKET.Checksum], ax
  902.  
  903.         ; Fill in the IP header checksum
  904.         GET_IHL ecx,edx              ; get IP-Header length
  905.         stdcall checksum_jb,edx,ecx  ; buf_ptr, buf_size
  906.         xchg    al, ah
  907.         mov     [edx + IP_PACKET.HeaderChecksum], ax
  908.  
  909.         ; Check destination IP address.
  910.         ; If it is the local host IP, route it back to IP_RX
  911.  
  912.         pop     ebx
  913.  
  914.         mov     eax, NET1OUT_QUEUE
  915.         mov     ecx, [edx + SOCKET.RemoteIP]
  916.         mov     edx, [stack_ip]
  917.         cmp     edx, ecx
  918.         jne     .not_local
  919.         mov     eax, IPIN_QUEUE
  920.  
  921.   .not_local:
  922.         ; Send it.
  923.         call    queue
  924.  
  925.         xor     eax, eax
  926.         ret
  927.  
  928.   .error:
  929.         or      eax, -1
  930.         ret
  931. endp
  932.  
  933.  
  934. ;***************************************************************************
  935. ;   Function
  936. ;      socket_write_tcp
  937. ;
  938. ;   Description
  939. ;       socket in ebx
  940. ;       # of bytes to write in ecx
  941. ;       pointer to data in edx
  942. ;       returns 0 in eax ok, -1 == failed ( invalid socket, or
  943. ;       could not queue IP packet )
  944. ;
  945. ;***************************************************************************
  946. proc socket_write_tcp stdcall
  947. local sockAddr dd ?
  948.  
  949. ;        DEBUGF  1, "socket_write_tcp(0x%x)\n", ebx
  950.         stdcall net_socket_num_to_addr, ebx
  951.         or      eax, eax
  952.         jz      .error
  953.  
  954.         mov     ebx, eax
  955.         mov     [sockAddr], ebx
  956.  
  957.         ; If the socket is invalid, return with an error code
  958.         cmp     [ebx + SOCKET.Status], SOCK_EMPTY
  959.         je      .error
  960.  
  961.         ; If the sockets window timer is nonzero, do not queue packet
  962.         ; TODO - done
  963.         cmp     [ebx + SOCKET.wndsizeTimer], 0
  964.         jne     .error
  965.  
  966.         mov     eax, EMPTY_QUEUE
  967.         call    dequeue
  968.         cmp     ax, NO_BUFFER
  969.         je      .error
  970.  
  971.         push    eax
  972.  
  973.         ; Get the address of the callers data
  974.         mov     edi, [TASK_BASE]
  975.         add     edi, TASKDATA.mem_start
  976.         add     edx, [edi]
  977.         mov     esi, edx
  978.  
  979.         pop     eax
  980.         push    eax
  981.  
  982.         push    ecx
  983.         mov     bl, TH_ACK
  984.         stdcall build_tcp_packet, [sockAddr]
  985.         pop     ecx
  986.  
  987.         ; Check destination IP address.
  988.         ; If it is the local host IP, route it back to IP_RX
  989.  
  990.         pop     ebx
  991.         push    ecx
  992.  
  993.         mov     eax, NET1OUT_QUEUE
  994.         mov     edx, [stack_ip]
  995.         mov     ecx, [sockAddr]
  996.         cmp     edx, [ecx + SOCKET.RemoteIP]
  997.         jne     .not_local
  998.         mov     eax, IPIN_QUEUE
  999.  
  1000.   .not_local:
  1001.         pop     ecx
  1002.         push    ebx                 ; save ipbuffer number
  1003.  
  1004.         call    queue
  1005.  
  1006.         mov     esi, [sockAddr]
  1007.  
  1008.         ; increament SND.NXT in socket
  1009.         ; Amount to increment by is in ecx
  1010.         add     esi, SOCKET.SND_NXT
  1011.         call    add_inet_esi
  1012.  
  1013.         pop     ebx
  1014.  
  1015.         ; Copy the IP buffer to a resend queue
  1016.         ; If there isn't one, dont worry about it for now
  1017.         mov     esi, resendQ
  1018.         mov     ecx, 0
  1019.  
  1020.   .next_resendq:
  1021.         cmp     ecx, NUMRESENDENTRIES
  1022.         je      .exit              ; None found
  1023.         ;cmp     byte[esi], 0xff                                 ; XTODO: 0xff -> 0
  1024.         cmp     dword[esi + 4], 0
  1025.         je      @f                 ; found one
  1026.         inc     ecx
  1027.         add     esi, 8
  1028.         jmp     .next_resendq
  1029.  
  1030.     @@: push    ebx
  1031.  
  1032.         ; OK, we have a buffer descriptor ptr in esi.
  1033.         ; resend entry # in ecx
  1034.         ;  Populate it
  1035.         ;  socket #
  1036.         ;  retries count
  1037.         ;  retry time
  1038.         ;  fill IP buffer associated with this descriptor
  1039.  
  1040.         stdcall net_socket_addr_to_num, [sockAddr]
  1041.         ;mov     [esi], al                               ; XTODO: al -> eax
  1042.         mov     [esi + 4], eax
  1043.         mov     byte[esi + 1], TCP_RETRIES
  1044.         mov     word[esi + 2], TCP_TIMEOUT
  1045.  
  1046.         inc     ecx
  1047.         ; Now get buffer location, and copy buffer across. argh! more copying,,
  1048.         mov     edi, resendBuffer - IPBUFFSIZE
  1049.  
  1050.     @@: add     edi, IPBUFFSIZE
  1051.         loop    @b
  1052.  
  1053.         ; we have dest buffer location in edi
  1054.         pop     eax
  1055.         ; convert source buffer pointer eax to the absolute address
  1056.         mov     ecx, IPBUFFSIZE
  1057.         mul     ecx
  1058.         add     eax, IPbuffs
  1059.         mov     esi, eax
  1060.  
  1061.         ; do copy
  1062.         mov     ecx, IPBUFFSIZE
  1063.         cld
  1064.         rep     movsb
  1065.  
  1066.   .exit:
  1067.         xor     eax, eax
  1068.         ret
  1069.  
  1070.   .error:
  1071.         or      eax, -1
  1072.         ret
  1073. endp
  1074.