Subversion Repositories Kolibri OS

Rev

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