ot_udp.cp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:16k
源码类别:

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 "hxcom.h"
  36. #include "hxbuffer.h"
  37. #include "timebuff.h"
  38. #include "hxtick.h"
  39. #include "netbyte.h"
  40. #include "OT_UDP.h"
  41. #include "hxerrors.h"
  42. #include "MWDebug.h"
  43. #include <string.h>
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <ctype.h>
  47. #include "hxmm.h"
  48. //#define USE_DEFERRED_IMPL 1
  49. OT_UDP::OT_UDP (void)
  50. { /* begin OT_UDP */
  51. m_pInBuffer = new char[TCP_BUF_SIZE];
  52. m_bIsBroadcastEnabled = FALSE;
  53. } /* end OT_UDP */
  54. OT_UDP::~OT_UDP (void)
  55. { /* begin ~OT_UDP */
  56. Cleanup();
  57. } /* end ~OT_UDP */
  58. HX_RESULT
  59. OT_UDP::init(UINT32 local_addr, UINT16 port, UINT16 blocking)
  60. {
  61. HX_RESULT theErr = Create();
  62. if(!theErr) theErr = ActiveOpen(port);
  63. if(theErr) Cleanup();
  64. return theErr;
  65. }
  66. void
  67. OT_UDP::done(void)
  68. {
  69. Cleanup();
  70. }
  71. /*----------------------------------------------------------------------------
  72. Create
  73. Create a UDP endpoint.
  74. Exit: function result = error code.
  75. ----------------------------------------------------------------------------*/
  76. OSErr OT_UDP::Create(void)
  77. {
  78. OSErr theErr = HXR_OK;
  79. // clear completion flag
  80. mComplete = false;
  81. // open UDP endpoint
  82. #ifdef USE_DEFERRED_IMPL
  83. theErr = OTAsyncOpenEndpoint(OTCreateConfiguration(kUDPName), 0, nil, UDPTCPNotifyProc, this);
  84. #else
  85. #ifdef _CARBON
  86. theErr = OTAsyncOpenEndpointInContext(OTCreateConfiguration(kUDPName), 0, nil,
  87. ::NewOTNotifyUPP(UDPNotifyProc), this, NULL);
  88. #else
  89. theErr = OTAsyncOpenEndpoint(OTCreateConfiguration(kUDPName), 0, nil,
  90. UDPNotifyProc, this);
  91. #endif
  92. #endif
  93. // wait for completion
  94. if(!theErr) theErr = OTWait();
  95. // check for errors
  96. if (theErr || mCode != T_OPENCOMPLETE)
  97. theErr = HXR_SOCKET_CREATE;
  98. if(!theErr)
  99. {
  100. mRef = (EndpointRef) mCookie; // save UDP provider reference
  101. mDataArrived = FALSE;
  102. mDataFlowOn = FALSE;
  103. }
  104. #if 0
  105. if (!theErr)
  106. {
  107.  UINT32 uBufDepth = 0;
  108.  // XTI_RCVBUF : size of internal buffer
  109.  // XTI_RCVLOWAT : minimum accumulated size for notification
  110. OT_net::GetFourByteOption(mRef, XTI_GENERIC, XTI_RCVBUF, &uBufDepth);
  111. OT_net::GetFourByteOption(mRef, XTI_GENERIC, XTI_RCVLOWAT, &uBufDepth);
  112. OT_net::SetFourByteOption(mRef, XTI_GENERIC, XTI_RCVBUF, 64000);
  113. OT_net::SetFourByteOption(mRef, XTI_GENERIC, XTI_RCVLOWAT, 32000);
  114. OT_net::GetFourByteOption(mRef, XTI_GENERIC, XTI_RCVBUF, &uBufDepth);
  115. OT_net::GetFourByteOption(mRef, XTI_GENERIC, XTI_RCVLOWAT, &uBufDepth);
  116. OT_net::GetFourByteOption(mRef, XTI_GENERIC, XTI_RCVLOWAT, &uBufDepth);
  117. }
  118. #endif
  119. if(theErr)  // error occured close provider
  120. {
  121. if(mRef != 0) OTCloseProvider(mRef);
  122. mRef = 0;
  123. }
  124. mLastError = theErr;
  125. return theErr;
  126. }
  127. /*----------------------------------------------------------------------------
  128. Release 
  129. Release a UDP stream.
  130. Exit: function result = error code.
  131. Any active connection is also aborted, if necessary, before releasing 
  132. the stream.
  133. ----------------------------------------------------------------------------*/
  134. OSErr OT_UDP::Cleanup (void)
  135. {
  136. OSErr theErr = HXR_OK;
  137. Boolean abort;
  138. abort = !mOtherSideHasClosed || !mWeHaveClosed;
  139. if(mRef)
  140. {
  141. OTRemoveNotifier(mRef);
  142. theErr = OTCloseProvider(mRef);
  143. mRef = 0;
  144. mConnectionOpen = FALSE;
  145. mOtherSideHasClosed = TRUE;
  146. mWeHaveClosed = TRUE;
  147. }
  148. HX_VECTOR_DELETE(m_pInBuffer);
  149. mLastError = theErr;
  150. return theErr;
  151. }
  152. /*----------------------------------------------------------------------------
  153. ActiveOpen 
  154. Open an active stream.
  155. addr = IP address of server.
  156. port = port number of service.
  157. Exit: function result = error code.
  158. ----------------------------------------------------------------------------*/
  159.  OSErr OT_UDP::ActiveOpen (
  160.  
  161. UINT16 port)
  162. {
  163. OSErr theErr = HXR_OK;
  164. InetAddress reqAd,retAd;
  165. TBind req,ret;
  166. // get Inet address of port
  167. OTInitInetAddress(&reqAd, port, (InetHost) 0);
  168. // bind udp to current address and requested port
  169. req.addr.maxlen = sizeof(struct InetAddress);
  170. req.addr.len = sizeof(struct InetAddress);
  171. req.addr.buf = (unsigned char *) &reqAd;
  172. req.qlen = 1; // don't care for udp
  173. ret.addr.maxlen = sizeof(struct InetAddress);
  174. ret.addr.len = sizeof(struct InetAddress);
  175. ret.addr.buf = (unsigned char *) &retAd;
  176. // clear completion flag
  177. mComplete = false;
  178. // bind provider to return structure
  179. theErr = OTBind(mRef, &req, &ret);
  180. if(theErr)
  181. {
  182. mLastError = theErr;
  183. theErr = HXR_BIND;
  184. }
  185. // wait for bind completion
  186. if(!theErr)
  187. {
  188. theErr = OTWait();
  189. if(theErr == kOTNoDataErr) theErr = HXR_OK;
  190. if(theErr || mCode != T_BINDCOMPLETE) 
  191. {
  192. theErr = theErr ? theErr : HXR_BIND;
  193. mLastError = theErr;
  194. theErr = HXR_BIND;
  195. }
  196. }
  197. // get local port
  198. if(!theErr)
  199. {
  200. mLocalPort = reqAd.fPort;
  201. mConnectionOpen = TRUE;
  202. mOtherSideHasClosed = FALSE;
  203. mWeHaveClosed = FALSE;
  204. }
  205. return theErr;
  206. }
  207. /*----------------------------------------------------------------------------
  208. write 
  209. write data on a UDP stream.
  210. Entry: data = pointer to data to send.
  211. len = length of data to send.
  212. Exit: function result = error code.
  213. ----------------------------------------------------------------------------*/
  214. HX_RESULT
  215. OT_UDP::writeto (
  216. void  *buf,
  217. UINT16  *size, 
  218. ULONG32 addr,
  219. UINT16  port)
  220. {
  221. OSStatus result;
  222. TUnitData unitdata;
  223. InetAddress sin;
  224. TOption option;
  225. HX_RESULT theErr;
  226. ::OTInitInetAddress(&sin, port, addr);
  227. unitdata.addr.len = sizeof(struct InetAddress);
  228. unitdata.addr.buf = (UInt8*) &sin;
  229. unitdata.udata.len = *size;
  230. unitdata.udata.buf = (UInt8*) buf;
  231.   if(m_bIsBroadcastEnabled)
  232.   {
  233.   unitdata.opt.len = sizeof(option);
  234.   option.len = kOTFourByteOptionSize;
  235.   option.level = INET_IP;
  236. #ifdef _MAC_MACHO
  237.   option.name = kIP_BROADCAST;
  238. #else
  239.   option.name = IP_BROADCAST;
  240. #endif
  241.   option.status = 0;
  242.   option.value[0] = 1;
  243.   unitdata.opt.buf = (UInt8*) &option;
  244.   }
  245.   else
  246.   {
  247.   unitdata.opt.len = 0;
  248.   unitdata.opt.maxlen = 0;
  249.   unitdata.opt.buf = 0;
  250.   }
  251. result = ::OTSndUData(mRef,&unitdata);
  252. if(result == 0)
  253. {
  254. return HXR_OK;
  255. }
  256. switch(result)
  257. {
  258. case kOTFlowErr:
  259. mDataFlowOn = TRUE;
  260. theErr = HXR_WOULD_BLOCK;
  261. break;
  262. case kENOMEMErr:
  263. case kEBUSYErr:
  264. case kOTOutStateErr:
  265. case kEWOULDBLOCKErr:
  266. case kOTStateChangeErr:
  267. theErr = HXR_WOULD_BLOCK;
  268. break;
  269. case kOTLookErr:
  270. {
  271.                         OSStatus lookErr = ::OTLook(mRef);
  272. TUDErr UDErr;
  273. if(lookErr == T_UDERR)
  274. {
  275. UInt8 buf1[256];
  276. UInt8 buf2[256];
  277. UDErr.addr.maxlen = 256;
  278. UDErr.addr.buf = buf1;
  279. UDErr.opt.maxlen = 256;
  280. UDErr.opt.buf = buf2;
  281. lookErr = ::OTRcvUDErr(mRef, &UDErr);
  282. theErr = HXR_NET_WRITE;
  283. }
  284. else
  285. {
  286. theErr =  HXR_NET_WRITE;
  287. break;
  288. }
  289. }
  290.                         break;
  291. default:
  292. theErr =  HXR_NET_WRITE;
  293. break;
  294. }
  295. *size = 0;
  296. mLastError = theErr;
  297. return theErr;
  298. }
  299. /*******************************************************************************
  300. ** read
  301. ********************************************************************************/
  302. HX_RESULT
  303. OT_UDP::read (void *data, UINT16 *len)
  304. {
  305. return HXR_NOTIMPL;
  306. }
  307. HX_RESULT
  308. OT_UDP::readfrom (REF(IHXBuffer*)   pBuffer,
  309.   REF(UINT32)     ulAddress,
  310.   REF(UINT16)     ulPort)
  311. {
  312. UINT16 size = 0;
  313. OSStatus theErr = HXR_OK;
  314. TUnitData unitdata;
  315. OTFlags flags;
  316. InetAddress sin;
  317. pBuffer = NULL;
  318. ulAddress = 0;
  319. ulPort = 0;
  320. mLastError = HXR_OK;
  321. if(!mDataArrived)
  322. {
  323. return HXR_WOULD_BLOCK;
  324. }
  325. unitdata.opt.len = 0;
  326. unitdata.addr.len = 0;
  327. unitdata.udata.len = 0;
  328. unitdata.addr.maxlen = sizeof(struct InetAddress);
  329. unitdata.opt.maxlen = 0;
  330. unitdata.opt.buf = 0;
  331. unitdata.udata.maxlen = TCP_BUF_SIZE; // used to be 256
  332. unitdata.udata.buf = (UInt8*)m_pInBuffer;
  333. unitdata.addr.buf = (UInt8*) &sin;
  334. theErr = OTRcvUData(mRef,&unitdata, &flags);
  335. if (theErr == HXR_OK)
  336. {
  337. size = unitdata.udata.len;
  338. /* I have seen the size to be a really large value some times.
  339.  * This was before I added initializaion of
  340.        *  unitdata.opt.len = 0;
  341.      *  unitdata.addr.len = 0;
  342.      *  unitdata.udata.len = 0;
  343.      *
  344.      * It looks like sometimes OTRecvData returns no error and DOES NOT
  345.      * set the udata.len value. We now make sure that we have indeed
  346.      * received some data before creating an IHXBuffer
  347.      *
  348.      * XXXRA
  349.      */
  350.  
  351. HX_ASSERT(size > 0);
  352. if (size > 0)
  353. {
  354.     CHXTimeStampedBuffer* pTimeBuffer = new CHXTimeStampedBuffer;
  355.     pTimeBuffer->AddRef();
  356.     pTimeBuffer->SetTimeStamp(HX_GET_TICKCOUNT());
  357.     pTimeBuffer->Set((UCHAR*)m_pInBuffer, size);
  358.     pBuffer = (IHXBuffer*) pTimeBuffer;
  359.     ulAddress = DwToHost(sin.fHost);
  360.     ulPort = WToHost(sin.fPort);
  361. }
  362. }
  363. else if(theErr == kOTNoDataErr)
  364. {
  365. theErr = HXR_NO_DATA;
  366. // xxxbobclark This used to return HXR_OK if there was no data.
  367. // But now there's threaded networking code that needs to rely
  368. // on this returning HXR_NO_DATA if there's really no data.
  369. }
  370. else if(theErr == kEWOULDBLOCKErr)
  371. theErr = HXR_WOULD_BLOCK;
  372. else
  373. theErr = HXR_SERVER_DISCONNECTED;
  374. mLastError = theErr;
  375. return theErr;
  376. }
  377. /*
  378. HX_RESULT
  379. OT_UDP::listen (UINT16  backlog)
  380. {
  381. return(HXR_INVALID_OPERATION);
  382. }
  383. */
  384. HX_RESULT
  385. OT_UDP::connect(
  386. const char *host, 
  387. UINT16  port,
  388. UINT16  blocking,
  389. ULONG32 ulPlatform)
  390. {
  391. return(HXR_INVALID_OPERATION);
  392. }
  393. /* join_multicast_group() has this socket join a multicast group */
  394. HX_RESULT
  395. OT_UDP::join_multicast_group (ULONG32 multicastHost, ULONG32 if_addr)
  396. {
  397. OSStatus theErr = kOTNoError;
  398. // mLocalPort is set by the init() function
  399. // ::OTInitInetAddress(&mMulticastAddr, mLocalPort, multicastHost);
  400. // since we are already bound to an IP addr on our system
  401. // (bind occurred in the init() function) we can now Let 
  402. // IP know to listen for this multicast IP address on all interfaces.
  403. TOptMgmt  optReq;
  404. UInt8   optBuffer[ kOTOptionHeaderSize + sizeof(TIPAddMulticast) ];
  405. ULONG32 optLength = kOTOptionHeaderSize + sizeof(TIPAddMulticast);
  406. TOption*   opt = (TOption*)optBuffer;
  407. TIPAddMulticast* addopt = (TIPAddMulticast*)opt->value; 
  408. optReq.flags = T_NEGOTIATE;
  409. optReq.opt.len = optLength;
  410. optReq.opt.maxlen = optLength;
  411. optReq.opt.buf = (UInt8*) optBuffer;
  412. opt->level = INET_IP;
  413. #ifdef _MAC_MACHO
  414. opt->name = kIP_ADD_MEMBERSHIP;
  415. #else
  416. opt->name = IP_ADD_MEMBERSHIP;
  417. #endif
  418. opt->len = optLength;
  419. opt->status = 0;
  420. addopt->multicastGroupAddress = multicastHost;
  421. addopt->interfaceAddress = if_addr;
  422. // clear completion flag
  423. mComplete = false;
  424. theErr = ::OTOptionManagement(mRef,&optReq, &optReq);
  425. // wait for completion
  426. if(!theErr) 
  427. theErr = OTWait();
  428. if(theErr)
  429. theErr = HX_MULTICAST_JOIN_ERROR;
  430. return theErr;
  431. }
  432. HX_RESULT
  433. OT_UDP::leave_multicast_group(ULONG32 multicastHost, ULONG32 if_addr)
  434. {
  435. HX_RESULT theErr = HXR_OK;
  436. TOptMgmt  optReq;
  437. UInt8   optBuffer[ kOTOptionHeaderSize + sizeof(TIPAddMulticast) ];
  438. ULONG32 optLength = kOTOptionHeaderSize + sizeof(TIPAddMulticast);
  439. TOption*   opt = (TOption*)optBuffer;
  440. TIPAddMulticast* addopt = (TIPAddMulticast*)opt->value; 
  441. optReq.flags = T_NEGOTIATE;
  442. optReq.opt.len = optLength;
  443. optReq.opt.maxlen = optLength;
  444. optReq.opt.buf = (UInt8*) optBuffer;
  445. opt->level = INET_IP;
  446. #ifdef _MAC_MACHO
  447. opt->name = kIP_DROP_MEMBERSHIP;
  448. #else
  449. opt->name = IP_DROP_MEMBERSHIP;
  450. #endif
  451. opt->len = optLength;
  452. opt->status = 0;
  453. addopt->multicastGroupAddress = multicastHost;
  454. addopt->interfaceAddress = if_addr;
  455. // clear completion flag
  456. mComplete = false;
  457. theErr = ::OTOptionManagement(mRef,&optReq, &optReq);
  458. // wait for completion
  459. if(!theErr) 
  460. theErr = OTWait();
  461. if(theErr)
  462. return HX_GENERAL_MULTICAST_ERROR;
  463. return HXR_OK;
  464. }
  465. HX_RESULT
  466. OT_UDP::set_broadcast(BOOL enable)
  467. {
  468. OSStatus theErr = kOTNoError;
  469.   mComplete = false;
  470.     m_bIsBroadcastEnabled = enable;
  471.   return HXR_OK;
  472. }
  473.  
  474. /*----------------------------------------------------------------------------
  475. UDPNotifyProc 
  476. Open Transport notifier proc for UDP streams.
  477. Entry: s = pointer to UDP stream.
  478. code = OT event code.
  479. result = OT result.
  480. cookie = OT cookie.
  481. ----------------------------------------------------------------------------*/
  482. pascal void OT_UDP::UDPNotifyProc (
  483.  void *stream, 
  484.  OTEventCode code,
  485.  OTResult result, 
  486.  void *cookie )
  487.  
  488. {
  489. OT_UDP* s =  (OT_UDP*) stream;
  490. HXMM_INTERRUPTON();
  491. s->ProcessCmd(code, result, cookie);
  492. HXMM_INTERRUPTOFF();
  493. return;
  494. }
  495. void
  496. OT_UDP::ProcessCmd(OTEventCode code, OTResult result, void* cookie)
  497. {
  498. switch (code) 
  499. {
  500. case T_DISCONNECT:
  501. /* Other side has aborted. */
  502. mOtherSideHasClosed = true;
  503. mComplete = true;
  504. mConnectionOpen = FALSE;
  505. MWDebugPStr("pT_DISCONNECT");
  506.         if(mCallBack) mCallBack->Func(CONNECT_NOTIFICATION, FALSE);
  507. break;
  508. case T_ORDREL:
  509. /* Other side has closed. Close our side if necessary. */
  510. mOtherSideHasClosed = true;
  511. mComplete = true;
  512. mConnectionOpen = FALSE;
  513. if (mClosing) mRelease = true;
  514. MWDebugPStr("pT_ORDREL");
  515. break;
  516. case T_DATA:
  517. mDataArrived = TRUE;
  518. //if(mCallBack) mCallBack->callback_task(HX_UDP_CALLBACK);
  519. if(mCallBack) mCallBack->Func(READ_NOTIFICATION);
  520. break;
  521. case T_BINDCOMPLETE:
  522. case T_CONNECT:
  523. case T_PASSCON:
  524. mComplete = true;
  525. mCode = code;
  526. mResult = result;
  527. mCookie = cookie;
  528. break;
  529. case T_OPENCOMPLETE:
  530. mConnectionOpen = TRUE;
  531. mComplete = true;
  532. mCode = code;
  533. mResult = result;
  534. mCookie = cookie;
  535. if(mCallBack) mCallBack->Func(CONNECT_NOTIFICATION);
  536. break;
  537. case T_GODATA:
  538. mDataFlowOn = FALSE;
  539. MWDebugPStr("pT_GODATA");
  540. break;
  541. case T_OPTMGMTCOMPLETE:
  542. mComplete = true;
  543. mCode = code;
  544. mResult = result;
  545. mCookie = cookie;
  546. break;
  547. }
  548. return;
  549. }