Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

SOCK_Dgram_Bcast.cpp

Go to the documentation of this file.
00001 #include "ace_pch.h"
00002 // $Id: SOCK_Dgram_Bcast.cpp,v 1.1.1.4.2.1 2003/03/13 19:44:22 chad Exp $
00003 
00004 #include "ace/SOCK_Dgram_Bcast.h"
00005 #include "ace/Log_Msg.h"
00006 #include "ace/ACE.h"
00007 
00008 #if defined (ACE_LACKS_INLINE_FUNCTIONS)
00009 #include "ace/SOCK_Dgram_Bcast.i"
00010 #endif
00011 
00012 ACE_RCSID(ace, SOCK_Dgram_Bcast, "$Id: SOCK_Dgram_Bcast.cpp,v 1.1.1.4.2.1 2003/03/13 19:44:22 chad Exp $")
00013 
00014 ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Dgram_Bcast)
00015 
00016 ACE_Bcast_Node::ACE_Bcast_Node (ACE_INET_Addr &addr,
00017                                 ACE_Bcast_Node *next)
00018   : bcast_addr_ (addr),
00019     next_ (next)
00020 {
00021   ACE_TRACE ("ACE_Bcast_Node::ACE_Bcast_Node");
00022 }
00023 
00024 void
00025 ACE_SOCK_Dgram_Bcast::dump (void) const
00026 {
00027   ACE_TRACE ("ACE_SOCK_Dgram_Bcast::dump");
00028 }
00029 
00030 // Close up and release resources.
00031 
00032 int
00033 ACE_SOCK_Dgram_Bcast::close (void)
00034 {
00035   ACE_TRACE ("ACE_SOCK_Dgram_Bcast::close");
00036 
00037   ACE_Bcast_Node *temp = this->if_list_;
00038 
00039   // Release the dynamically allocated memory.
00040 
00041   while (temp != 0)
00042     {
00043       ACE_Bcast_Node *hold = temp->next_;
00044       delete temp;
00045       temp = hold;
00046     }
00047 
00048   // Shut down the descriptor.
00049   return ACE_SOCK::close ();
00050 }
00051 
00052 // Here's the simple-minded constructor.
00053 
00054 ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast (void)
00055   : if_list_ (0)
00056 {
00057   ACE_TRACE ("ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast");
00058 }
00059 
00060 // Here's the general-purpose constructor used by a connectionless
00061 // datagram ``server''...
00062 
00063 ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast (const ACE_Addr &local,
00064                                             int protocol_family,
00065                                             int protocol,
00066                                             int reuse_addr,
00067                                             const ACE_TCHAR *host_name)
00068   : ACE_SOCK_Dgram (local, protocol_family, protocol, reuse_addr),
00069     if_list_ (0)
00070 {
00071   ACE_TRACE ("ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast");
00072 
00073   if (this->mk_broadcast (host_name) == -1)
00074     ACE_ERROR ((LM_ERROR,
00075                 ACE_LIB_TEXT ("%p\n"),
00076                 ACE_LIB_TEXT ("ACE_SOCK_Dgram_Bcast")));
00077 }
00078 
00079 // Here's the general-purpose open routine.
00080 
00081 int
00082 ACE_SOCK_Dgram_Bcast::open (const ACE_Addr &local,
00083                             int protocol_family,
00084                             int protocol,
00085                             int reuse_addr,
00086                             const ACE_TCHAR *host_name)
00087 {
00088   ACE_TRACE ("ACE_SOCK_Dgram_Bcast::open");
00089 
00090   if (this->ACE_SOCK_Dgram::open (local, protocol_family,
00091                                   protocol, reuse_addr) == -1)
00092     return -1;
00093 
00094   return this->mk_broadcast (host_name);
00095 }
00096 
00097 // Make broadcast available for Datagram socket.
00098 
00099 int
00100 ACE_SOCK_Dgram_Bcast::mk_broadcast (const ACE_TCHAR *host_name)
00101 {
00102   ACE_TRACE ("ACE_SOCK_Dgram_Bcast::mk_broadcast");
00103 
00104   int one = 1;
00105 
00106   if (ACE_OS::setsockopt (this->get_handle (),
00107                           SOL_SOCKET,
00108                           SO_BROADCAST,
00109                           (char *) &one,
00110                           sizeof one) == -1)
00111     return -1;
00112 
00113 #if !defined (ACE_WIN32)
00114   ACE_HANDLE s = this->get_handle ();
00115 
00116   char buf[BUFSIZ];
00117   struct ifconf ifc;
00118 
00119   ifc.ifc_len = sizeof buf;
00120   ifc.ifc_buf = buf;
00121 
00122   // Get interface structure and initialize the addresses using UNIX
00123   // techniques.
00124   if (ACE_OS::ioctl (s,
00125                      SIOCGIFCONF,
00126                      (char *) &ifc) == -1)
00127     ACE_ERROR_RETURN ((LM_ERROR, "%p\n",
00128                       "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get interface configuration)"),
00129                       ACE_INVALID_HANDLE);
00130 
00131   struct ifreq *ifr = ifc.ifc_req;
00132 
00133   struct sockaddr_in host_addr;
00134 
00135   //Get host ip address
00136   if (host_name)
00137     {
00138       hostent *hp = ACE_OS::gethostbyname (host_name);
00139 
00140       if (hp == 0)
00141         return -1;
00142       else
00143 #if defined(_UNICOS)
00144         {
00145           ACE_UINT64 haddr;  // a place to put the address
00146           char * haddrp = (char *) &haddr;  // convert to char pointer
00147           ACE_OS::memcpy(haddrp,(char *) hp->h_addr,hp->h_length);
00148           host_addr.sin_addr.s_addr = haddr;
00149         }
00150 #else /* ! _UNICOS */
00151         ACE_OS::memcpy ((char *) &host_addr.sin_addr.s_addr,
00152                         (char *) hp->h_addr,
00153                         hp->h_length);
00154 #endif /* ! _UNICOS */
00155     }
00156 
00157   for (int n = ifc.ifc_len / sizeof (struct ifreq) ; n > 0;
00158 #if !defined(CHORUS_4) && !defined(AIX)
00159        n--, ifr++)
00160 #else
00161        n--,
00162            ((ifr->ifr_addr.sa_len <= sizeof (struct sockaddr)) ?
00163              ifr++ :
00164              ifr = (struct ifreq *)
00165              (ifr->ifr_addr.sa_len + (caddr_t) &ifr->ifr_addr)))
00166 #endif /* CHORUS_4 */
00167     {
00168       // Compare host ip address with interface ip address.
00169       if (host_name)
00170         {
00171           struct sockaddr_in if_addr;
00172 
00173           ACE_OS::memcpy (&if_addr,
00174                           &ifr->ifr_addr,
00175                           sizeof if_addr);
00176 
00177           if (host_addr.sin_addr.s_addr != if_addr.sin_addr.s_addr)
00178             continue;
00179         }
00180 
00181       if (ifr->ifr_addr.sa_family != AF_INET)
00182         {
00183           // Note that some systems seem to generate 0 (AF_UNDEF) for
00184           // the sa_family, even when there are no errors!  Thus, we
00185           // only print an error if this is not the case, or if we're
00186           // in "debugging" mode.
00187           if (ifr->ifr_addr.sa_family != 0
00188               || ACE::debug () > 0)
00189           ACE_DEBUG ((LM_DEBUG,
00190                       "warning %p: sa_family: %d\n",
00191                       "ACE_SOCK_Dgram_Bcast::mk_broadcast: Not AF_INET",
00192                       ifr->ifr_addr.sa_family));
00193           continue;
00194         }
00195 
00196       struct ifreq flags = *ifr;
00197       struct ifreq if_req = *ifr;
00198 
00199       if (ACE_OS::ioctl (s,
00200                          SIOCGIFFLAGS,
00201                          (char *) &flags) == -1)
00202         {
00203           ACE_ERROR ((LM_ERROR, "%p\n",
00204                      "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get interface flags)"));
00205           continue;
00206         }
00207 
00208       if (ACE_BIT_ENABLED (flags.ifr_flags,
00209                            IFF_UP) == 0)
00210         {
00211           ACE_ERROR ((LM_ERROR, "%p\n",
00212                      "ACE_SOCK_Dgram_Bcast::mk_broadcast: Network interface is not up"));
00213           continue;
00214         }
00215 
00216       if (ACE_BIT_ENABLED (flags.ifr_flags,
00217                            IFF_LOOPBACK))
00218         continue;
00219 
00220       if (ACE_BIT_ENABLED (flags.ifr_flags,
00221                            IFF_BROADCAST))
00222         {
00223           if (ACE_OS::ioctl (s,
00224                              SIOCGIFBRDADDR,
00225                              (char *) &if_req) == -1)
00226             ACE_ERROR ((LM_ERROR, "%p\n",
00227                        "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get broadaddr)"));
00228           else
00229             {
00230               ACE_INET_Addr addr (ACE_reinterpret_cast (sockaddr_in *,
00231                                                         &if_req.ifr_broadaddr),
00232                                   sizeof if_req.ifr_broadaddr);
00233               ACE_NEW_RETURN (this->if_list_,
00234                               ACE_Bcast_Node (addr,
00235                                               this->if_list_),
00236                               -1);
00237             }
00238         }
00239       else
00240         ACE_ERROR ((LM_ERROR, "%p\n",
00241                    "ACE_SOCK_Dgram_Bcast::mk_broadcast: Broadcast is not enable for this interface."));
00242     }
00243 #else
00244   ACE_UNUSED_ARG (host_name);
00245 
00246   ACE_INET_Addr addr (u_short (0),
00247                       ACE_UINT32 (INADDR_BROADCAST));
00248   ACE_NEW_RETURN (this->if_list_,
00249                   ACE_Bcast_Node (addr,
00250                                   this->if_list_),
00251                   -1);
00252 #endif /* !ACE_WIN32 */
00253   return this->if_list_ == 0 ? -1 : 0;
00254 }
00255 
00256 // Broadcast the datagram to every interface.  Returns the average
00257 // number of bytes sent.
00258 
00259 ssize_t
00260 ACE_SOCK_Dgram_Bcast::send (const void *buf,
00261                             size_t n,
00262                             u_short port_number,
00263                             int flags) const
00264 {
00265   ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
00266   size_t iterations = 0;
00267   ssize_t total_bytes = 0;
00268 
00269   if (this->if_list_ == 0)
00270     return -1;
00271 
00272   for (ACE_Bcast_Node *temp = this->if_list_;
00273        temp != 0;
00274        temp = temp->next_)
00275     {
00276       temp->bcast_addr_.set_port_number (port_number);
00277 
00278       ssize_t bytes_sent = ACE_SOCK_Dgram::send (buf,
00279                                                  n,
00280                                                  temp->bcast_addr_,
00281                                                  flags);
00282 
00283       if (bytes_sent == -1)
00284         return -1;
00285       else
00286         total_bytes += bytes_sent;
00287 
00288       iterations++;
00289     }
00290 
00291   return iterations == 0 ? 0 : total_bytes / iterations;
00292 }
00293 
00294 #if defined (ACE_HAS_MSG)
00295 // Broadcast datagram to every interfaces.
00296 
00297 ssize_t
00298 ACE_SOCK_Dgram_Bcast::send (const iovec iov[],
00299                             int n,
00300                             u_short /* port_number */,
00301                             int flags) const
00302 {
00303   ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
00304 
00305   if (this->if_list_ == 0)
00306     return -1;
00307 
00308   // Send the message to every interface.
00309 
00310   for (ACE_Bcast_Node *temp = this->if_list_;
00311        temp != 0;
00312        temp = temp->next_)
00313     if (ACE_SOCK_Dgram::send (iov,
00314                               n,
00315                               temp->bcast_addr_,
00316                               flags) == -1)
00317       return -1;
00318 
00319   return 0;
00320 }
00321 
00322 // Broadcast an iovec of size N to ADDR as a datagram (note that addr
00323 // must be preassigned to the broadcast address of the subnet...).
00324 
00325 ssize_t
00326 ACE_SOCK_Dgram_Bcast::send (const iovec iov[],
00327                             int n,
00328                             const ACE_Addr &addr,
00329                             int flags) const
00330 {
00331   ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
00332 
00333   return ACE_SOCK_Dgram::send (iov, n, addr, flags);
00334 }
00335 #endif /* ACE_HAS_MSG */

Generated on Mon Jun 16 11:21:20 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002