hxopwavetcpsock.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:21k
源码类别:

Symbian

开发平台:

Visual C++

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