PageRenderTime 45ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/qwaqvm/platforms/Cross/third-party/resiprocate-src-1.6/resip/stack/UdpTransport.cxx

http://openqwaq.googlecode.com/
C++ | 548 lines | 374 code | 75 blank | 99 comment | 52 complexity | 05113011953b10c1b1e9e3839c119f3f MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0, BSD-3-Clause
  1. #if defined(HAVE_CONFIG_H)
  2. #include "resip/stack/config.hxx"
  3. #endif
  4. #include <memory>
  5. #include "resip/stack/Helper.hxx"
  6. #include "resip/stack/SendData.hxx"
  7. #include "resip/stack/SipMessage.hxx"
  8. #include "resip/stack/UdpTransport.hxx"
  9. #include "rutil/Data.hxx"
  10. #include "rutil/DnsUtil.hxx"
  11. #include "rutil/Logger.hxx"
  12. #include "rutil/Socket.hxx"
  13. #include "rutil/WinLeakCheck.hxx"
  14. #include "rutil/compat.hxx"
  15. #include "rutil/stun/Stun.hxx"
  16. #ifdef USE_SIGCOMP
  17. #include <osc/Stack.h>
  18. #include <osc/StateChanges.h>
  19. #include <osc/SigcompMessage.h>
  20. #endif
  21. #define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT
  22. using namespace std;
  23. using namespace resip;
  24. UdpTransport::UdpTransport(Fifo<TransactionMessage>& fifo,
  25. int portNum,
  26. IpVersion version,
  27. StunSetting stun,
  28. const Data& pinterface,
  29. AfterSocketCreationFuncPtr socketFunc,
  30. Compression &compression)
  31. : InternalTransport(fifo, portNum, version, pinterface, socketFunc, compression),
  32. mSigcompStack(0),
  33. mExternalUnknownDatagramHandler(0)
  34. {
  35. mTuple.setType(transport());
  36. mFd = InternalTransport::socket(transport(), version);
  37. mTuple.mFlowKey=mFd;
  38. bind();
  39. InfoLog (<< "Creating UDP transport host=" << pinterface
  40. << " port=" << mTuple.getPort()
  41. << " ipv4=" << bool(version==V4) );
  42. #ifdef USE_SIGCOMP
  43. if (mCompression.isEnabled())
  44. {
  45. DebugLog (<< "Compression enabled for transport: " << *this);
  46. mSigcompStack = new osc::Stack(mCompression.getStateHandler());
  47. mCompression.addCompressorsToStack(mSigcompStack);
  48. }
  49. else
  50. {
  51. DebugLog (<< "Compression disabled for transport: " << *this);
  52. }
  53. #else
  54. DebugLog (<< "No compression library available: " << *this);
  55. #endif
  56. }
  57. UdpTransport::~UdpTransport()
  58. {
  59. InfoLog (<< "Shutting down " << mTuple);
  60. #ifdef USE_SIGCOMP
  61. delete mSigcompStack;
  62. #endif
  63. }
  64. void
  65. UdpTransport::process(FdSet& fdset)
  66. {
  67. // pull buffers to send out of TxFifo
  68. // receive datagrams from fd
  69. // preparse and stuff into RxFifo
  70. if (mTxFifo.messageAvailable() && fdset.readyToWrite(mFd))
  71. {
  72. std::auto_ptr<SendData> sendData = std::auto_ptr<SendData>(mTxFifo.getNext());
  73. //DebugLog (<< "Sent: " << sendData->data);
  74. //DebugLog (<< "Sending message on udp.");
  75. assert( &(*sendData) );
  76. assert( sendData->destination.getPort() != 0 );
  77. const sockaddr& addr = sendData->destination.getSockaddr();
  78. int expected;
  79. int count;
  80. #ifdef USE_SIGCOMP
  81. // If message needs to be compressed, compress it here.
  82. if (mSigcompStack &&
  83. sendData->sigcompId.size() > 0 &&
  84. !sendData->isAlreadyCompressed )
  85. {
  86. osc::SigcompMessage *sm = mSigcompStack->compressMessage
  87. (sendData->data.data(), sendData->data.size(),
  88. sendData->sigcompId.data(), sendData->sigcompId.size(),
  89. isReliable());
  90. DebugLog (<< "Compressed message from "
  91. << sendData->data.size() << " bytes to "
  92. << sm->getDatagramLength() << " bytes");
  93. expected = sm->getDatagramLength();
  94. count = sendto(mFd,
  95. sm->getDatagramMessage(),
  96. sm->getDatagramLength(),
  97. 0, // flags
  98. &addr, sendData->destination.length());
  99. delete sm;
  100. }
  101. else
  102. #endif
  103. {
  104. expected = sendData->data.size();
  105. count = sendto(mFd,
  106. sendData->data.data(), sendData->data.size(),
  107. 0, // flags
  108. &addr, sendData->destination.length());
  109. }
  110. if ( count == SOCKET_ERROR )
  111. {
  112. int e = getErrno();
  113. error(e);
  114. InfoLog (<< "Failed (" << e << ") sending to " << sendData->destination);
  115. fail(sendData->transactionId);
  116. }
  117. else
  118. {
  119. if (count != expected)
  120. {
  121. ErrLog (<< "UDPTransport - send buffer full" );
  122. fail(sendData->transactionId);
  123. }
  124. }
  125. }
  126. // !jf! this may have to change - when we read a message that is too big
  127. if ( fdset.readyToRead(mFd) )
  128. {
  129. //should this buffer be allocated on the stack and then copied out, as it
  130. //needs to be deleted every time EWOULDBLOCK is encountered
  131. // .dlb. can we determine the size of the buffer before we allocate?
  132. // something about MSG_PEEK|MSG_TRUNC in Stevens..
  133. // .dlb. RFC3261 18.1.1 MUST accept 65K datagrams. would have to attempt to
  134. // adjust the UDP buffer as well...
  135. char* buffer = MsgHeaderScanner::allocateBuffer(MaxBufferSize);
  136. // !jf! how do we tell if it discarded bytes
  137. // !ah! we use the len-1 trick :-(
  138. Tuple tuple(mTuple);
  139. socklen_t slen = tuple.length();
  140. int len = recvfrom( mFd,
  141. buffer,
  142. MaxBufferSize,
  143. 0 /*flags */,
  144. &tuple.getMutableSockaddr(),
  145. &slen);
  146. if ( len == SOCKET_ERROR )
  147. {
  148. int err = getErrno();
  149. if ( err != EWOULDBLOCK )
  150. {
  151. error( err );
  152. }
  153. }
  154. if (len == 0 || len == SOCKET_ERROR)
  155. {
  156. delete[] buffer;
  157. buffer=0;
  158. return;
  159. }
  160. if (len+1 >= MaxBufferSize)
  161. {
  162. InfoLog(<<"Datagram exceeded max length "<<MaxBufferSize);
  163. delete [] buffer; buffer=0;
  164. return;
  165. }
  166. //handle incoming CRLFCRLF keep-alive packets
  167. if (len == 4 &&
  168. strncmp(buffer, Symbols::CRLFCRLF, len) == 0)
  169. {
  170. delete[] buffer;
  171. buffer = 0;
  172. StackLog(<<"Throwing away incoming firewall keep-alive");
  173. return;
  174. }
  175. // this must be a STUN response (or garbage)
  176. if (buffer[0] == 1 && buffer[1] == 1 && ipVersion() == V4)
  177. {
  178. resip::Lock lock(myMutex);
  179. StunMessage resp;
  180. memset(&resp, 0, sizeof(StunMessage));
  181. if (stunParseMessage(buffer, len, resp, false))
  182. {
  183. in_addr sin_addr;
  184. #if defined(WIN32)
  185. sin_addr.S_un.S_addr = htonl(resp.mappedAddress.ipv4.addr);
  186. #else
  187. sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);
  188. #endif
  189. mStunMappedAddress = Tuple(sin_addr,resp.mappedAddress.ipv4.port, UDP);
  190. mStunSuccess = true;
  191. }
  192. delete[] buffer;
  193. buffer = 0;
  194. return;
  195. }
  196. // this must be a STUN request (or garbage)
  197. if (buffer[0] == 0 && buffer[1] == 1 && ipVersion() == V4)
  198. {
  199. bool changePort = false;
  200. bool changeIp = false;
  201. StunAddress4 myAddr;
  202. const sockaddr_in& bi = (const sockaddr_in&)boundInterface();
  203. myAddr.addr = ntohl(bi.sin_addr.s_addr);
  204. myAddr.port = ntohs(bi.sin_port);
  205. StunAddress4 from; // packet source
  206. const sockaddr_in& fi = (const sockaddr_in&)tuple.getSockaddr();
  207. from.addr = ntohl(fi.sin_addr.s_addr);
  208. from.port = ntohs(fi.sin_port);
  209. StunMessage resp;
  210. StunAddress4 dest;
  211. StunAtrString hmacPassword;
  212. hmacPassword.sizeValue = 0;
  213. StunAddress4 secondary;
  214. secondary.port = 0;
  215. secondary.addr = 0;
  216. bool ok = stunServerProcessMsg( buffer, len, // input buffer
  217. from, // packet source
  218. secondary, // not used
  219. myAddr, // address to fill into response
  220. myAddr, // not used
  221. &resp, // stun response
  222. &dest, // where to send response
  223. &hmacPassword, // not used
  224. &changePort, // not used
  225. &changeIp, // not used
  226. false ); // logging
  227. if (ok)
  228. {
  229. DebugLog(<<"Got UDP STUN keepalive. Sending response...");
  230. char* response = new char[STUN_MAX_MESSAGE_SIZE];
  231. int rlen = stunEncodeMessage( resp,
  232. response,
  233. STUN_MAX_MESSAGE_SIZE,
  234. hmacPassword,
  235. false );
  236. SendData* stunResponse = new SendData(tuple, response, rlen);
  237. mTxFifo.add(stunResponse);
  238. }
  239. delete[] buffer;
  240. buffer = 0;
  241. return;
  242. }
  243. #ifdef USE_SIGCOMP
  244. osc::StateChanges *sc = 0;
  245. #endif
  246. // Attempt to decode SigComp message, if appropriate.
  247. if ((buffer[0] & 0xf8) == 0xf8)
  248. {
  249. if (!mCompression.isEnabled())
  250. {
  251. InfoLog(<< "Discarding unexpected SigComp Message");
  252. delete[] buffer;
  253. buffer = 0;
  254. return;
  255. }
  256. #ifdef USE_SIGCOMP
  257. char* newBuffer = MsgHeaderScanner::allocateBuffer(MaxBufferSize);
  258. size_t uncompressedLength =
  259. mSigcompStack->uncompressMessage(buffer, len,
  260. newBuffer, MaxBufferSize, sc);
  261. DebugLog (<< "Uncompressed message from "
  262. << len << " bytes to "
  263. << uncompressedLength << " bytes");
  264. osc::SigcompMessage *nack = mSigcompStack->getNack();
  265. if (nack)
  266. {
  267. mTxFifo.add(new SendData(tuple,
  268. Data(nack->getDatagramMessage(),
  269. nack->getDatagramLength()),
  270. Data::Empty,
  271. Data::Empty,
  272. true)
  273. );
  274. delete nack;
  275. }
  276. delete[] buffer;
  277. buffer = newBuffer;
  278. len = uncompressedLength;
  279. #endif
  280. }
  281. buffer[len]=0; // null terminate the buffer string just to make debug easier and reduce errors
  282. //DebugLog ( << "UDP Rcv : " << len << " b" );
  283. //DebugLog ( << Data(buffer, len).escaped().c_str());
  284. SipMessage* message = new SipMessage(this);
  285. // set the received from information into the received= parameter in the
  286. // via
  287. // It is presumed that UDP Datagrams are arriving atomically and that
  288. // each one is a unique SIP message
  289. // Save all the info where this message came from
  290. tuple.transport = this;
  291. tuple.mFlowKey=mTuple.mFlowKey;
  292. message->setSource(tuple);
  293. //DebugLog (<< "Received from: " << tuple);
  294. // Tell the SipMessage about this datagram buffer.
  295. message->addBuffer(buffer);
  296. mMsgHeaderScanner.prepareForMessage(message);
  297. char *unprocessedCharPtr;
  298. if (mMsgHeaderScanner.scanChunk(buffer,
  299. len,
  300. &unprocessedCharPtr) !=
  301. MsgHeaderScanner::scrEnd)
  302. {
  303. StackLog(<<"Scanner rejecting datagram as unparsable / fragmented from " << tuple);
  304. StackLog(<< Data(Data::Borrow, buffer, len));
  305. if(mExternalUnknownDatagramHandler)
  306. {
  307. auto_ptr<Data> datagram(new Data(buffer,len));
  308. (*mExternalUnknownDatagramHandler)(this,tuple,datagram);
  309. }
  310. delete message;
  311. message=0;
  312. return;
  313. }
  314. // no pp error
  315. int used = unprocessedCharPtr - buffer;
  316. if (used < len)
  317. {
  318. // body is present .. add it up.
  319. // NB. The Sip Message uses an overlay (again)
  320. // for the body. It ALSO expects that the body
  321. // will be contiguous (of course).
  322. // it doesn't need a new buffer in UDP b/c there
  323. // will only be one datagram per buffer. (1:1 strict)
  324. message->setBody(buffer+used,len-used);
  325. //DebugLog(<<"added " << len-used << " byte body");
  326. }
  327. if (!basicCheck(*message))
  328. {
  329. delete message; // cannot use it, so, punt on it...
  330. // basicCheck queued any response required
  331. message = 0;
  332. return;
  333. }
  334. stampReceived(message);
  335. #ifdef USE_SIGCOMP
  336. if (mCompression.isEnabled() && sc)
  337. {
  338. const Via &via = message->header(h_Vias).front();
  339. if (message->isRequest())
  340. {
  341. // For requests, the compartment ID is read out of the
  342. // top via header field; if not present, we use the
  343. // TCP connection for identification purposes.
  344. if (via.exists(p_sigcompId))
  345. {
  346. Data compId = via.param(p_sigcompId);
  347. if(!compId.empty())
  348. {
  349. // .bwc. Crash was happening here. Why was there an empty sigcomp
  350. // id?
  351. mSigcompStack->provideCompartmentId(
  352. sc, compId.data(), compId.size());
  353. }
  354. }
  355. else
  356. {
  357. mSigcompStack->provideCompartmentId(sc, this, sizeof(this));
  358. }
  359. }
  360. else
  361. {
  362. // For responses, the compartment ID is supposed to be
  363. // the same as the compartment ID of the request. We
  364. // *could* dig down into the transaction layer to try to
  365. // figure this out, but that's a royal pain, and a rather
  366. // severe layer violation. In practice, we're going to ferret
  367. // the ID out of the the Via header field, which is where we
  368. // squirreled it away when we sent this request in the first place.
  369. // !bwc! This probably shouldn't be going out over the wire.
  370. Data compId = via.param(p_branch).getSigcompCompartment();
  371. if(!compId.empty())
  372. {
  373. mSigcompStack->provideCompartmentId(sc, compId.data(), compId.size());
  374. }
  375. }
  376. }
  377. #endif
  378. mStateMachineFifo.add(message);
  379. }
  380. }
  381. void
  382. UdpTransport::buildFdSet( FdSet& fdset )
  383. {
  384. fdset.setRead(mFd);
  385. if (mTxFifo.messageAvailable())
  386. {
  387. fdset.setWrite(mFd);
  388. }
  389. }
  390. bool
  391. UdpTransport::stunSendTest(const Tuple& dest)
  392. {
  393. bool changePort=false;
  394. bool changeIP=false;
  395. StunAtrString username;
  396. StunAtrString password;
  397. username.sizeValue = 0;
  398. password.sizeValue = 0;
  399. StunMessage req;
  400. memset(&req, 0, sizeof(StunMessage));
  401. stunBuildReqSimple(&req, username, changePort , changeIP , 1);
  402. char* buf = new char[STUN_MAX_MESSAGE_SIZE];
  403. int len = STUN_MAX_MESSAGE_SIZE;
  404. int rlen = stunEncodeMessage(req, buf, len, password, false);
  405. SendData* stunRequest = new SendData(dest, buf, rlen);
  406. mTxFifo.add(stunRequest);
  407. mStunSuccess = false;
  408. return true;
  409. }
  410. bool
  411. UdpTransport::stunResult(Tuple& mappedAddress)
  412. {
  413. resip::Lock lock(myMutex);
  414. if (mStunSuccess)
  415. {
  416. mappedAddress = mStunMappedAddress;
  417. }
  418. return mStunSuccess;
  419. }
  420. void
  421. UdpTransport::setExternalUnknownDatagramHandler(ExternalUnknownDatagramHandler *handler)
  422. {
  423. mExternalUnknownDatagramHandler = handler;
  424. }
  425. /* ====================================================================
  426. * The Vovida Software License, Version 1.0
  427. *
  428. * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
  429. *
  430. * Redistribution and use in source and binary forms, with or without
  431. * modification, are permitted provided that the following conditions
  432. * are met:
  433. *
  434. * 1. Redistributions of source code must retain the above copyright
  435. * notice, this list of conditions and the following disclaimer.
  436. *
  437. * 2. Redistributions in binary form must reproduce the above copyright
  438. * notice, this list of conditions and the following disclaimer in
  439. * the documentation and/or other materials provided with the
  440. * distribution.
  441. *
  442. * 3. The names "VOCAL", "Vovida Open Communication Application Library",
  443. * and "Vovida Open Communication Application Library (VOCAL)" must
  444. * not be used to endorse or promote products derived from this
  445. * software without prior written permission. For written
  446. * permission, please contact vocal@vovida.org.
  447. *
  448. * 4. Products derived from this software may not be called "VOCAL", nor
  449. * may "VOCAL" appear in their name, without prior written
  450. * permission of Vovida Networks, Inc.
  451. *
  452. * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
  453. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  454. * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
  455. * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
  456. * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
  457. * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
  458. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  459. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  460. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  461. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  462. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  463. * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  464. * DAMAGE.
  465. *
  466. * ====================================================================
  467. *
  468. * This software consists of voluntary contributions made by Vovida
  469. * Networks, Inc. and many individuals on behalf of Vovida Networks,
  470. * Inc. For more information on Vovida Networks, Inc., please see
  471. * <http://www.vovida.org/>.
  472. *
  473. */