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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: hxopwaveudpsock.cpp,v 1.4.28.1 2004/07/09 02:08:45 hubbe Exp $
  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,
  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 "hxopwaveudpsock.h"
  50. #include "debug.h"
  51. #include "hxassert.h"
  52. #include "ihxpckts.h"
  53. #include "smartptr.h"
  54. #define D_UDPSOCKET 0x10000000
  55. HXOpwaveUDPSocket::HXOpwaveUDPSocket(IHXCommonClassFactory* pCCF)
  56.                                     : OpSocket(kUDP)
  57.                                     , m_lRefCount(0)
  58.                                     , m_pResponse(0)
  59.                                     , m_pCCF(0)
  60.                                     , m_state(udpNotInitialized)
  61.                                     , m_ulRemoteAddr(0)
  62.                                     , m_nRemotePort(0)
  63.                                     , m_nLocalPort(0)
  64.                                     , m_ulLocalAddr(0)
  65.                                     , m_ulReadSize(0)
  66.                                     , m_pWriteBuffer(NULL)
  67.                                     , m_ulBytesLeftToWrite(0)
  68.                                     , m_pReadBuffer(NULL)
  69. {
  70.     
  71.     if (pCCF)
  72.     {
  73.         m_pCCF = pCCF;
  74.         m_pCCF->AddRef();
  75.     }
  76. }
  77. HXOpwaveUDPSocket::~HXOpwaveUDPSocket()
  78. {
  79.     
  80.     DPRINTF(D_UDPSOCKET, ("HXOpwaveUDPSocket::~HXOpwaveUDPSocket()n"));
  81.     
  82.     CloseSocket(HXR_OK);
  83.     HX_RELEASE(m_pResponse);
  84.     HX_RELEASE(m_pCCF);
  85. }
  86. /*
  87. *  IUnknown methods
  88. */
  89. STDMETHODIMP
  90. HXOpwaveUDPSocket::QueryInterface(THIS_
  91.                                   REFIID riid,
  92.                                   void** ppvObj)
  93. {
  94.     
  95.     DPRINTF(D_UDPSOCKET, ("HXOpwaveUDPSocket::QueryInterface()n"));
  96.     
  97.     if (IsEqualIID(riid, IID_IHXUDPSocket))
  98.     {
  99.         
  100.         AddRef();
  101.         *ppvObj = (IHXUDPSocket*)this;
  102.         return HXR_OK;
  103.     }
  104.     else if (IsEqualIID(riid, IID_IHXSetSocketOption))
  105.     {
  106.         AddRef();
  107.         *ppvObj = (IHXSetSocketOption*)this;
  108.         return HXR_OK;
  109.     }    
  110.     else if (IsEqualIID(riid, IID_IUnknown))
  111.     {
  112.         AddRef();
  113.         *ppvObj = (IUnknown*)(IHXUDPSocket*)this;
  114.         return HXR_OK;
  115.     }
  116.     
  117.     *ppvObj = NULL;
  118.     return HXR_NOINTERFACE;
  119. }
  120. STDMETHODIMP_(ULONG32)
  121. HXOpwaveUDPSocket::AddRef(THIS)
  122. {
  123.     return InterlockedIncrement(&m_lRefCount);
  124. }
  125. STDMETHODIMP_(ULONG32)
  126. HXOpwaveUDPSocket::Release(THIS)
  127. {
  128.     if (InterlockedDecrement(&m_lRefCount) > 0)
  129.     {
  130.         return m_lRefCount;
  131.     }
  132.     
  133.     delete this;
  134.     return 0;
  135. }
  136. /*
  137. * IHXUDPSocket methods
  138. *
  139. *  Network addresses and ports are in native byte order
  140. *  
  141. */
  142. STDMETHODIMP
  143. HXOpwaveUDPSocket::Init(THIS_
  144.                         ULONG32 ulAddr,
  145.                         UINT16 nPort,
  146.                         IHXUDPResponse* pUDPResponse)
  147. {
  148.     DPRINTF(D_UDPSOCKET, ("HXOpwaveUDPSocket::Init(%08lx, %u)n",
  149.         ulAddr, nPort));
  150.     
  151.     HX_RESULT res = HXR_OK;
  152.     if (m_state != udpNotInitialized)
  153.     {
  154.         return res;
  155.     }
  156.     if (pUDPResponse)
  157.     {
  158.         HX_RELEASE(m_pResponse);
  159.         m_pResponse = pUDPResponse;
  160.         m_pResponse->AddRef();
  161.     }
  162.     m_ulRemoteAddr = ulAddr;
  163.     m_nRemotePort = nPort;
  164.     
  165.     if (m_ulRemoteAddr != 0 && m_nRemotePort != 0)
  166.     {
  167.         m_state = udpInitialized;
  168.         if (m_state != udpBound)
  169.         {
  170.  
  171.             /// Openwave sdk does bind inside connect
  172.             /// we do binding here due to when Bind is called, the Init is not called
  173.             /// with valid m_nRemotePort and m_ulRemoteAddr.
  174.             connect(m_nLocalPort, m_nRemotePort, m_ulRemoteAddr);
  175.         
  176.             //OpDPRINTF("UDP::Init: this=%p, ulLocalAddr=%d, localport=%d, remotePort=%d, remoteaddr=%dn", this, 
  177.             //            m_ulLocalAddr,m_nLocalPort, m_nRemotePort, m_ulRemoteAddr);
  178.             m_state = udpBound;        
  179.             m_bWritable = FALSE;
  180.             m_bReadable = FALSE;
  181.         }
  182.     }
  183.     return res;
  184. }
  185. STDMETHODIMP 
  186. HXOpwaveUDPSocket::Bind(THIS_
  187.                         UINT32 ulLocalAddr,
  188.                         UINT16 nPort)
  189. {
  190.     
  191.     DPRINTF(D_UDPSOCKET, ("HXOpwaveUDPSocket::Bind(%08lx, %u)n", ulLocalAddr, nPort));
  192.     
  193.     /// Until OpSocket implement the DNS layer, this is nothting but cache address and
  194.     /// port values
  195.     /// OpSocket has bind function built into connect
  196.   
  197.     HX_RESULT res = HXR_OK;
  198.     
  199.     m_ulLocalAddr = ulLocalAddr;
  200.     m_nLocalPort = nPort;
  201.     if (m_state == udpInitialized && m_state != udpBound && m_nLocalPort != 0)
  202.     {
  203.         /// Only do binding if it is initialized 
  204.         /// Openwave sdk does bind inside connect
  205.         connect(m_nLocalPort, m_nRemotePort, m_ulRemoteAddr);
  206.         
  207.         //OpDPRINTF("UDP::Bind: this=%p, ulLocalAddr=%d, localport=%d, remotePort=%d, remoteaddr=%dn", this, 
  208.         //           m_ulLocalAddr,m_nLocalPort, m_nRemotePort, m_ulRemoteAddr);
  209.         m_state = udpBound;        
  210.         m_bWritable = FALSE;
  211.         m_bReadable = FALSE;
  212.     }
  213.     return res;
  214. }
  215. STDMETHODIMP 
  216. HXOpwaveUDPSocket::Read(THIS_
  217.                         UINT16 Size)
  218. {
  219.     
  220.     DPRINTF(D_UDPSOCKET, ("HXOpwaveUDPSocket::Read(%u)n", Size));
  221.     
  222.     HX_RESULT res = HXR_OK;
  223.     m_ulReadSize = Size;
  224.     //OpDPRINTF("UDP:Read: this=%p, size=%d, bread=%d, state=%d, bwrite=%dn", this, Size, m_bReadable, m_state, m_bWritable);
  225.     if (m_state == udpBound)
  226.     {
  227.         if (m_bReadable && m_ulReadSize)
  228.         {
  229.             /// avoid recursion that might occur because 
  230.             /// OnReadDone call in DoRead invoke ::Read again
  231.             m_bReadable = FALSE;
  232.             res = DoRead();
  233.         }
  234.     }
  235.     return res;
  236.     
  237. }
  238. /// Work horse for reading. As long as we are initilized once 
  239. /// to read, we always try to read something of the socket.
  240. HX_RESULT
  241. HXOpwaveUDPSocket::DoRead()
  242. {
  243.     /// Create a new IHXBuffer for every read
  244.     HX_RESULT res = HXR_FAIL;
  245.     IHXBuffer* pReadBuffer = NULL;
  246.     res = m_pCCF->CreateInstance(IID_IHXBuffer, (void**)&pReadBuffer);
  247.     if (SUCCEEDED(res))
  248.     {
  249.         res = pReadBuffer->SetSize(m_ulReadSize);
  250.     
  251.         UCHAR* pData = pReadBuffer->GetBuffer();
  252.         int nRead = read(pData, m_ulReadSize);
  253.  
  254.         //OpDPRINTF("UDP::DoRead: this=%p, read=%d, askfor=%dn", this, nRead, m_ulReadSize);
  255.         if (nRead > 0)
  256.         {
  257.             pReadBuffer->SetSize(nRead);
  258.             m_pReadBuffer = pReadBuffer;
  259.             // Don't ADDREF, m_pReadBuffer will be released in the callback OnReadDone
  260.         
  261.             if (m_pResponse)
  262.             {
  263.                 /// still to be found that address and port arguments
  264.                 /// should be put here (remote or local)
  265.                 m_pResponse->ReadDone(res, m_pReadBuffer,
  266.                     m_ulRemoteAddr, m_nRemotePort);
  267.             }
  268.             
  269.         }
  270.     }
  271.     HX_RELEASE(m_pReadBuffer);
  272.     return res;
  273. }
  274. STDMETHODIMP 
  275. HXOpwaveUDPSocket::Write(THIS_
  276.                          IHXBuffer* pBuffer)
  277. {
  278.     
  279.     DPRINTF(D_UDPSOCKET, ("HXOpwaveUDPSocket::Write()n"));
  280.     HX_RESULT res = HXR_OK;
  281.     if (!pBuffer)
  282.     {
  283.      res = HXR_INVALID_PARAMETER;
  284.     }
  285.   
  286.     //OpDPRINTF("UDP:Write: this=%p, lwsize=%d, bread=%d, newwritesize=%d, bwrite=%dn", this, m_ulBytesLeftToWrite, m_bReadable, pBuffer->GetSize(), m_bWritable);
  287.     if (SUCCEEDED(res) && (m_state == udpBound))
  288.     {
  289.         /// First add to our list
  290.         pBuffer->AddRef();
  291.         m_writeList.AddTail(pBuffer);
  292.         /// decide if we need to do a write 
  293.         /// because last time when it is ready to write, there is no data 
  294.         /// to be written.
  295.         if (m_bWritable)
  296.         {
  297.             if (!m_pWriteBuffer)
  298.             {
  299.                 m_pWriteBuffer = (IHXBuffer*)m_writeList.RemoveHead();
  300.                 m_ulBytesLeftToWrite = m_pWriteBuffer->GetSize();  
  301.             }
  302.             res =DoWrite();
  303.             if (SUCCEEDED(res))
  304.             {
  305.                 m_bWritable = FALSE;
  306.             }
  307.         }
  308.     }
  309.     return res;
  310. }
  311. /// This is working method to do actual write from
  312. /// the m_pWriteBuffer which is guranteed to have data to be written
  313. /// and the socket is ready to accept data
  314. HX_RESULT HXOpwaveUDPSocket::DoWrite()
  315. {
  316.     HX_RESULT res = HXR_OK;
  317.  
  318.     UCHAR* pBufData = m_pWriteBuffer->GetBuffer(); 
  319.     size_t ulActualWritten = write(pBufData, m_ulBytesLeftToWrite);
  320.    
  321.     HX_ASSERT(m_ulBytesLeftToWrite >= ulActualWritten);
  322.  
  323.     //OpDPRINTF("UDP::DoWrite, this=%p, written%d, write=%dnn",this, ulActualWritten, m_ulBytesLeftToWrite);
  324.     m_ulBytesLeftToWrite -= ulActualWritten;
  325.     if (m_ulBytesLeftToWrite > 0)
  326.     {
  327.         // more left in this m_pWriteBuffer to be written out
  328.         UCHAR* pLeftData = new UCHAR[m_ulBytesLeftToWrite];
  329.         if (!pLeftData)
  330.         {
  331.             res = HXR_OUTOFMEMORY;
  332.             OnWriteDone(res);
  333.             return res;
  334.         }
  335.             
  336.         memcpy(pLeftData, pBufData+ulActualWritten, m_ulBytesLeftToWrite);
  337.         m_pWriteBuffer->Set(pLeftData, m_ulBytesLeftToWrite); 
  338.         delete pLeftData;
  339.     }
  340.     return res;
  341. }
  342. STDMETHODIMP
  343. HXOpwaveUDPSocket::GetLocalPort(THIS_
  344.                                 REF(UINT16) port)
  345. {
  346.     
  347.     DPRINTF(D_UDPSOCKET, ("HXOpwaveUDPSocket::GetLocalPort()n"));
  348.     
  349.     HX_RESULT res = HXR_OK;
  350.     port = m_nLocalPort;
  351.     return res;
  352. }
  353. STDMETHODIMP 
  354. HXOpwaveUDPSocket::SetOption(THIS_ 
  355.                              HX_SOCKET_OPTION option,
  356.                              UINT32 ulValue)
  357. {
  358.     
  359.     DPRINTF(D_UDPSOCKET, ("HXOpwaveUDPSocket::SetOption(%d, %lu)n", option, ulValue));
  360.     HX_RESULT res = HXR_FAILED;
  361.     
  362.     if (m_state == udpNotInitialized)
  363.     {
  364.         switch(option)
  365.         {
  366.         case  HX_SOCKOPT_REUSE_ADDR:
  367.         case HX_SOCKOPT_REUSE_PORT:
  368.             //// OpSocket doesn't support set socket options
  369.             {
  370.                 res = HXR_NOTIMPL;
  371.             }
  372.             break;
  373.         case HX_SOCKOPT_BROADCAST:
  374.         case HX_SOCKOPT_SET_RECVBUF_SIZE:
  375.         case HX_SOCKOPT_SET_SENDBUF_SIZE:
  376.         case HX_SOCKOPT_MULTICAST_IF:
  377.             res = HXR_UNEXPECTED;
  378.             break;
  379.         default:
  380.             break;
  381.         }
  382.     }
  383.     
  384.     return res;
  385. }
  386. STDMETHODIMP
  387. HXOpwaveUDPSocket::WriteTo(THIS_ ULONG32 ulAddr, UINT16 nPort,
  388.                            IHXBuffer* pBuffer)
  389. {
  390.     HX_RESULT res = HXR_OK;
  391.     return res;
  392. }
  393. STDMETHODIMP
  394. HXOpwaveUDPSocket::JoinMulticastGroup(THIS_ ULONG32     ulMulticastAddr,
  395.                                       ULONG32     ulInterfaceAddr)
  396. {
  397.     HX_RESULT res = HXR_OK;
  398.     return res;
  399. }
  400. STDMETHODIMP
  401. HXOpwaveUDPSocket::LeaveMulticastGroup (THIS_ ULONG32     ulMulticastAddr,
  402.                                          ULONG32     ulInterfaceAddr)
  403. {
  404.     HX_RESULT res = HXR_OK;
  405.     return res;
  406. }
  407. void HXOpwaveUDPSocket::OnWriteDone(HX_RESULT status)
  408. {
  409.     
  410.     DPRINTF(D_UDPSOCKET, ("HXOpwaveUDPSocket::OnWriteDone(%ld)n", status));
  411.     DECLARE_SMART_POINTER_UNKNOWN scopeRef((IHXUDPSocket*)this);
  412.     
  413.     if (status == HXR_OK)
  414.     {
  415.         HX_RELEASE(m_pWriteBuffer);
  416.         if (m_writeList.GetCount() > 0)
  417.         {
  418.             m_pWriteBuffer = (IHXBuffer*)m_writeList.RemoveHead();
  419.             m_ulBytesLeftToWrite = m_pWriteBuffer->GetSize();     
  420.         }
  421.       
  422.     }
  423.     else
  424.     {
  425.         CloseSocket(status);
  426.     }
  427. }
  428. void HXOpwaveUDPSocket::CloseSocket(HX_RESULT status)
  429. {
  430.     
  431.     DPRINTF(D_UDPSOCKET, ("HXOpwaveUDPSocket::CloseConnection(%ld)n", status));
  432.     
  433.     if (m_state != udpNotInitialized)
  434.     {
  435.         close(true);
  436.     }
  437.     
  438.     // Clear the writer list
  439.     
  440.     while (m_writeList.GetCount() > 0)
  441.     {
  442.         // Release all the left unsent buffers in the list
  443.         IHXBuffer* pBuffer = (IHXBuffer*)m_writeList.RemoveHead();
  444.         HX_RELEASE(pBuffer);
  445.     }
  446.     m_state = udpNotInitialized;
  447.     
  448. }
  449. void HXOpwaveUDPSocket::onReadable(OpSocketEvent *pSocketEvent)
  450. {
  451.     
  452.     HX_RESULT res = HXR_OK;
  453.     //OpDPRINTF("UDP:onReadable: this=%p, mrsize=%d, bread=%d, state=%d, bwrite=%dn", this, m_ulReadSize, m_bReadable, m_state, m_bWritable);
  454.   
  455.     if (m_ulReadSize > 0)
  456.     {
  457.         /// avoid recursion that might occur because 
  458.         /// OnReadDone call in DoRead invoke ::Read again
  459.         m_bReadable = FALSE;
  460.         DoRead();
  461.     }
  462. }
  463. void HXOpwaveUDPSocket::onWritable(OpSocketEvent *pSocketEvent)
  464. {
  465.     HX_RESULT res = HXR_OK;
  466.     m_bWritable = TRUE;
  467.     //OpDPRINTF("UDP:onWritable: this=%p, mrsize=%d, bread=%d, lwsize=%d, bwrite=%dn", this, m_ulReadSize, m_bReadable, m_ulBytesLeftToWrite, m_bWritable);
  468.   
  469.   
  470.     /// Normal write process
  471.     /// Call OnWriteDone for handling the notification of last write
  472.     if (m_ulBytesLeftToWrite == 0)
  473.     {
  474.         /// Notify last writing is completely done
  475.         OnWriteDone(res);
  476.     }
  477.     
  478.     /// Do the next writing
  479.     if (m_pWriteBuffer && m_ulBytesLeftToWrite > 0)
  480.     {
  481.         if (DoWrite() == HXR_OK)
  482.         {
  483.             m_bWritable = FALSE;
  484.         }
  485.     }
  486. }
  487. void HXOpwaveUDPSocket::onException(OpSocketEvent *pSocketEvent)
  488. {
  489.     static int num = 0;
  490.     DPRINTF(D_UDPSOCKET, ("HXOpwaveUDPSocket::OnException(%ld)n", ++num));
  491. }