SocketOptions.cxx
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:11k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /* ====================================================================
  2.  * The Vovida Software License, Version 1.0 
  3.  * 
  4.  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in
  15.  *    the documentation and/or other materials provided with the
  16.  *    distribution.
  17.  * 
  18.  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
  19.  *    and "Vovida Open Communication Application Library (VOCAL)" must
  20.  *    not be used to endorse or promote products derived from this
  21.  *    software without prior written permission. For written
  22.  *    permission, please contact vocal@vovida.org.
  23.  *
  24.  * 4. Products derived from this software may not be called "VOCAL", nor
  25.  *    may "VOCAL" appear in their name, without prior written
  26.  *    permission of Vovida Networks, Inc.
  27.  * 
  28.  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
  29.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
  31.  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
  32.  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
  33.  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
  34.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  35.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  36.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  37.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  38.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  39.  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  40.  * DAMAGE.
  41.  * 
  42.  * ====================================================================
  43.  * 
  44.  * This software consists of voluntary contributions made by Vovida
  45.  * Networks, Inc. and many individuals on behalf of Vovida Networks,
  46.  * Inc.  For more information on Vovida Networks, Inc., please see
  47.  * <http://www.vovida.org/>.
  48.  *
  49.  */
  50. static const char* const SocketOptions_cxx_Version = 
  51.     "$Id: SocketOptions.cxx,v 1.9 2000/12/18 23:49:32 bko Exp $";
  52. #include "SocketOptions.hxx"
  53. #include "Socket.hxx"
  54. #include "TransportCommon.hxx"
  55. #include "SystemException.hxx"
  56. #include "IPAddress.hxx"
  57. #include "VLog.hxx"
  58. #include <cerrno>
  59. using Vocal::Transport::SocketOptions;
  60. using Vocal::Transport::Socket;
  61. using Vocal::Transport::IPAddress;
  62. using Vocal::Logging::VLog;
  63. using namespace Vocal;
  64. SocketOptions::SocketOptions(Socket & sock)
  65.     : socket_(sock)
  66. {
  67. }
  68. SocketOptions::~SocketOptions()
  69. {
  70. }
  71. void     
  72. SocketOptions::keepAlive(bool on)
  73. throw ( Vocal::SystemException )
  74. {
  75.     set(SOL_SOCKET, SO_KEEPALIVE, on);
  76. }
  77. bool     
  78. SocketOptions::keepAlive() const
  79. throw ( Vocal::SystemException )
  80. {
  81.     return ( get(SOL_SOCKET, SO_KEEPALIVE) );
  82. }
  83. void     
  84. SocketOptions::bsdCompatible(bool on)
  85. throw ( Vocal::SystemException )
  86. {
  87.     #if defined(__linux__)
  88.     set(SOL_SOCKET, SO_BSDCOMPAT, on);
  89.     #endif // defined(__linux__)
  90. }
  91. bool     
  92. SocketOptions::bsdCompatible() const
  93. throw ( Vocal::SystemException )
  94. {
  95.     #if defined(__linux__)
  96.     return ( get(SOL_SOCKET, SO_BSDCOMPAT) );
  97.     #else
  98.     return ( false );
  99.     #endif // defined(__linux__)
  100. }
  101. void     
  102. SocketOptions::reuseAddress(bool on)
  103. throw ( Vocal::SystemException )
  104. {
  105.     set(SOL_SOCKET, SO_REUSEADDR, on);
  106. }
  107. bool     
  108. SocketOptions::reuseAddress() const     
  109. throw ( Vocal::SystemException )
  110. {
  111.     return ( get(SOL_SOCKET, SO_REUSEADDR) );
  112. }
  113. void     
  114. SocketOptions::broadcast(bool on)
  115. throw ( Vocal::SystemException )
  116. {
  117.     set(SOL_SOCKET, SO_BROADCAST, on);
  118. }
  119. bool     
  120. SocketOptions::broadcast() const
  121. throw ( Vocal::SystemException )
  122. {
  123.     return ( get(SOL_SOCKET, SO_BROADCAST) );
  124. }
  125.     
  126. void     
  127. SocketOptions::linger(bool on, int seconds)
  128. throw ( Vocal::SystemException )
  129. {
  130.     const string    fn("SocketOptions::linger");
  131.     VLog         log(fn);
  132.     ::linger  lin;
  133.     lin.l_onoff = on;
  134.     lin.l_linger = seconds;
  135.     
  136.     socklen_t optionLength = sizeof(lin);    
  137.     if  ( setsockopt(socket_.getFD(), SOL_SOCKET, SO_LINGER, 
  138.               #if defined(__sun)
  139.     (char *)
  140.     #endif // defined(__sun)
  141.               &lin, 
  142.     optionLength)
  143.          < SUCCESS 
  144. )
  145.     {
  146.      int error = errno;
  147.      throw Vocal::SystemException(fn + " on setsockopt(): " + strerror(error),
  148.               __FILE__, __LINE__, error);
  149.     }
  150.     VDEBUG(log) << fn << ": option = SO_LINGER, value = " << (on ? "on" : "off") 
  151.           << ", seconds = " << (on ? seconds : 0)
  152. << VDEBUG_END(log);
  153. }
  154. bool     
  155. SocketOptions::linger(int & seconds) const
  156. throw ( Vocal::SystemException )
  157. {
  158.     const string    fn("SocketOptions::linger");
  159.     VLog         log(fn);
  160.     ::linger  lin;
  161.     socklen_t optionLength = sizeof(lin);    
  162.     if  ( getsockopt(socket_.getFD(), SOL_SOCKET, SO_LINGER, 
  163.               #if defined(__sun)
  164.     (char *)
  165.     #endif // defined(__sun)
  166.               &lin, 
  167.     &optionLength) 
  168.          < SUCCESS 
  169. )
  170.     {
  171.      int error = errno;
  172.      throw Vocal::SystemException(fn + " on setsockopt(): " + strerror(error),
  173.               __FILE__, __LINE__, error);
  174.     }
  175.     bool on = lin.l_onoff;
  176.     seconds = lin.l_linger;
  177.     
  178.     VDEBUG(log) << fn << ": option = SO_LINGER, value = " << (on ? "on" : "off") 
  179.           << ", seconds = " << (on ? seconds : 0)
  180. << VDEBUG_END(log);
  181.     return ( on );
  182. }
  183. void     
  184. SocketOptions::joinMulticastGroup(IPAddress & mcastAddr)
  185. throw ( Vocal::SystemException )
  186. {
  187.     const string    fn("SocketOptions::joinMulticastGroup");
  188.     VLog         log(fn);
  189.     if ( socket_.getAddressFamily() != AddressFamily(AF_INET) )
  190.     {
  191.      return;
  192.     }
  193.     #if defined(__linux__)
  194.     ip_mreqn mcReq;
  195.     
  196.     mcReq.imr_multiaddr = mcastAddr.getIPAddress().sin_addr;
  197.     mcReq.imr_address = ((sockaddr_in *)(socket_.getLocalAddress().getAddress()))->sin_addr;
  198.     mcReq.imr_ifindex = 0;
  199.     #else
  200.     ip_mreq   mcReq;
  201.     mcReq.imr_multiaddr = mcastAddr.getIPAddress().sin_addr;
  202.     mcReq.imr_interface = ((sockaddr_in *)(socket_.getLocalAddress().getAddress()))->sin_addr;
  203.     #endif // defined(__linux__)
  204.     socklen_t optionLength = sizeof(mcReq); 
  205.         
  206.     if  ( setsockopt(socket_.getFD(), 
  207.               IPPROTO_IP,
  208.     IP_ADD_MEMBERSHIP, 
  209.               #if defined(__sun)
  210.     (char *)
  211.     #endif // defined(__sun)
  212.               &mcReq, 
  213.     optionLength) < SUCCESS 
  214. )
  215.     {
  216.      int error = errno;
  217.      throw Vocal::SystemException(fn + " on setsockopt(): " + strerror(error),
  218.               __FILE__, __LINE__, error);
  219.     }
  220.     VDEBUG(log) << fn << ": option = IP_ADD_MEMBERSHIP"
  221.           << ", local addr = " << socket_.getLocalAddress()
  222.           << ", mapped to multicast group = " << mcastAddr
  223. << VDEBUG_END(log);
  224. }
  225. void     
  226. SocketOptions::leaveMulticastGroup(IPAddress & mcastAddr)
  227. throw ( Vocal::SystemException )
  228. {
  229.     const string    fn("SocketOptions::leaveMulticastGroup");
  230.     VLog         log(fn);
  231.     if ( socket_.getAddressFamily() != AddressFamily(AF_INET) )
  232.     {
  233.      return;
  234.     }
  235.     #if defined(__linux__)
  236.     ip_mreqn mcReq;
  237.     
  238.     mcReq.imr_multiaddr = mcastAddr.getIPAddress().sin_addr;
  239.     mcReq.imr_address = ((sockaddr_in *)(socket_.getLocalAddress().getAddress()))->sin_addr;
  240.     mcReq.imr_ifindex = 0;
  241.     #else
  242.     ip_mreq   mcReq;
  243.     mcReq.imr_multiaddr = mcastAddr.getIPAddress().sin_addr;
  244.     mcReq.imr_interface = ((sockaddr_in *)(socket_.getLocalAddress().getAddress()))->sin_addr;
  245.     #endif // defined(__linux__)
  246.     socklen_t optionLength = sizeof(mcReq); 
  247.         
  248.     if  ( setsockopt(socket_.getFD(), 
  249.               IPPROTO_IP,
  250.     IP_DROP_MEMBERSHIP, 
  251.               #if defined(__sun)
  252.     (char *)
  253.     #endif // defined(__sun)
  254.               &mcReq, 
  255.     optionLength) < SUCCESS 
  256. )
  257.     {
  258.      int error = errno;
  259.      throw Vocal::SystemException(fn + " on setsockopt(): " + strerror(error),
  260.               __FILE__, __LINE__, error);
  261.     }
  262.     VDEBUG(log) << fn << ": option = IP_DROP_MEMBERSHIP"
  263.           << ", local addr = " << socket_.getLocalAddress()
  264.           << ", leaving multicast group = " << mcastAddr
  265. << VDEBUG_END(log);
  266. }
  267. void     
  268. SocketOptions::set(int level, int optname, bool opt)
  269. throw ( Vocal::SystemException )
  270. {
  271.     const string    fn("SocketOptions::set");
  272.     VLog         log(fn);
  273.     
  274.     int          option = opt;
  275.     socklen_t     optionLength = sizeof(option);
  276.     
  277.     if  ( setsockopt(socket_.getFD(), 
  278.                level, 
  279.      optname, 
  280.      #if defined(__sun)
  281.      (char *)
  282.      #endif // defined(__sun)
  283.      &option, 
  284.      optionLength) 
  285.          < SUCCESS 
  286. )
  287.     {
  288.      int error = errno;
  289.      throw Vocal::SystemException(fn + " on setsockopt(): " + strerror(error),
  290.               __FILE__, __LINE__, error);
  291.     }
  292.     VDEBUG(log) << fn << ": option = ";
  293.     
  294.     if ( level == SOL_SOCKET )
  295.     {
  296.         switch ( optname )
  297.         {
  298.          case SO_KEEPALIVE:
  299.     {
  300.      VDEBUG_CONT(log) << "SO_KEEPALIVE";
  301.      break;
  302.          }
  303.     #if defined(__linux__)
  304.     case SO_BSDCOMPAT:
  305.     {
  306.      VDEBUG_CONT(log) << "SO_BSDCOMPAT";
  307.      break;
  308.          }
  309.     #endif // defined(__linux__)
  310.     case SO_REUSEADDR:
  311.     {
  312.      VDEBUG_CONT(log) << "SO_REUSEADDR";
  313.      break;
  314.          }
  315.     case SO_BROADCAST:
  316.     {
  317.      VDEBUG_CONT(log) << "SO_BROADCAST";
  318.      break;
  319.          }
  320.     default:
  321.     {
  322.      VDEBUG_CONT(log) << "Unknown option";
  323. break;
  324.          }
  325. }
  326.     }
  327.     else
  328.     {
  329.      VDEBUG_CONT(log) << "Unknown option";
  330.     }
  331.         
  332.     VDEBUG_CONT(log) << ", value = " << (opt ? "true" : "false")
  333.      << VDEBUG_END(log);
  334. }
  335. bool
  336. SocketOptions::get(int level, int optname) const
  337. throw( Vocal::SystemException )
  338. {
  339.     const string    fn("SocketOptions::get");
  340.     VLog         log(fn);
  341.     int          option = 0;
  342.     socklen_t     optionLength = sizeof(option);
  343.     
  344.     if  ( getsockopt(socket_.getFD(), 
  345.                level, 
  346.      optname, 
  347.      #if defined(__sun)
  348.      (char *)
  349.      #endif // defined(__sun)
  350.      &option, 
  351.      &optionLength) 
  352.          < SUCCESS 
  353. )
  354.     {
  355.      int error = errno;
  356.      throw Vocal::SystemException(fn + " on setsockopt(): " + strerror(error),
  357.               __FILE__, __LINE__, error);
  358.     }
  359.     VDEBUG(log) << fn << ": option = ";
  360.     
  361.     if ( level == SOL_SOCKET )
  362.     {
  363.         switch ( optname )
  364.         {
  365.          case SO_KEEPALIVE:
  366.     {
  367.      VDEBUG_CONT(log) << "SO_KEEPALIVE";
  368.      break;
  369.          }
  370.     #if defined(__linux__)
  371.     case SO_BSDCOMPAT:
  372.     {
  373.      VDEBUG_CONT(log) << "SO_BSDCOMPAT";
  374.      break;
  375.          }
  376.     #endif // defined(__linux__)
  377.     case SO_REUSEADDR:
  378.     {
  379.      VDEBUG_CONT(log) << "SO_REUSEADDR";
  380.      break;
  381.          }
  382.     case SO_BROADCAST:
  383.     {
  384.      VDEBUG_CONT(log) << "SO_BROADCAST";
  385.      break;
  386.          }
  387.     default:
  388.     {
  389.      VDEBUG_CONT(log) << "Unknown option";
  390. break;
  391.          }
  392. }
  393.     }
  394.     else
  395.     {
  396.      VDEBUG_CONT(log) << "Unknown option";
  397.     }
  398.         
  399.     VDEBUG_CONT(log) << ", value = " << (option ? "true" : "false")
  400.      << VDEBUG_END(log);
  401.     return ( option ? true : false );
  402. }