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

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2003 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 "platform/symbian/hxsymbianudpsock.h"
  36. #include "hxsymbiansockhlp.h"
  37. #include "debug.h"
  38. #include "hxassert.h"
  39. #include "ihxpckts.h"
  40. #include "smartptr.h"
  41. #include <in_sock.h>
  42. #define D_UDPSOCKET 0x10000000
  43. class HXSymbianUDPWriter : public CActive
  44. {
  45. public:
  46.     HXSymbianUDPWriter(HXSymbianUDPSocket* pParent);
  47.     ~HXSymbianUDPWriter();
  48.     void Write(RSocket& socket, ULONG32 ulAddr, UINT16 nPort,
  49.        IHXBuffer* pBuffer);
  50.     
  51. private:
  52.     void RunL();
  53.     void DoCancel();
  54.     HXSymbianUDPSocket* m_pParent;
  55.     IHXBuffer* m_pBuffer;
  56.     TInetAddr m_sendAddr;
  57.     TPtrC8 m_bufDes;
  58. };
  59. HXSymbianUDPWriter::HXSymbianUDPWriter(HXSymbianUDPSocket* pParent) :
  60.     CActive(EPriorityStandard),
  61.     m_pParent(pParent),
  62.     m_pBuffer(0)
  63. {
  64.     CActiveScheduler::Add(this);
  65. }
  66. HXSymbianUDPWriter::~HXSymbianUDPWriter()
  67. {    
  68.     if (IsActive())
  69. Cancel();
  70.     HX_RELEASE(m_pBuffer);
  71.     m_pParent = 0;
  72. }
  73.     
  74. void HXSymbianUDPWriter::Write(RSocket& socket, 
  75.        ULONG32 ulAddr,
  76.        UINT16 nPort,
  77.        IHXBuffer* pBuffer)
  78. {
  79.     HX_RELEASE(m_pBuffer);
  80.     m_pBuffer = pBuffer;
  81.     if (m_pBuffer)
  82.     {
  83. m_pBuffer->AddRef();
  84.     
  85. m_bufDes.Set(m_pBuffer->GetBuffer(), m_pBuffer->GetSize());
  86. m_sendAddr.SetAddress(ulAddr);
  87. m_sendAddr.SetPort(nPort);
  88. socket.SendTo(m_bufDes, m_sendAddr, 0, iStatus);
  89. SetActive();
  90.     }
  91. }
  92. void HXSymbianUDPWriter::RunL()
  93. {
  94.     HX_RESULT res = HXR_FAILED;
  95.     if (iStatus == KErrNone)
  96.     {
  97. res = HXR_OK;
  98.     }
  99.     else if(iStatus == KErrEof)
  100.     {
  101. res = HXR_STREAM_DONE;
  102.     }
  103.     else if(iStatus == KErrNoMemory)
  104.     {
  105. res = HXR_OUTOFMEMORY;
  106.     }
  107.     HX_RELEASE(m_pBuffer);
  108.     m_pParent->OnWriteDone(res);
  109. }
  110. void HXSymbianUDPWriter::DoCancel()
  111. {}
  112. class HXSymbianUDPWriteInfo
  113. {
  114. public:
  115.     HXSymbianUDPWriteInfo(ULONG32    ulAddr, UINT16     nPort,
  116.   IHXBuffer* pBuffer);
  117.     ~HXSymbianUDPWriteInfo();
  118.     ULONG32 Address() const;
  119.     UINT16 Port() const;
  120.     IHXBuffer* GetBuffer();
  121. private:
  122.     ULONG32 m_ulAddr;
  123.     UINT16 m_nPort;
  124.     IHXBuffer* m_pBuffer;
  125. };
  126. HXSymbianUDPWriteInfo::HXSymbianUDPWriteInfo(ULONG32    ulAddr, 
  127.      UINT16     nPort,
  128.      IHXBuffer* pBuffer) :
  129.     m_ulAddr(ulAddr),
  130.     m_nPort(nPort),
  131.     m_pBuffer(pBuffer)
  132. {
  133.     if (m_pBuffer)
  134.     {
  135. m_pBuffer->AddRef();
  136.     }
  137. }
  138. HXSymbianUDPWriteInfo::~HXSymbianUDPWriteInfo()
  139. {
  140.     HX_RELEASE(m_pBuffer);
  141. }
  142. ULONG32 HXSymbianUDPWriteInfo::Address() const
  143. {
  144.     return m_ulAddr;
  145. }
  146. UINT16 HXSymbianUDPWriteInfo::Port() const
  147. {
  148.     return m_nPort;
  149. }
  150. IHXBuffer* HXSymbianUDPWriteInfo::GetBuffer()
  151. {
  152.     IHXBuffer* pRet = m_pBuffer;
  153.     if (pRet)
  154. pRet->AddRef();
  155.     return pRet;
  156. }
  157. class HXSymbianUDPReader : public CActive
  158. {
  159. public:
  160.     HXSymbianUDPReader(HXSymbianUDPSocket* pParent,
  161.                        IHXCommonClassFactory* pCCF);
  162.     ~HXSymbianUDPReader();
  163.     
  164.     HX_RESULT Read(RSocket& socket, UINT16);
  165. private:
  166.     void RunL();
  167.     void DoCancel();
  168.     HXSymbianUDPSocket* m_pParent;
  169.     IHXBuffer* m_pBuffer;
  170.     TPtr8 m_bufDes;
  171.     TInetAddr m_recvAddr;
  172.     IHXCommonClassFactory* m_pCCF;
  173. };
  174. HXSymbianUDPReader::HXSymbianUDPReader(HXSymbianUDPSocket* pParent,
  175.                                        IHXCommonClassFactory* pCCF) :
  176.     CActive(EPriorityStandard),
  177.     m_pParent(pParent),
  178.     m_pBuffer(0),
  179.     m_bufDes(0, 0),
  180.     m_pCCF(pCCF)
  181. {
  182.     CActiveScheduler::Add(this);
  183.     if (m_pCCF)
  184.     {
  185.         m_pCCF->AddRef();
  186.     }
  187. }
  188. HXSymbianUDPReader::~HXSymbianUDPReader()
  189. {
  190.     if (IsActive())
  191. Cancel();
  192.     
  193.     HX_RELEASE(m_pBuffer);
  194.     HX_RELEASE(m_pCCF);
  195.     m_pParent = 0;
  196. }
  197. HX_RESULT HXSymbianUDPReader::Read(RSocket& socket, UINT16 uSize)
  198. {
  199.     HX_RESULT res = HXR_FAILED;
  200.     if (m_pParent)
  201.     {
  202.         res = HXSymbianSocketHelper::ResizeOrCreate(m_pCCF, uSize, m_pBuffer);
  203.         if (HXR_OK == res)
  204.         {
  205.             m_bufDes.Set(m_pBuffer->GetBuffer(), 0, m_pBuffer->GetSize());
  206.             
  207.             socket.RecvFrom(m_bufDes, m_recvAddr, 0, iStatus);
  208.             SetActive();
  209.         }
  210.     }
  211.     return res;
  212. }
  213. void HXSymbianUDPReader::RunL()
  214. {
  215.     HX_RESULT res = HXR_FAILED;
  216.     if (iStatus == KErrNone)
  217.     {
  218. res = HXR_OK;
  219.     }
  220.     else if(iStatus == KErrEof)
  221.     {
  222. res = HXR_STREAM_DONE;
  223.     }
  224.     else if(iStatus == KErrNoMemory)
  225.     {
  226. res = HXR_OUTOFMEMORY;
  227.     }
  228.     
  229.     IHXBuffer* pBuffer = 0;
  230.     if( res != HXR_OUTOFMEMORY )
  231.     {
  232.         HXSymbianSocketHelper::CopyOrTransfer(m_pCCF, m_bufDes.Length(), 
  233.                                               m_pBuffer, pBuffer);
  234.     }
  235.     // All error handling is done through the response object.
  236.     m_pParent->OnReadDone(res,
  237.   (ULONG32)m_recvAddr.Address(),
  238.   m_recvAddr.Port(),
  239.   pBuffer);
  240.     HX_RELEASE(pBuffer);
  241. }
  242. void HXSymbianUDPReader::DoCancel()
  243. {}
  244. HXSymbianUDPSocket::HXSymbianUDPSocket(IHXCommonClassFactory* pCCF) :
  245.     m_lRefCount(0),
  246.     m_pResponse(0),
  247.     m_state(udpNotOpen),
  248.     m_ulRemoteAddr(0),
  249.     m_nRemotePort(0),
  250.     m_pWriter(0),
  251.     m_pReader(0)
  252. {
  253.     m_pWriter = new HXSymbianUDPWriter(this);
  254.     m_pReader = new HXSymbianUDPReader(this, pCCF);
  255.     if (pCCF && m_pWriter && m_pReader &&
  256. (m_socketServ.Connect() == KErrNone) &&
  257. (m_socket.Open(m_socketServ, KAfInet, 
  258.        KSockDatagram, KProtocolInetUdp) == KErrNone))
  259.     {
  260. m_state = udpOpen;
  261.     }
  262. }
  263. HXSymbianUDPSocket::~HXSymbianUDPSocket()
  264. {
  265.     if (m_state != udpNotOpen)
  266.     {
  267. CloseSocket(HXR_OK);
  268. m_socket.Close();
  269. m_socketServ.Close();
  270.     }
  271.     HX_DELETE(m_pWriter);
  272.     HX_DELETE(m_pReader);
  273.     HX_RELEASE(m_pResponse);
  274. }
  275.     /*
  276.      *  IUnknown methods
  277.      */
  278. STDMETHODIMP HXSymbianUDPSocket::QueryInterface(THIS_
  279. REFIID riid,
  280. void** ppvObj)
  281. {
  282. QInterfaceList qiList[] =
  283. {
  284. { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXNetworkServices*)this },
  285. { GET_IIDHANDLE(IID_IHXUDPSocket), (IHXUDPSocket*) this },
  286. { GET_IIDHANDLE(IID_IHXSetSocketOption), (IHXSetSocketOption*) this },
  287. };
  288.     return QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  289. }
  290. STDMETHODIMP_(ULONG32) HXSymbianUDPSocket::AddRef(THIS)
  291. {
  292.     return InterlockedIncrement(&m_lRefCount);
  293. }
  294. STDMETHODIMP_(ULONG32) HXSymbianUDPSocket::Release(THIS)
  295. {
  296.     if (InterlockedDecrement(&m_lRefCount) > 0)
  297.     {
  298.         return m_lRefCount;
  299.     }
  300.     
  301.     delete this;
  302.     return 0;
  303. }
  304.     /*
  305.      * IHXUDPSocket methods
  306.      *
  307.      *  Network addresses and ports are in native byte order
  308.      */
  309. STDMETHODIMP HXSymbianUDPSocket::Init(THIS_
  310.       ULONG32 ulAddr,
  311.       UINT16 nPort,
  312.       IHXUDPResponse* pUDPResponse)
  313. {
  314.     DPRINTF(D_UDPSOCKET, ("HXSymbianUDPSocket::Init(%08lx, %u)n",
  315.   ulAddr, nPort));
  316.     HX_RESULT res = HXR_FAILED;
  317.     if (m_state != udpNotOpen)
  318.     {
  319. if (!m_pResponse && !pUDPResponse)
  320. {
  321.     res = HXR_UNEXPECTED;
  322. }
  323. else if (pUDPResponse)
  324. {
  325.     HX_RELEASE(m_pResponse);
  326.     m_pResponse = pUDPResponse;
  327.     m_pResponse->AddRef();
  328. }
  329. if (m_pResponse)
  330. {
  331.     m_ulRemoteAddr = ulAddr;
  332.     m_nRemotePort = nPort;
  333.     if (m_state == udpOpen)
  334.     {
  335. m_state = udpInitialized;
  336.     }
  337.     
  338.     res = HXR_OK;
  339. }
  340.     }
  341.     return res;
  342. }
  343. STDMETHODIMP HXSymbianUDPSocket::Bind(THIS_
  344.       UINT32  ulLocalAddr,
  345.       UINT16  nPort)
  346. {
  347.     DPRINTF(D_UDPSOCKET, ("HXSymbianUDPSocket::Bind(%08lx, %u)n",
  348.   ulLocalAddr, nPort));
  349.     HX_RESULT res = HXR_FAILED;
  350.     TInetAddr addr(ulLocalAddr, nPort);
  351.     if ((m_state != udpNotOpen) &&
  352. (m_socket.Bind(addr) == KErrNone))
  353.     {
  354. m_state = udpBound;
  355. res = HXR_OK;
  356.     }
  357.     return res;
  358. }
  359. STDMETHODIMP HXSymbianUDPSocket::Read(THIS_ UINT16 Size)
  360. {
  361.     DPRINTF(D_UDPSOCKET, ("HXSymbianUDPSocket::Read(%d)n", Size));
  362.     HX_RESULT res = HXR_FAILED;
  363.     if (m_state == udpBound)
  364.     {
  365.         // Note: We intentionally ignore the read
  366.         //       size and use the maximum possible
  367.         //       UDP packet size. This allows us to
  368.         //       properly receive any UDP packet.
  369. res = DoRead(0xffff);
  370.     }
  371.     return res;
  372. }
  373. STDMETHODIMP HXSymbianUDPSocket::Write(THIS_ IHXBuffer* pBuffer)
  374. {
  375.     DPRINTF(D_UDPSOCKET, ("HXSymbianUDPSocket::Write()n"));
  376.     return WriteTo(m_ulRemoteAddr, m_nRemotePort, pBuffer);
  377. }
  378. STDMETHODIMP HXSymbianUDPSocket::WriteTo(THIS_ 
  379.  ULONG32    ulAddr,
  380.  UINT16     nPort,
  381.  IHXBuffer* pBuffer)
  382. {
  383.     DPRINTF(D_UDPSOCKET, ("HXSymbianUDPSocket::WriteTo(%08lx, %d)n",
  384.   ulAddr, nPort));
  385.     HX_RESULT res = HXR_FAILED;
  386.     if ((m_state == udpBound) && pBuffer)
  387.     {
  388. if (m_pWriter->IsActive())
  389. {
  390.     // A write is in process. Cache the information
  391.     // about this write for later use.
  392.     HXSymbianUDPWriteInfo* pWriteInfo = 
  393. new HXSymbianUDPWriteInfo(ulAddr, nPort, pBuffer);
  394.     if (pWriteInfo)
  395.     {
  396. LISTPOSITION listRet = m_writeList.AddTail(pWriteInfo);
  397.                 if( listRet == NULL )
  398.                 {
  399.     res = HXR_OUTOFMEMORY;
  400.     HX_DELETE(pWriteInfo);
  401.                 }
  402.                 else
  403.                 {
  404.     res = HXR_OK;
  405.                 }
  406.     }
  407. }
  408. else
  409. {
  410.     // Do the write now
  411.     m_pWriter->Write(m_socket, ulAddr, nPort, pBuffer);
  412.     res = HXR_OK;
  413. }
  414.     }
  415.     return res;
  416. }
  417. STDMETHODIMP HXSymbianUDPSocket::GetLocalPort(THIS_
  418.       REF(UINT16) port)
  419. {
  420.     DPRINTF(D_UDPSOCKET, ("HXSymbianUDPSocket::GetLocalPort()n"));
  421.     HX_RESULT res = HXR_FAILED;
  422.     if (m_state == udpBound)
  423.     {
  424. port = m_socket.LocalPort();
  425. res = HXR_OK;
  426.     }
  427.     return res;
  428. }
  429. STDMETHODIMP HXSymbianUDPSocket::JoinMulticastGroup(THIS_
  430.     ULONG32 ulMulticastAddr,
  431.     ULONG32 ulInterfaceAddr)
  432. {
  433.     DPRINTF(D_UDPSOCKET, ("HXSymbianUDPSocket::JoinMulticastGroup(%08lx %08lx)n",
  434.   ulMulticastAddr, ulInterfaceAddr));
  435.     return HXR_NOTIMPL;
  436. }
  437.     
  438. STDMETHODIMP HXSymbianUDPSocket::LeaveMulticastGroup(THIS_
  439.      ULONG32 ulMulticastAddr,
  440.      ULONG32 ulInterfaceAddr)
  441. {
  442.     DPRINTF(D_UDPSOCKET, ("HXSymbianUDPSocket::LeaveMulticastGroup(%08lx %08lx)n",
  443.   ulMulticastAddr, ulInterfaceAddr));
  444.     return HXR_NOTIMPL;
  445. }
  446. STDMETHODIMP HXSymbianUDPSocket::SetOption(THIS_ 
  447.    HX_SOCKET_OPTION option,
  448.    UINT32 ulValue)
  449. {
  450.     DPRINTF(D_UDPSOCKET, ("HXSymbianUDPSocket::SetOption(%d, %ld)n",
  451.   option, ulValue));
  452.     HX_RESULT res = HXR_FAILED;
  453.     if (m_state == udpNotOpen)
  454.     {
  455. switch(option)
  456. {
  457. case  HX_SOCKOPT_REUSE_ADDR:
  458. case HX_SOCKOPT_REUSE_PORT:
  459.     if (m_socket.SetOpt(KSoReuseAddr, KSOLSocket, ulValue) == KErrNone)
  460.     {
  461. res = HXR_OK;
  462.     }
  463.     break;
  464. case HX_SOCKOPT_BROADCAST:
  465. case HX_SOCKOPT_SET_RECVBUF_SIZE:
  466. case HX_SOCKOPT_SET_SENDBUF_SIZE:
  467. case HX_SOCKOPT_MULTICAST_IF:
  468.     res = HXR_UNEXPECTED;
  469.     break;
  470. default:
  471.     res = HXR_FAILED;
  472.     break;
  473. };
  474.     }
  475.     return res;
  476. }
  477. void HXSymbianUDPSocket::OnWriteDone(HX_RESULT status)
  478. {
  479.     DPRINTF(D_UDPSOCKET, ("HXSymbianUDPSocket::WriteDone(%ld)n", status));
  480.     if (status == HXR_OK)
  481.     {
  482. if (m_writeList.GetCount() > 0)
  483. {
  484.     // Write the next buffer in the list
  485.     HXSymbianUDPWriteInfo* pWriteInfo = 
  486. (HXSymbianUDPWriteInfo*)m_writeList.RemoveHead();
  487.     IHXBuffer* pBuffer = pWriteInfo->GetBuffer();
  488.     m_pWriter->Write(m_socket, 
  489.      pWriteInfo->Address(), pWriteInfo->Port(),
  490.      pBuffer);
  491.     HX_RELEASE(pBuffer);
  492.     delete pWriteInfo;
  493. }
  494.     }
  495.     else
  496.     {
  497. CloseSocket(status);
  498.     }
  499. }
  500. void HXSymbianUDPSocket::OnReadDone(HX_RESULT status, 
  501.     ULONG32 ulAddr, UINT16 nPort, 
  502.     IHXBuffer* pBuffer)
  503. {
  504.     DPRINTF(D_UDPSOCKET, ("HXSymbianUDPSocket::OnReadDone(%ld, %08lx, %d)n",
  505.   status, ulAddr, nPort));
  506.     DECLARE_SMART_POINTER_UNKNOWN scopeRef((IHXUDPSocket*)this);
  507.     
  508.     // We assume that the reponse object is going to be responsible for error 
  509.     // handling, so the symbian network services does not try to notify
  510.     // anyone of errors returned here.
  511.     if (m_pResponse)
  512.     {
  513. m_pResponse->ReadDone(status, pBuffer, ulAddr, nPort);
  514.     }
  515.     if (status != HXR_OK)
  516.     {
  517. CloseSocket(status);
  518.     }
  519. }
  520. HX_RESULT HXSymbianUDPSocket::DoRead(UINT16 size)
  521. {
  522.     DPRINTF(D_UDPSOCKET, ("HXSymbianUDPSocket::DoRead(%d)n", size));
  523.     HX_RESULT res = HXR_FAILED;
  524.     
  525.     if (m_pReader)
  526.     {
  527.         res = m_pReader->Read(m_socket, size);
  528.     }
  529.     return res;
  530. }
  531. void HXSymbianUDPSocket::CloseSocket(HX_RESULT status)
  532. {
  533.     if (m_state != udpNotOpen)
  534.     {
  535. // Cancel writer
  536. if (m_pWriter->IsActive())
  537. {
  538.     m_socket.CancelWrite();
  539.     m_pWriter->Cancel();
  540. }
  541. if (m_pReader->IsActive())
  542. {
  543.     m_socket.CancelRecv();
  544.     m_pReader->Cancel();
  545. }
  546. // Clear the writer list
  547. while (m_writeList.GetCount() > 0)
  548. {
  549.     // Write the next buffer in the list
  550.     HXSymbianUDPWriteInfo* pWriteInfo = 
  551. (HXSymbianUDPWriteInfo*)m_writeList.RemoveHead();
  552.     
  553.     HX_DELETE(pWriteInfo);
  554. }
  555. m_state = udpOpen;
  556.     }
  557. }