hxopwavetcpsock.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:20k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hxopwavetcpsock.h"
  36. #include "debug.h"
  37. #include "hxassert.h"
  38. #include "ihxpckts.h"
  39. #include "smartptr.h"
  40. #define D_TCPSOCKET 0x10000000
  41. class HXOpwaveTCPResolvResp : public IHXResolverResponse
  42. {
  43. public:
  44.     HXOpwaveTCPResolvResp(HXOpwaveTCPSocket* pParent);
  45.     ~HXOpwaveTCPResolvResp();
  46.     /*
  47.      *  IUnknown methods
  48.      */
  49.     STDMETHOD(QueryInterface) (THIS_
  50. REFIID riid,
  51. void** ppvObj);
  52.     STDMETHOD_(ULONG32,AddRef) (THIS);
  53.     STDMETHOD_(ULONG32,Release) (THIS);
  54.     /*
  55.      * IHXResolverResponse methods
  56.      */
  57.     STDMETHOD(GetHostByNameDone) (THIS_
  58. HX_RESULT status,
  59. ULONG32 ulAddr);
  60. private:
  61.     ULONG32 m_lRefCount;
  62.     HXOpwaveTCPSocket* m_pParent;
  63. };
  64. HXOpwaveTCPResolvResp::HXOpwaveTCPResolvResp(HXOpwaveTCPSocket* pParent) 
  65.   : m_lRefCount(0)
  66.   , m_pParent(pParent)
  67. {
  68.     HX_ADDREF(m_pParent);
  69. }
  70. HXOpwaveTCPResolvResp::~HXOpwaveTCPResolvResp()
  71. {
  72.     HX_RELEASE(m_pParent);
  73. }
  74. /*
  75.  *  IUnknown methods
  76.  */
  77. STDMETHODIMP
  78. HXOpwaveTCPResolvResp::QueryInterface(THIS_  REFIID riid,
  79. void** ppvObj)
  80. {
  81.     if (IsEqualIID(riid, IID_IHXResolverResponse))
  82.     {
  83.         AddRef();
  84.         *ppvObj = (IHXResolverResponse*)this;
  85.         return HXR_OK;
  86.     }
  87.     else if (IsEqualIID(riid, IID_IUnknown))
  88.     {
  89.         AddRef();
  90.         *ppvObj = (IUnknown*)(IHXResolverResponse*)this;
  91.         return HXR_OK;
  92.     }
  93.     *ppvObj = NULL;
  94.     return HXR_NOINTERFACE;
  95. }
  96. STDMETHODIMP_(ULONG32)
  97. HXOpwaveTCPResolvResp::AddRef(THIS)
  98. {
  99.     return InterlockedIncrement(&m_lRefCount);
  100. }
  101. STDMETHODIMP_(ULONG32)
  102. HXOpwaveTCPResolvResp::Release(THIS)
  103. {
  104.     if (InterlockedDecrement(&m_lRefCount) > 0)
  105.     {
  106.         return m_lRefCount;
  107.     }
  108.     delete this;
  109.     return 0;
  110. }
  111. /*
  112.  * IHXResolverResponse methods
  113.  */
  114. STDMETHODIMP
  115. HXOpwaveTCPResolvResp::GetHostByNameDone(THIS_
  116.   HX_RESULT status,
  117. ULONG32 ulAddr)
  118. {
  119.     return m_pParent->GetHostByNameDone(status, ulAddr);
  120. }
  121. HXOpwaveTCPSocket::HXOpwaveTCPSocket(IHXCommonClassFactory* pCCF,
  122.        IHXResolver* pResolver)
  123.   : OpSocket(kTCP)
  124.   , m_lRefCount(0)
  125.   , m_pResponse(0)
  126.   , m_pResolver(0)
  127.   , m_pCCF(0)
  128.   , m_state(tcpNotInitialized)
  129.   , m_nConnectPort(0)
  130.   , m_nLocalPort(0)
  131.   , m_ulLocalAddr(0)
  132.   , m_bWantWrite(FALSE)
  133.   , m_pReadBuffer(NULL)
  134.   , m_pWriteBuffer(NULL)
  135.   , m_ulBytesLeftToWrite(0)
  136.   , m_ulReadSize(0)
  137. {
  138.     IHXResolverResponse* pResolvResp = new HXOpwaveTCPResolvResp(this);
  139.     if (pResolvResp)
  140.     {
  141. pResolvResp->AddRef();
  142.     
  143.         if (pCCF && pResolver && (pResolver->Init(pResolvResp) == HXR_OK))
  144. {
  145.     m_pCCF = pCCF;
  146.     m_pCCF->AddRef();
  147.     m_pResolver = pResolver;
  148.     m_pResolver->AddRef();
  149.     m_state = tcpInitialized;
  150. }
  151.     }
  152.     HX_RELEASE(pResolvResp);
  153. }
  154. HXOpwaveTCPSocket::~HXOpwaveTCPSocket()
  155. {
  156.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::~HXOpwaveTCPSocket()n"));
  157.     if (m_state != tcpNotInitialized)
  158.     {
  159. CloseConnection(HXR_OK);
  160.     }
  161.     HX_RELEASE(m_pResponse);
  162.     HX_RELEASE(m_pResolver);
  163.     HX_RELEASE(m_pCCF);
  164. }
  165. /*
  166.  *  IUnknown methods
  167.  */
  168. STDMETHODIMP
  169. HXOpwaveTCPSocket::QueryInterface(THIS_
  170. REFIID riid,
  171. void** ppvObj)
  172. {
  173.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::QueryInterface()n"));
  174.     if (IsEqualIID(riid, IID_IHXTCPSocket))
  175.     {
  176.         AddRef();
  177.         *ppvObj = (IHXTCPSocket*)this;
  178.         return HXR_OK;
  179.     }
  180.     else if (IsEqualIID(riid, IID_IHXSetSocketOption))
  181.     {
  182.         AddRef();
  183.         *ppvObj = (IHXSetSocketOption*)this;
  184.         return HXR_OK;
  185.     }    
  186.     else if (IsEqualIID(riid, IID_IUnknown))
  187.     {
  188.         AddRef();
  189.         *ppvObj = (IUnknown*)(IHXTCPSocket*)this;
  190.         return HXR_OK;
  191.     }
  192.     *ppvObj = NULL;
  193.     return HXR_NOINTERFACE;
  194. }
  195. STDMETHODIMP_(ULONG32)
  196. HXOpwaveTCPSocket::AddRef(THIS)
  197. {
  198.     return InterlockedIncrement(&m_lRefCount);
  199. }
  200. STDMETHODIMP_(ULONG32)
  201. HXOpwaveTCPSocket::Release(THIS)
  202. {
  203.     if (InterlockedDecrement(&m_lRefCount) > 0)
  204.     {
  205.         return m_lRefCount;
  206.     }
  207.     delete this;
  208.     return 0;
  209. }
  210. /*
  211.  * IHXTCPSocket methods
  212.  *
  213.  *  Network addresses and ports are in native byte order
  214.  *  
  215.  */
  216. STDMETHODIMP
  217. HXOpwaveTCPSocket::Init(THIS_
  218.      IHXTCPResponse* /*IN*/ pTCPResponse)
  219. {
  220.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::Init()n"));
  221.     HX_RELEASE(m_pResponse);
  222.     m_pResponse = pTCPResponse;
  223.     if (m_pResponse)
  224.     {
  225. m_pResponse->AddRef();
  226.     }
  227.     return (m_pResponse) ? HXR_OK : HXR_FAILED;
  228. }
  229. STDMETHODIMP 
  230. HXOpwaveTCPSocket::SetResponse(THIS_
  231.         IHXTCPResponse* pTCPResponse)
  232. {
  233.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::SetResponse()n"));
  234.     HX_RELEASE(m_pResponse);
  235.     m_pResponse = pTCPResponse;
  236.     if (m_pResponse)
  237. m_pResponse->AddRef();
  238.     return (m_pResponse) ? HXR_OK : HXR_FAILED;
  239. }
  240. STDMETHODIMP 
  241. HXOpwaveTCPSocket::Bind(THIS_
  242. UINT32 ulLocalAddr,
  243.          UINT16 nPort)
  244. {
  245.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::Bind(%08lx, %u)n", ulLocalAddr, nPort));
  246. /// Until OpSocket implement the DNS layer, this is nothting but cache address and
  247. /// port values
  248. /// OpSocket has bind function built into connect
  249.     HX_RESULT res = HXR_OK;
  250.     m_ulLocalAddr = ulLocalAddr;
  251.     m_nLocalPort = nPort;
  252.     m_state = tcpBound;
  253.     return res;
  254. }
  255. /*
  256.  * pDestination is a string containing host name or dotted-ip notation
  257.  */
  258. STDMETHODIMP 
  259. HXOpwaveTCPSocket::Connect(THIS_ 
  260.             const char* pDestination,
  261.    UINT16 nPort)    
  262. {
  263.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::Connect('%s', %u)n", pDestination, nPort));
  264.     HX_RESULT res = HXR_OK;
  265.     if (m_state == tcpInitialized)
  266.     {
  267.          Bind(0, 0);
  268.     }
  269.     m_ipDest = 0;
  270.     m_nConnectPort = nPort;
  271.     m_state = tcpResolving;   
  272.     res = m_pResolver->GetHostByName(pDestination);
  273.     return res;
  274. }
  275. STDMETHODIMP 
  276. HXOpwaveTCPSocket::Read(THIS_
  277. UINT16 Size)
  278. {
  279.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::Read(%u)n", Size));
  280.     HX_RESULT res = HXR_OK;
  281.     HX_ASSERT(m_state == tcpConnected);
  282.     m_ulReadSize = Size;
  283.     //OpDPRINTF("Read: this=%p, size=%d, bread=%d, state=%d, bwrite=%dn", this, Size, m_bReadable, m_state, m_bWritable);
  284.     if (m_state == tcpConnected)
  285.     {
  286.         if (m_bReadable &&m_ulReadSize)
  287.         {
  288.             /// avoid recursion that might occur because 
  289.             /// OnReadDone call in DoRead invoke ::Read again
  290.             m_bReadable = FALSE;
  291.             res = DoRead();
  292.         }
  293.         
  294.     }
  295.     else
  296.     {
  297.      res = HXR_FAILED;
  298.     }
  299.     return res;
  300. }
  301. /// Work horse for reading. As long as we are initilized once 
  302. /// to read, we always try to read something of the socket.
  303. HX_RESULT
  304. HXOpwaveTCPSocket::DoRead()
  305. {
  306.     /// Create a new IHXBuffer for every read
  307.     HX_RESULT res = HXR_FAIL;
  308.     IHXBuffer* pReadBuffer = NULL;
  309.     res = m_pCCF->CreateInstance(IID_IHXBuffer, (void**)&pReadBuffer);
  310.     if (SUCCEEDED(res))
  311.     {
  312.         res = pReadBuffer->SetSize(m_ulReadSize);
  313.     
  314.         UCHAR* pData = pReadBuffer->GetBuffer();
  315.         int nRead = read(pData, m_ulReadSize);
  316.  
  317.         //OpDPRINTF("DoRead: this=%p, read=%d, askfor=%dnn", this, nRead, m_ulReadSize);
  318.         if (nRead > 0)
  319.         {
  320.             pReadBuffer->SetSize(nRead);
  321.             m_pReadBuffer = pReadBuffer;
  322.             // Don't ADDREF, m_pReadBuffer will be released in the callback OnReadDone
  323.         
  324.             OnReadDone(res, m_pReadBuffer);
  325.         }
  326.     }
  327.     HX_RELEASE(m_pReadBuffer);
  328.     return res;
  329. }
  330. STDMETHODIMP 
  331. HXOpwaveTCPSocket::Write(THIS_
  332.  IHXBuffer* pBuffer)
  333. {
  334.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::Write()n"));
  335.     HX_RESULT res = HXR_OK;
  336.     if (!pBuffer)
  337.     {
  338.      res = HXR_INVALID_PARAMETER;
  339.     }
  340.     //OpDPRINTF("Write: this=%p, lwsize=%d, bread=%d, newwritesize=%d, bwrite=%dn", this, m_ulBytesLeftToWrite, m_bReadable, pBuffer->GetSize(), m_bWritable);
  341.     UCHAR* pBufData = pBuffer->GetBuffer(); 
  342.     if (SUCCEEDED(res) && (m_state == tcpConnected))
  343.     {
  344.         /// First add to our list
  345.         pBuffer->AddRef();
  346.         m_writeList.AddTail(pBuffer);
  347.         /// decide if we need to do a write 
  348.         /// because last time when it is ready to write, there is no data 
  349.         /// to be written.
  350.         if (m_bWritable)
  351.         {
  352.             if (!m_pWriteBuffer)
  353.             {
  354.                 m_pWriteBuffer = (IHXBuffer*)m_writeList.RemoveHead();
  355.                 m_ulBytesLeftToWrite = m_pWriteBuffer->GetSize();  
  356.             }
  357.             res =DoWrite();
  358.             if (SUCCEEDED(res))
  359.             {
  360.                 m_bWritable = FALSE;
  361.             }
  362.         }
  363.     }
  364.     return res;
  365. }
  366. /// This is working method to do actual write from
  367. /// the m_pWriteBuffer which is guranteed to have data to be written
  368. /// and the socket is ready to accept data
  369. HX_RESULT HXOpwaveTCPSocket::DoWrite()
  370. {
  371.     HX_RESULT res = HXR_OK;
  372.  
  373.     UCHAR* pBufData = m_pWriteBuffer->GetBuffer(); 
  374.     size_t ulActualWritten = write(pBufData, m_ulBytesLeftToWrite);
  375.    
  376.     HX_ASSERT(m_ulBytesLeftToWrite >= ulActualWritten);
  377.  
  378.     //OpDPRINTF("DoWrite, this=%p, written%d, write=%dnn",this, ulActualWritten, m_ulBytesLeftToWrite);
  379.     m_ulBytesLeftToWrite -= ulActualWritten;
  380.     if (m_ulBytesLeftToWrite > 0)
  381.     {
  382.         // more left in this m_pWriteBuffer to be written out
  383.         UCHAR* pLeftData = new UCHAR[m_ulBytesLeftToWrite];
  384.         if (!pLeftData)
  385.         {
  386.             res = HXR_OUTOFMEMORY;
  387.             OnWriteDone(res);
  388.             return res;
  389.         }
  390.             
  391.         memcpy(pLeftData, pBufData+ulActualWritten, m_ulBytesLeftToWrite);
  392.         m_pWriteBuffer->Set(pLeftData, m_ulBytesLeftToWrite); 
  393.         delete pLeftData;
  394.     }
  395.     return res;
  396. }
  397. /************************************************************************
  398.  * Method:
  399.  *     IHXTCPSocket::WantWrite
  400.  * Purpose:
  401.  *     This method is called when you wish to write a large amount of
  402.  *     data.  If you are only writing small amounts of data, you can
  403.  *     just call Write (all data not ready to be transmitted will be
  404.  *     buffered on your behalf).  When the TCP channel is ready to be
  405.  *     written to, the response interfaces WriteReady method will be 
  406.  *     called.
  407.  */
  408. STDMETHODIMP
  409. HXOpwaveTCPSocket::WantWrite(THIS)
  410. {
  411.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::WantWrite()n"));
  412.     m_bWantWrite = TRUE;
  413.     return HXR_OK;
  414. }
  415. /************************************************************************
  416.  * Method:
  417.  *     IHXTCPSocket::GetForeignAddress
  418.  * Purpose:
  419.  *     Returns the address of the other end of the TCP socket as a
  420.  *     ULONG32 in local host order
  421.  */
  422. STDMETHODIMP 
  423. HXOpwaveTCPSocket::GetForeignAddress(THIS_ REF(ULONG32) lAddress)
  424. {
  425.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::GetForeignAddress()n"));
  426.     
  427.     /// OpSocket's DNS should make this better
  428.     HX_RESULT res = HXR_OK;
  429.     if (m_state == tcpConnected)
  430.     {
  431.         lAddress = m_ipDest;
  432.     }
  433.     return res;
  434. }
  435. STDMETHODIMP 
  436. HXOpwaveTCPSocket::GetLocalAddress(THIS_ REF(ULONG32) lAddress)
  437. {
  438.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::GetLocalAddress()n"));
  439.     HX_RESULT res = HXR_OK;
  440.     lAddress = m_ulLocalAddr;
  441.     return res;
  442. }
  443. /************************************************************************
  444.  * Method:
  445.  *     IHXTCPSocket::GetForeignPort
  446.  * Purpose:
  447.  *     Returns the port of the other end of the TCP socket in local
  448.  *      host order.
  449.  */
  450. STDMETHODIMP
  451. HXOpwaveTCPSocket::GetForeignPort(THIS_ REF(UINT16) port)
  452. {
  453.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::GetForeignPort()n"));
  454. /// Until OpSocket has DNS, this is not appropriately implemented
  455.     HX_RESULT res = HXR_OK;
  456.     if (m_state == tcpConnected)
  457.     {
  458. port = m_nConnectPort;
  459.     }
  460.     else 
  461.     {
  462. res = HXR_FAILED;
  463.     }
  464.     return res;
  465. }
  466. STDMETHODIMP
  467. HXOpwaveTCPSocket::GetLocalPort(THIS_
  468. REF(UINT16) port)
  469. {
  470.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::GetLocalPort()n"));
  471.     HX_RESULT res = HXR_OK;
  472.     if ((m_state != tcpNotInitialized) &&
  473. (m_state != tcpInitialized))
  474.     {
  475. port = m_nLocalPort;
  476.     }
  477.     return res;
  478. }
  479. STDMETHODIMP 
  480. HXOpwaveTCPSocket::SetOption(THIS_ 
  481.              HX_SOCKET_OPTION option,
  482.     UINT32 ulValue)
  483. {
  484.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::SetOption(%d, %lu)n", option, ulValue));
  485.     HX_RESULT res = HXR_FAILED;
  486.     if (m_state == tcpNotInitialized)
  487.     {
  488.         switch(option)
  489.         {
  490.         case  HX_SOCKOPT_REUSE_ADDR:
  491.         case HX_SOCKOPT_REUSE_PORT:
  492.             //// OpSocket doesn't support set socket options
  493.             {
  494.                 res = HXR_NOTIMPL;
  495.             }
  496.             break;
  497.         case HX_SOCKOPT_BROADCAST:
  498.         case HX_SOCKOPT_SET_RECVBUF_SIZE:
  499.         case HX_SOCKOPT_SET_SENDBUF_SIZE:
  500.         case HX_SOCKOPT_MULTICAST_IF:
  501.             res = HXR_UNEXPECTED;
  502.             break;
  503.         default:
  504.             break;
  505.         }
  506.     }
  507.     return res;
  508. }
  509. HX_RESULT
  510. HXOpwaveTCPSocket::GetHostByNameDone(HX_RESULT status, 
  511. ULONG32 ulAddr)
  512. {
  513.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::ResolveDone(%ld, %08lx)n", status, ulAddr));
  514.     HX_ASSERT( m_state == tcpResolving);
  515.  
  516.     if (SUCCEEDED(status))
  517.     {
  518.         m_ipDest = ulAddr;
  519.         m_state = tcpConnecting;
  520.    
  521.         connect(m_nLocalPort, m_nConnectPort, m_ipDest);
  522.         /*
  523.         char* stopstring = NULL;
  524.         UINT32 segVal = 0;
  525.              
  526.         segVal = strtoul(pDestination, &stopstring, 10);
  527.         m_ipDest = segVal << 24;
  528.         pDestination = stopstring + 1;
  529.         segVal = strtoul(pDestination, &stopstring, 10);
  530.         m_ipDest += (segVal << 16);
  531.         pDestination = stopstring + 1;
  532.         segVal = strtoul(pDestination, &stopstring, 10);
  533.         m_ipDest += (segVal << 8);
  534.         pDestination = stopstring + 1;
  535.         segVal = strtoul(pDestination, &stopstring, 10);
  536.         m_ipDest += segVal;
  537.         connect(m_nLocalPort, nPort, m_ipDest);
  538.         //OpDPRINTF("Connect: this=%p, localPort=%d,remotePort=%d,desIP=%dn", this, m_nLocalPort, nPort, m_ipDest);
  539.         */
  540.         m_bWritable = FALSE;
  541.         m_bReadable = FALSE;
  542.  
  543.     }
  544.     
  545.     return status;
  546. }
  547. void HXOpwaveTCPSocket::OnConnect(HX_RESULT status)
  548. {
  549.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::OnConnect(%ld)n",status));
  550.     
  551.     HX_ASSERT(m_state == tcpConnecting);
  552.     DECLARE_SMART_POINTER_UNKNOWN scopeRef((IHXTCPSocket*)this);
  553.     
  554.     if (status == HXR_OK)
  555.     {
  556.         m_state = tcpConnected;
  557.     }
  558.     else
  559.     {
  560.         m_state = tcpBound;
  561.     }
  562.     if (m_pResponse)
  563.     {
  564.         m_pResponse->ConnectDone(status);
  565.     }
  566. }
  567. void HXOpwaveTCPSocket::OnWriteDone(HX_RESULT status)
  568. {
  569.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::OnWriteDone(%ld)n", status));
  570.     DECLARE_SMART_POINTER_UNKNOWN scopeRef((IHXTCPSocket*)this);
  571.     
  572.     if (status == HXR_OK)
  573.     {
  574.         HX_RELEASE(m_pWriteBuffer);
  575.         if (m_writeList.GetCount() > 0)
  576.         {
  577.             m_pWriteBuffer = (IHXBuffer*)m_writeList.RemoveHead();
  578.             m_ulBytesLeftToWrite = m_pWriteBuffer->GetSize();     
  579.         }
  580.       
  581.         // Signal WriteReady() if we don't have any
  582.         // writes pending and the response object
  583.         // wants these calls
  584.         if (m_bWantWrite && m_pResponse)
  585.         {
  586.             m_pResponse->WriteReady(HXR_OK);
  587.         }
  588.     }
  589.     else
  590.     {
  591.         CloseConnection(status);
  592.     }
  593. }
  594. void HXOpwaveTCPSocket::OnReadDone(HX_RESULT status, IHXBuffer* pBuffer)
  595. {
  596.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::OnReadDone(%ld)n", status));
  597.     DECLARE_SMART_POINTER_UNKNOWN scopeRef((IHXTCPSocket*)this);
  598.     if (m_pResponse)
  599.     {
  600. m_pResponse->ReadDone(status, pBuffer);
  601.     }
  602.     if (status != HXR_OK)
  603.     {
  604. CloseConnection(status);
  605.     }
  606. }
  607. void HXOpwaveTCPSocket::CloseConnection(HX_RESULT status)
  608. {
  609.     DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::CloseConnection(%ld)n", status));
  610.     if (m_state != tcpNotInitialized)
  611.     {
  612. close(true);
  613.     }
  614.     // Clear the writer list
  615.     while (m_writeList.GetCount() > 0)
  616.     {
  617.         // Release all the left unsent buffers in the list
  618.         IHXBuffer* pBuffer = (IHXBuffer*)m_writeList.RemoveHead();
  619.         HX_RELEASE(pBuffer);
  620.     }
  621.     if ((m_state != tcpInitialized) && m_pResponse)
  622.     {
  623.         m_pResponse->Closed(HXR_OK);
  624.     }
  625.     m_state = tcpNotInitialized;
  626. }
  627. void HXOpwaveTCPSocket::onReadable(OpSocketEvent *pSocketEvent)
  628. {
  629.     HX_RESULT res = HXR_OK;
  630.     m_bReadable = TRUE;
  631.     //OpDPRINTF("onReadable: this=%p, mrsize=%d, bread=%d, state=%d, bwrite=%dn", this, m_ulReadSize, m_bReadable, m_state, m_bWritable);
  632.   
  633.     if (m_ulReadSize > 0)
  634.     {
  635.         /// avoid recursion that might occur because 
  636.         /// OnReadDone call in DoRead invoke ::Read again
  637.         m_bReadable = FALSE;
  638.         DoRead();
  639.     }
  640. }
  641. void HXOpwaveTCPSocket::onWritable(OpSocketEvent *pSocketEvent)
  642. {
  643.     HX_RESULT res = HXR_OK;
  644.     m_bWritable = TRUE;
  645.     //OpDPRINTF("onWritable: this=%p, mrsize=%d, bread=%d, lwsize=%d, bwrite=%dn", this, m_ulReadSize, m_bReadable, m_ulBytesLeftToWrite, m_bWritable);
  646.   
  647.     if (m_state == tcpConnecting)
  648.     {
  649.         /// Since Openwave OpSocket's api is designed to have kWritable as the first
  650.         /// event sending back to clients, so we first respond to core for connection
  651.         /// status
  652.         OpSocketEvent::Condition sockCond = pSocketEvent->getCondition();
  653.         HX_RESULT status =  sockCond == OpSocketEvent::kException ? HXR_NET_CONNECT : HXR_OK;
  654.         OnConnect(status);
  655.     }
  656.   
  657.     /// Normal write process
  658.     /// Call OnWriteDone for handling the notification of last write
  659.     if (m_ulBytesLeftToWrite == 0)
  660.     {
  661.         /// Notify last writing is completely done
  662.         OnWriteDone(res);
  663.     }
  664.     
  665.     /// Do the next writing
  666.     if (m_pWriteBuffer && m_ulBytesLeftToWrite > 0)
  667.     {
  668.         if (DoWrite() == HXR_OK)
  669.         {
  670.             m_bWritable = FALSE;
  671.         }
  672.     }
  673.   
  674. }
  675. void HXOpwaveTCPSocket::onException(OpSocketEvent *pSocketEvent)
  676. {
  677.     OpSocketEvent::Exception except = pSocketEvent->getException();
  678. }
  679.    
  680. #if 0
  681. // Don't need it for the time being because
  682. // all the cases are handled by the above three callbacks.
  683. bool HXOpwaveTCPSocket::onEvent(OpEvent& ev)
  684. {
  685.    
  686.     OpSocketEvent* pSockEvt = NULL;
  687.     if ( (pSockEvt = OpSocketEvent::Cast(&ev)) != NULL)
  688.     {
  689.         HX_RESULT status = pSockEvt->getCondition() == OpSocketEvent::kException ? HXR_NET_CONNECT : HXR_OK;
  690.         OnConnect(status);
  691.         return true;
  692.     }
  693.     return OpEventSink::onEvent(ev);
  694. }
  695. #endif