Subversion Repositories Kolibri OS

Rev

Rev 593 | 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: 738 $
  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 offset from
  81. ; 76|       RX Data                                                 |
  82. ;   +-+-+-..........                                               -+
  83.  
  84.  
  85. ; so, define struct
  86. struc SOCKET
  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.    .UnusedL                 dw   ?  ;+14 - may be removed in future
  92.    .RemoteIP                dd   ?  ;+16 - Remote IP Address
  93.    .RemotePort              dw   ?  ;+20 - Remote Port
  94.    .UnusedR                 dw   ?  ;+22 - may be removed in future
  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.    .rxData                  dd   ?  ;+76 - receive data buffer here
  109. }
  110.  
  111. virtual at 0
  112.   SOCKET SOCKET
  113. end virtual
  114.  
  115. ; simple macro calcing real memory address of SOCKET struct by socket's
  116. macro   Index2RealAddr reg
  117. {
  118.         shl     reg, 12
  119.     add     reg, sockets
  120. }
  121.  
  122. ;Constants
  123. ; current socket statuses
  124. SOCK_EMPTY        equ     0        ; socket not in use
  125. SOCK_OPEN         equ     1        ; open issued, but no data sent
  126.  
  127. ; TCP opening modes
  128. SOCKET_PASSIVE    equ     0
  129. SOCKET_ACTIVE     equ     1
  130.  
  131. ;***************************************************************************
  132. ;   Function
  133. ;      is_localport_unused
  134. ;
  135. ;   Description
  136. ;         scans through all the active sockets , looking to see if the
  137. ;      port number specified in bx is in use as a localport number.
  138. ;      This is useful when you want a to generate a unique local port
  139. ;      number.
  140. ;          On return, eax = 1 for free, 0 for in use
  141. ;
  142. ;***************************************************************************
  143. is_localport_unused:
  144.     mov     al, bh
  145.     mov     ah, bl
  146.     mov     bx, ax
  147.  
  148.     mov     edx, SOCKETBUFFSIZE * NUM_SOCKETS
  149.     mov     ecx, NUM_SOCKETS
  150.     mov     eax, 0                    ; Assume the return value is 'in use'
  151.  
  152. ilu1:
  153.     sub     edx, SOCKETBUFFSIZE
  154.     cmp     [edx + sockets + SOCKET.LocalPort], bx
  155.     loopnz  ilu1                  ; Return back if the socket is occupied
  156.  
  157.     jz      ilu_exit
  158.     inc     eax                         ; return port not in use
  159.  
  160. ilu_exit:
  161.     ret
  162.  
  163.  
  164.  
  165. ;***************************************************************************
  166. ;   Function
  167. ;      get_free_socket
  168. ;
  169. ;   Description
  170. ;
  171. ;***************************************************************************
  172. get_free_socket:
  173.     push    ecx
  174.     mov     eax, SOCKETBUFFSIZE * NUM_SOCKETS
  175.     mov     ecx, NUM_SOCKETS
  176.  
  177. gfs1:
  178.     sub     eax, SOCKETBUFFSIZE
  179.     cmp     [eax + sockets + SOCKET.Status], dword SOCK_EMPTY
  180.     loopnz  gfs1                  ; Return back if the socket is occupied
  181.     mov     eax, ecx
  182.     pop     ecx
  183.     jz      gfs_exit
  184.     mov     eax, 0xFFFFFFFF
  185.  
  186. gfs_exit:
  187.     ret
  188.  
  189.  
  190. ;***************************************************************************
  191. ;   Function
  192. ;      socket_open
  193. ;
  194. ;   Description
  195. ;       find a free socket
  196. ;       local port in ebx
  197. ;       remote port in ecx
  198. ;       remote ip in edx
  199. ;       return socket # in eax, -1 if none available
  200. ;
  201. ;***************************************************************************
  202. socket_open:
  203.     call    get_free_socket
  204.  
  205.     cmp     eax, 0xFFFFFFFF
  206.     jz      so_exit
  207.  
  208.     ; ax holds the socket number that is free. Get real address
  209.     push    eax
  210.     Index2RealAddr eax
  211.  
  212.     mov     [eax + SOCKET.Status], dword SOCK_OPEN
  213.  
  214.     xchg    bh, bl
  215.     mov     [eax + SOCKET.LocalPort], bx
  216.     xchg    ch, cl
  217.     mov     [eax + SOCKET.RemotePort], cx
  218.  
  219.     mov     ebx, [stack_ip]
  220.     mov     [eax + SOCKET.LocalIP], ebx
  221.     mov     [eax + SOCKET.RemoteIP], edx
  222.     mov     [eax + SOCKET.rxDataCount], dword 0      ; recieved data count
  223.  
  224.     mov     esi, [TASK_BASE]
  225.     mov     ebx, [esi+TASKDATA.pid]
  226.     mov     [eax + SOCKET.PID], ebx         ; save the process ID
  227.     pop     eax      ; Get the socket number back, so we can return it
  228.  
  229. so_exit:
  230.     ret
  231.  
  232.  
  233.  
  234. ;***************************************************************************
  235. ;   Function
  236. ;      socket_open_tcp
  237. ;
  238. ;   Description
  239. ;       Opens a TCP socket in PASSIVE or ACTIVE mode
  240. ;       find a free socket
  241. ;       local port in ebx ( intel format )
  242. ;       remote port in ecx ( intel format )
  243. ;       remote ip in edx ( in Internet byte order )
  244. ;       Socket open mode in esi  ( SOCKET_PASSIVE or SOCKET_ACTIVE )
  245. ;       return socket # in eax, -1 if none available
  246. ;
  247. ;***************************************************************************
  248. socket_open_tcp:
  249.     call    get_free_socket
  250.  
  251.     cmp     eax, 0xFFFFFFFF
  252.     jz      so_exit
  253.  
  254.     ; ax holds the socket number that is free. Get real address
  255.     push eax
  256.     Index2RealAddr eax
  257.  
  258.     mov     [sktAddr], eax
  259.     mov     [eax], dword SOCK_OPEN
  260.  
  261.     ; TODO - check this works!
  262.     mov     [eax + SOCKET.wndsizeTimer], dword 0     ; Reset the window timer.
  263.  
  264.         xchg    bh, bl
  265.         mov     [eax + SOCKET.LocalPort], bx
  266. ;    mov     [eax + 12], byte bh      ; Local port ( LS 16 bits )
  267. ;    mov     [eax + 13], byte bl      ; Local port ( LS 16 bits )
  268.  
  269.         xchg    ch, cl
  270.         mov     [eax + SOCKET.RemotePort], cx
  271. ;    mov     [eax + 20], ch         ; Remote Port ( LS 16 bits )
  272. ;    mov     [eax + 21], cl         ; Remote Port ( LS 16 bits )
  273.  
  274.     mov     ebx, [stack_ip]
  275.     mov     [eax + SOCKET.LocalIP], ebx
  276.     mov     [eax + SOCKET.RemoteIP], edx
  277.     mov     [eax + SOCKET.rxDataCount], dword 0
  278.  
  279.     ; Now fill in TCB state
  280.     mov     ebx, TCB_LISTEN
  281.     cmp     esi, SOCKET_PASSIVE
  282.     jz      sot_001
  283.     mov     ebx, TCB_SYN_SENT
  284.  
  285. sot_001:
  286.     mov     [eax + SOCKET.TCBState], ebx            ; Indicate the state of the TCB
  287.  
  288.     mov     esi, [TASK_BASE]
  289.     mov     ecx, [esi+TASKDATA.pid]
  290.     mov     [eax + SOCKET.PID], ecx         ; save the process ID
  291.  
  292.     cmp     ebx, TCB_LISTEN
  293.     je      sot_done
  294.  
  295.     ; Now, if we are in active mode, then we have to send a SYN to the specified remote port
  296.     mov     eax, EMPTY_QUEUE
  297.     call    dequeue
  298.     cmp     ax, NO_BUFFER
  299.     je      sot_done
  300.  
  301.     push    eax
  302.  
  303.     mov     bl, 0x02        ; SYN
  304.     mov     ecx, 0
  305.  
  306.     call    buildTCPPacket
  307.  
  308.     mov     eax, NET1OUT_QUEUE
  309.  
  310.     mov     edx, [stack_ip]
  311.     mov     ecx, [sktAddr ]
  312.     mov     ecx, [ecx + 16]
  313.     cmp     edx, ecx
  314.     jne     sot_notlocal
  315.     mov     eax, IPIN_QUEUE
  316.  
  317. sot_notlocal:
  318.        ; Send it.
  319.     pop     ebx
  320.     call    queue
  321.  
  322.     mov     esi, [sktAddr]
  323.  
  324.     ; increment SND.NXT in socket
  325.     add     esi, 48
  326.     call    inc_inet_esi
  327.  
  328. sot_done:
  329.     pop     eax      ; Get the socket number back, so we can return it
  330.  
  331. sot_exit:
  332.     ret
  333.  
  334.  
  335.  
  336. ;***************************************************************************
  337. ;   Function
  338. ;      socket_close
  339. ;
  340. ;   Description
  341. ;       socket # in ebx
  342. ;       returns 0 for ok, -1 for socket not open (fail)
  343. ;
  344. ;***************************************************************************
  345. socket_close:
  346.     mov     eax, 0xFFFFFFFF         ; assume this operation will fail..
  347.     cmp     ebx, NUM_SOCKETS
  348.     jae     sc_exit
  349.     Index2RealAddr ebx
  350.     cmp     [ebx + SOCKET.Status], dword SOCK_EMPTY
  351.     jz      sc_exit
  352.  
  353.     ; Clear the socket varaibles
  354.     xor     eax, eax
  355.     mov     edi, ebx
  356.     mov     ecx, SOCKETHEADERSIZE
  357.     cld
  358.     rep     stosb
  359.  
  360. sc_exit:
  361.     ret
  362.  
  363.  
  364.  
  365. ;***************************************************************************
  366. ;   Function
  367. ;      socket_close_tcp
  368. ;
  369. ;   Description
  370. ;       socket # in ebx
  371. ;       returns 0 for ok, -1 for socket not open (fail)
  372. ;
  373. ;***************************************************************************
  374. socket_close_tcp:
  375.     ; first, remove any resend entries
  376.     pusha
  377.  
  378.     mov     esi, resendQ
  379.     mov     ecx, 0
  380.  
  381. sct001:
  382.     cmp     ecx, NUMRESENDENTRIES
  383.     je      sct003              ; None left
  384.     cmp     [esi], bl
  385.     je      sct002              ; found one
  386.     inc     ecx
  387.     add     esi, 4
  388.     jmp     sct001
  389.  
  390. sct002:
  391.  
  392.     mov     [esi], byte 0xFF
  393.     jmp     sct001
  394.  
  395. sct003:
  396.     popa
  397.  
  398.     Index2RealAddr ebx
  399.     mov     [sktAddr], ebx
  400.     mov     eax, 0xFFFFFFFF         ; assume this operation will fail..
  401.     cmp     [ebx + SOCKET.Status], dword SOCK_EMPTY
  402.     jz      sct_exit
  403.  
  404.     ; Now construct the response, and queue for sending by IP
  405.     mov     eax, EMPTY_QUEUE
  406.     call    dequeue
  407.     cmp     ax, NO_BUFFER
  408.     je      stl_exit
  409.  
  410.     push    eax
  411.  
  412.     mov     bl, 0x11        ; FIN + ACK
  413.     mov     ecx, 0
  414.     mov     esi, 0
  415.  
  416.     call    buildTCPPacket
  417.  
  418.     mov     ebx, [sktAddr]
  419.  
  420.     ; increament SND.NXT in socket
  421.     mov     esi, 48
  422.     add     esi, ebx
  423.     call    inc_inet_esi
  424.  
  425.  
  426.     ; Get the socket state
  427.     mov     eax, [ebx + SOCKET.TCBState]
  428.     cmp     eax, TCB_LISTEN
  429.     je      destroyTCB
  430.     cmp     eax, TCB_SYN_SENT
  431.     je      destroyTCB
  432.     cmp     eax, TCB_SYN_RECEIVED
  433.     je      sct_finwait1
  434.     cmp     eax, TCB_ESTABLISHED
  435.     je      sct_finwait1
  436.  
  437.     ; assume CLOSE WAIT
  438.     ; Send a fin, then enter last-ack state
  439.     mov     eax, TCB_LAST_ACK
  440.     mov     [ebx + SOCKET.TCBState], eax
  441.     xor     eax, eax
  442.     jmp     sct_send
  443.  
  444. sct_finwait1:
  445.     ; Send a fin, then enter finwait2 state
  446.     mov     eax, TCB_FIN_WAIT_1
  447.     mov     [ebx + SOCKET.TCBState], eax
  448.     xor     eax, eax
  449.  
  450. sct_send:
  451.     mov     eax, NET1OUT_QUEUE
  452.  
  453.     mov     edx, [stack_ip]
  454.     mov     ecx, [sktAddr ]
  455.     mov     ecx, [ecx + 16]
  456.     cmp     edx, ecx
  457.     jne     sct_notlocal
  458.     mov     eax, IPIN_QUEUE
  459.  
  460. sct_notlocal:
  461.        ; Send it.
  462.     pop     ebx
  463.     call    queue
  464.     jmp     sct_exit
  465.  
  466. destroyTCB:
  467.     pop     eax
  468.     ; Clear the socket varaibles
  469.     xor     eax, eax
  470.     mov     edi, ebx
  471.     mov     ecx, SOCKETHEADERSIZE
  472.     cld
  473.     rep     stosb
  474.  
  475. sct_exit:
  476.     ret
  477.  
  478.  
  479.  
  480. ;***************************************************************************
  481. ;   Function
  482. ;      socket_poll
  483. ;
  484. ;   Description
  485. ;       socket # in ebx
  486. ;       returns count in eax.
  487. ;
  488. ;***************************************************************************
  489. socket_poll:
  490.     Index2RealAddr ebx
  491.     mov     eax, [ebx + SOCKET.rxDataCount]
  492.  
  493.     ret
  494.  
  495.  
  496.  
  497. ;***************************************************************************
  498. ;   Function
  499. ;      socket_status
  500. ;
  501. ;   Description
  502. ;       socket # in ebx
  503. ;       returns TCB state in eax.
  504. ;
  505. ;***************************************************************************
  506. socket_status:
  507.     Index2RealAddr ebx
  508.     mov     eax, [ebx + SOCKET.TCBState]
  509.  
  510.     ret
  511.  
  512.  
  513.  
  514. ;***************************************************************************
  515. ;   Function
  516. ;      socket_read
  517. ;
  518. ;   Description
  519. ;       socket # in ebx
  520. ;       returns # of bytes remaining in eax, data in bl
  521. ;
  522. ;***************************************************************************
  523. socket_read:
  524.     Index2RealAddr ebx
  525.     mov     eax, [ebx + SOCKET.rxDataCount]         ; get count of bytes
  526.     mov     ecx, 1
  527.     test    eax, eax
  528.     jz      sr2
  529.  
  530.     dec     eax
  531.     mov     esi, ebx            ; esi is address of socket
  532.     mov     [ebx + SOCKET.rxDataCount], eax         ; store new count
  533.     ;movzx   ebx, byte [ebx + SOCKET.rxData]  ; get the byte
  534.     movzx   ebx, byte [ebx + SOCKETHEADERSIZE]  ; get the byte
  535.     add     esi, SOCKETHEADERSIZE
  536.     mov     edi, esi
  537.     inc     esi
  538.  
  539.     mov     ecx, (SOCKETBUFFSIZE - SOCKETHEADERSIZE) / 4
  540.     cld
  541.     rep     movsd
  542.     xor     ecx, ecx
  543.  
  544. sr1:
  545.     jmp     sor_exit
  546.  
  547. sr2:
  548.     xor     bl, bl
  549.  
  550. sor_exit:
  551.     ret
  552.  
  553.  
  554. ;***************************************************************************
  555. ;   Function
  556. ;      socket_read_packet
  557. ;
  558. ;   Description
  559. ;       socket # in ebx
  560. ;       datapointer # in ecx
  561. ;       buffer size in edx
  562. ;       returns # of bytes copied in eax
  563. ;
  564. ;***************************************************************************
  565. socket_read_packet:
  566.     Index2RealAddr ebx                                     ; get real socket address
  567.     mov     eax, [ebx + SOCKET.rxDataCount]                ; get count of bytes
  568.     test    eax, eax                                       ; if count of bytes is zero..
  569.     jz      .exit                                          ; exit function (eax will be zero)
  570.  
  571.     test    edx, edx                                       ; if buffer size is zero, copy all data
  572.     jz      .copyallbytes
  573.     cmp     edx, eax                                       ; if buffer size is larger then the bytes of data, copy all data
  574.     jge     .copyallbytes
  575.  
  576.     sub     eax, edx                                       ; store new count (data bytes in buffer - bytes we're about to copy)
  577.     mov     [ebx + SOCKET.rxDataCount], eax                ;
  578.     push    eax
  579.     mov     eax, edx                                       ; number of bytes we want to copy must be in eax
  580.     call    .startcopy                                     ; copy to the application
  581.  
  582.     mov     esi, ebx                                       ; now we're going to copy the remaining bytes to the beginning
  583.     add     esi, SOCKETHEADERSIZE                          ; we dont need to copy the header
  584.     mov     edi, esi                                       ; edi is where we're going to copy to
  585.     add     esi, edx                                       ; esi is from where we copy
  586.     pop     ecx                                            ; count of bytes we have left
  587.     push    ecx                                            ; push it again so we can re-use it later
  588.     shr     ecx, 2                                         ; divide eax by 4
  589.     cld
  590.     rep     movsd                                          ; copy all full dwords
  591.     pop     ecx
  592.     and     ecx, 3
  593.     rep     movsb                                          ; copy remaining bytes
  594.  
  595.     ret                                                    ; at last, exit
  596.  
  597. .copyallbytes:
  598.     xor     esi, esi
  599.     mov     [ebx + SOCKET.rxDataCount], esi                ; store new count (zero)
  600.  
  601. .startcopy:
  602.     mov     edi, ecx                                       ;
  603.  ;   add     edi, std_application_base_address              ; get data pointer to buffer in application
  604.  
  605.     mov     esi, ebx                                       ;
  606.     add     esi, SOCKETHEADERSIZE                          ; we dont need to copy the header
  607.     mov     ecx, eax                                       ; eax is count of bytes
  608.     push    ecx
  609.     shr     ecx, 2                                         ; divide eax by 4
  610.     cld                                                    ; copy all full dwords
  611.     rep     movsd                                          ;
  612.     pop     ecx
  613.     and     ecx, 3
  614.     rep     movsb                                          ; copy the rest bytes
  615.  
  616. .exit:
  617.     ret                                                    ; exit, or go back to shift remaining bytes if any
  618.  
  619.  
  620.  
  621.  
  622. ;***************************************************************************
  623. ;   Function
  624. ;      socket_write
  625. ;
  626. ;   Description
  627. ;       socket in ebx
  628. ;       # of bytes to write in ecx
  629. ;       pointer to data in edx
  630. ;       returns 0 in eax ok, -1 == failed ( invalid socket, or
  631. ;       could not queue IP packet )
  632. ;
  633. ;***************************************************************************
  634. socket_write:
  635.     Index2RealAddr ebx
  636.  
  637.     mov     eax, 0xFFFFFFFF
  638.     ; If the socket is invalid, return with an error code
  639.     cmp     [ebx], dword SOCK_EMPTY
  640.     je      sw_exit
  641.  
  642.  
  643.     mov     eax, EMPTY_QUEUE
  644.     call    dequeue
  645.     cmp     ax, NO_BUFFER
  646.     je      sw_exit
  647.  
  648.     ; Save the queue entry number
  649.     push    eax
  650.  
  651.     ; save the pointers to the data buffer & size
  652.     push    edx
  653.     push    ecx
  654.  
  655.     ; convert buffer pointer eax to the absolute address
  656.     mov     ecx, IPBUFFSIZE
  657.     mul     ecx
  658.     add     eax, IPbuffs
  659.  
  660.     mov     edx, eax
  661.  
  662.     ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
  663.  
  664.     ; Fill in the IP header ( some data is in the socket descriptor)
  665.     mov     eax, [ebx + 8]
  666.     mov     [edx + 12], eax      ; source IP
  667.     mov     eax, [ebx + 16]
  668.     mov     [edx + 16], eax      ; Destination IP
  669.  
  670.     mov     al, 0x45
  671.     mov     [edx], al         ; Version, IHL
  672.     xor     al, al
  673.     mov     [edx + 1], al     ; Type of service
  674.  
  675.     pop     eax                   ; Get the UDP data length
  676.     push    eax
  677.  
  678.     add     eax, 20 + 8           ; add IP header and UDP header lengths
  679.     mov     [edx + 2], ah
  680.     mov     [edx + 3], al
  681.     xor     al, al
  682.     mov     [edx + 4], al
  683.     mov     [edx + 5], al
  684.     mov     al, 0x40
  685.     mov     [edx + 6], al
  686.     xor     al, al
  687.     mov     [edx + 7], al
  688.     mov     al, 0x20
  689.     mov     [edx + 8], al
  690.     mov     al, 17
  691.     mov     [edx + 9], al
  692.  
  693.     ; Checksum left unfilled
  694.     xor     ax, ax
  695.     mov     [edx + 10], ax
  696.  
  697.     ; Fill in the UDP header ( some data is in the socket descriptor)
  698.     mov     ax, [ebx + 12]
  699.     mov     [edx + 20], ax
  700.  
  701.     mov     ax, [ebx + 20]
  702.     mov     [edx + 20 + 2], ax
  703.  
  704.     pop     eax
  705.     push    eax
  706.  
  707.     add     eax, 8
  708.     mov     [edx + 20 + 4], ah
  709.     mov     [edx + 20 + 5], al
  710.  
  711.     ; Checksum left unfilled
  712.     xor     ax, ax
  713.     mov     [edx + 20 + 6], ax
  714.  
  715.     pop     ecx                  ; count of bytes to send
  716.     mov     ebx, ecx            ; need the length later
  717.     pop     eax                  ; get callers ptr to data to send
  718.  
  719.     ; Get the address of the callers data
  720.     mov     edi, [TASK_BASE]
  721.     add     edi, TASKDATA.mem_start
  722.     add     eax, [edi]
  723.     mov     esi, eax
  724.  
  725.     mov     edi, edx
  726.     add     edi, 28
  727.     cld
  728.     rep     movsb               ; copy the data across
  729.  
  730.     ; we have edx as IPbuffer ptr.
  731.     ; Fill in the UDP checksum
  732.     ; First, fill in pseudoheader
  733.     mov     eax, [edx + 12]
  734.     mov     [pseudoHeader], eax
  735.     mov     eax, [edx + 16]
  736.     mov     [pseudoHeader+4], eax
  737.     mov     ax, 0x1100            ; 0 + protocol
  738.     mov     [pseudoHeader+8], ax
  739.     add     ebx, 8
  740.     mov     eax, ebx
  741.     mov     [pseudoHeader+10], ah
  742.     mov     [pseudoHeader+11], al
  743.  
  744.     mov     eax, pseudoHeader
  745.     mov     [checkAdd1], eax
  746.     mov     [checkSize1], word 12
  747.     mov     eax, edx
  748.     add     eax, 20
  749.     mov     [checkAdd2], eax
  750.     mov     eax, ebx
  751.     mov     [checkSize2], ax      ; was eax!! mjh 8/7/02
  752.  
  753.     call    checksum
  754.  
  755.     ; store it in the UDP checksum ( in the correct order! )
  756.     mov     ax, [checkResult]
  757.  
  758.     ; If the UDP checksum computes to 0, we must make it 0xffff
  759.     ; (0 is reserved for 'not used')
  760.     cmp     ax, 0
  761.     jne     sw_001
  762.     mov     ax, 0xffff
  763.  
  764. sw_001:
  765.     mov     [edx + 20 + 6], ah
  766.     mov     [edx + 20 + 7], al
  767.  
  768.     ; Fill in the IP header checksum
  769.     GET_IHL ecx,edx              ; get IP-Header length
  770.     stdcall checksum_jb,edx,ecx  ; buf_ptr, buf_size
  771.  
  772.     mov     [edx + 10], ah
  773.     mov     [edx + 11], al
  774.  
  775.     ; Check destination IP address.
  776.     ; If it is the local host IP, route it back to IP_RX
  777.  
  778.     pop     ebx
  779.     mov     eax, NET1OUT_QUEUE
  780.  
  781.     mov     ecx, [ edx + 16]
  782.     mov     edx, [stack_ip]
  783.     cmp     edx, ecx
  784.     jne     sw_notlocal
  785.     mov     eax, IPIN_QUEUE
  786.  
  787. sw_notlocal:
  788.     ; Send it.
  789.     call    queue
  790.  
  791.     xor     eax, eax
  792.  
  793. sw_exit:
  794.     ret
  795.  
  796.  
  797.  
  798. ;***************************************************************************
  799. ;   Function
  800. ;      socket_write_tcp
  801. ;
  802. ;   Description
  803. ;       socket in ebx
  804. ;       # of bytes to write in ecx
  805. ;       pointer to data in edx
  806. ;       returns 0 in eax ok, -1 == failed ( invalid socket, or
  807. ;       could not queue IP packet )
  808. ;
  809. ;***************************************************************************
  810. socket_write_tcp:
  811.         Index2RealAddr ebx
  812.  
  813.     mov     [sktAddr], ebx
  814.  
  815.     mov     eax, 0xFFFFFFFF
  816.     ; If the socket is invalid, return with an error code
  817.     cmp     [ebx], dword SOCK_EMPTY
  818.     je      swt_exit
  819.  
  820.     ; If the sockets window timer is nonzero, do not queue packet
  821.     ; TODO - done
  822.     cmp     [ebx + SOCKET.wndsizeTimer], dword 0
  823.     jne     swt_exit
  824.  
  825.     mov     eax, EMPTY_QUEUE
  826.     call    dequeue
  827.     cmp     ax, NO_BUFFER
  828.     je      swt_exit
  829.  
  830.     push    eax
  831.  
  832.     mov     bl, 0x10        ; ACK
  833.  
  834.     ; Get the address of the callers data
  835.     mov     edi, [TASK_BASE]
  836.     add     edi, TASKDATA.mem_start
  837.     add     edx, [edi]
  838.     mov     esi, edx
  839.  
  840.     pop     eax
  841.     push    eax
  842.  
  843.     push    ecx
  844.     call    buildTCPPacket
  845.     pop     ecx
  846.  
  847.     ; Check destination IP address.
  848.     ; If it is the local host IP, route it back to IP_RX
  849.  
  850.     pop     ebx
  851.     push    ecx
  852.     mov     eax, NET1OUT_QUEUE
  853.  
  854.     mov     edx, [stack_ip]
  855.     mov     ecx, [sktAddr ]
  856.     mov     ecx, [ecx + 16]
  857.     cmp     edx, ecx
  858.     jne     swt_notlocal
  859.     mov     eax, IPIN_QUEUE
  860.  
  861. swt_notlocal:
  862.     pop     ecx
  863.  
  864.     push    ebx                 ; save ipbuffer number
  865.  
  866.     call    queue
  867.  
  868.     mov     esi, [sktAddr]
  869.  
  870.     ; increament SND.NXT in socket
  871.     ; Amount to increment by is in ecx
  872.     add     esi, 48
  873.     call    add_inet_esi
  874.  
  875.     pop     ebx
  876.  
  877.     ; Copy the IP buffer to a resend queue
  878.     ; If there isn't one, dont worry about it for now
  879.     mov     esi, resendQ
  880.     mov     ecx, 0
  881.  
  882. swt003:
  883.     cmp     ecx, NUMRESENDENTRIES
  884.     je      swt001              ; None found
  885.     cmp     [esi], byte 0xFF
  886.     je      swt002              ; found one
  887.     inc     ecx
  888.     add     esi, 4
  889.     jmp     swt003
  890.  
  891. swt002:
  892.     push    ebx
  893.  
  894.     ; OK, we have a buffer descriptor ptr in esi.
  895.     ; resend entry # in ecx
  896.     ;  Populate it
  897.     ;  socket #
  898.     ;  retries count
  899.     ;  retry time
  900.     ;  fill IP buffer associated with this descriptor
  901.  
  902.     mov     eax, [sktAddr]
  903.     sub     eax, sockets
  904.     shr     eax, 12             ; get skt #
  905.     mov     [esi], al
  906.     mov     [esi + 1], byte TCP_RETRIES
  907.     mov     [esi + 2], word TCP_TIMEOUT
  908.  
  909.     inc     ecx
  910.     ; Now get buffer location, and copy buffer across. argh! more copying,,
  911.     mov     edi, resendBuffer - IPBUFFSIZE
  912. swt002a:
  913.     add     edi, IPBUFFSIZE
  914.     loop    swt002a
  915.  
  916.     ; we have dest buffer location in edi
  917.     pop     eax
  918.     ; convert source buffer pointer eax to the absolute address
  919.     mov     ecx, IPBUFFSIZE
  920.     mul     ecx
  921.     add     eax, IPbuffs
  922.     mov     esi, eax
  923.  
  924.     ; do copy
  925.     mov     ecx, IPBUFFSIZE
  926.     cld
  927.     rep     movsb
  928.  
  929. swt001:
  930.     xor     eax, eax
  931.  
  932. swt_exit:
  933.     ret
  934.  
  935.