1 // $Id: SOCK_Dgram_Bcast.cpp 80826 2008-03-04 14:51:23Z wotte $
3 #include "ace/SOCK_Dgram_Bcast.h"
5 #include "ace/Log_Msg.h"
7 #include "ace/OS_NS_string.h"
8 #include "ace/os_include/net/os_if.h"
9 #include "ace/OS_NS_netdb.h"
10 #include "ace/OS_Memory.h"
12 #if !defined (__ACE_INLINE__)
13 #include "ace/SOCK_Dgram_Bcast.inl"
14 #endif /* __ACE_INLINE__ */
16 ACE_RCSID(ace
, SOCK_Dgram_Bcast
, "$Id: SOCK_Dgram_Bcast.cpp 80826 2008-03-04 14:51:23Z wotte $")
18 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
20 ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Dgram_Bcast
)
22 ACE_Bcast_Node::ACE_Bcast_Node (ACE_INET_Addr
&addr
,
27 ACE_TRACE ("ACE_Bcast_Node::ACE_Bcast_Node");
31 ACE_SOCK_Dgram_Bcast::dump (void) const
33 #if defined (ACE_HAS_DUMP)
34 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::dump");
35 #endif /* ACE_HAS_DUMP */
38 // Close up and release resources.
41 ACE_SOCK_Dgram_Bcast::close (void)
43 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::close");
45 ACE_Bcast_Node
*temp
= this->if_list_
;
48 // Release the dynamically allocated memory.
52 ACE_Bcast_Node
*hold
= temp
->next_
;
57 // Shut down the descriptor.
58 return ACE_SOCK::close ();
61 // Here's the simple-minded constructor.
63 ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast (void)
66 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast");
69 // Here's the general-purpose constructor used by a connectionless
70 // datagram ``server''...
72 ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast (const ACE_Addr
&local
,
76 const ACE_TCHAR
*host_name
)
77 : ACE_SOCK_Dgram (local
, protocol_family
, protocol
, reuse_addr
),
80 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::ACE_SOCK_Dgram_Bcast");
82 if (this->mk_broadcast (host_name
) == -1)
85 ACE_TEXT ("ACE_SOCK_Dgram_Bcast")));
88 // Here's the general-purpose open routine.
91 ACE_SOCK_Dgram_Bcast::open (const ACE_Addr
&local
,
95 const ACE_TCHAR
*host_name
)
97 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::open");
99 if (this->ACE_SOCK_Dgram::open (local
, protocol_family
,
100 protocol
, reuse_addr
) == -1)
103 return this->mk_broadcast (host_name
);
106 // Make broadcast available for Datagram socket.
109 ACE_SOCK_Dgram_Bcast::mk_broadcast (const ACE_TCHAR
*host_name
)
111 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::mk_broadcast");
115 if (ACE_OS::setsockopt (this->get_handle (),
120 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n",
121 "ACE_SOCK_Dgram_Bcast::mk_broadcast: setsockopt failed"),
124 #if !defined (ACE_WIN32) && !defined(__INTERIX)
125 ACE_HANDLE s
= this->get_handle ();
130 ifc
.ifc_len
= sizeof buf
;
133 // Get interface structure and initialize the addresses using UNIX
135 if (ACE_OS::ioctl (s
,
137 (char *) &ifc
) == -1)
138 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n",
139 "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get interface configuration)"),
142 struct ifreq
*ifr
= ifc
.ifc_req
;
144 struct sockaddr_in host_addr
;
146 // Get host ip address
149 hostent
*hp
= ACE_OS::gethostbyname (ACE_TEXT_ALWAYS_CHAR (host_name
));
156 ACE_UINT64 haddr
; // a place to put the address
157 char * haddrp
= (char *) &haddr
; // convert to char pointer
158 ACE_OS::memcpy(haddrp
,(char *) hp
->h_addr
,hp
->h_length
);
159 host_addr
.sin_addr
.s_addr
= haddr
;
161 #else /* ! _UNICOS */
162 ACE_OS::memcpy ((char *) &host_addr
.sin_addr
.s_addr
,
165 #endif /* ! _UNICOS */
169 #if !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_VXWORKS) && !defined(__APPLE__)
170 for (int n
= ifc
.ifc_len
/ sizeof (struct ifreq
) ; n
> 0;
174 There are addresses longer than sizeof (struct sockaddr) eg. IPv6
175 or QNX::links. In this case address does not fit into struct ifreq.
176 The code below could be applied everywhere, but not every system
177 provides sockaddr.sa_len field.
179 for (int nbytes
= ifc
.ifc_len
; nbytes
>= (int) sizeof (struct ifreq
) &&
180 ((ifr
->ifr_addr
.sa_len
> sizeof (struct sockaddr
)) ?
181 (nbytes
>= (int) sizeof (ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
) : 1);
182 ((ifr
->ifr_addr
.sa_len
> sizeof (struct sockaddr
)) ?
183 (nbytes
-= sizeof (ifr
->ifr_name
) + ifr
->ifr_addr
.sa_len
,
184 ifr
= (struct ifreq
*)
185 ((caddr_t
) &ifr
->ifr_addr
+ ifr
->ifr_addr
.sa_len
)) :
186 (nbytes
-= sizeof (struct ifreq
), ifr
++)))
187 #endif /* !defined(AIX) && !defined (__QNX__) && !defined (__FreeBSD__) && !defined(__NetBSD__) && !defined (ACE_VXWORKS) && !defined(__APPLE__) */
189 #if defined (__QNX__) || defined (ACE_VXWORKS)
190 // Silently skip link interfaces
191 if (ifr
->ifr_addr
.sa_family
== AF_LINK
)
194 // Compare host ip address with interface ip address.
197 struct sockaddr_in if_addr
;
199 ACE_OS::memcpy (&if_addr
,
203 if (host_addr
.sin_addr
.s_addr
!= if_addr
.sin_addr
.s_addr
)
207 if (ifr
->ifr_addr
.sa_family
!= AF_INET
)
209 // Note that some systems seem to generate 0 (AF_UNDEF) for
210 // the sa_family, even when there are no errors! Thus, we
211 // only print an error if this is not the case, or if we're
212 // in "debugging" mode.
213 if (ifr
->ifr_addr
.sa_family
!= 0
215 ACE_DEBUG ((LM_DEBUG
,
216 "warning %p: sa_family: %d\n",
217 "ACE_SOCK_Dgram_Bcast::mk_broadcast: Not AF_INET",
218 ifr
->ifr_addr
.sa_family
));
222 struct ifreq flags
= *ifr
;
223 struct ifreq if_req
= *ifr
;
225 if (ACE_OS::ioctl (s
,
227 (char *) &flags
) == -1)
229 ACE_ERROR ((LM_ERROR
, "%p [%s]\n",
230 "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get interface flags)",
235 if (ACE_BIT_ENABLED (flags
.ifr_flags
,
238 ACE_ERROR ((LM_ERROR
, "%p [%s]\n",
239 "ACE_SOCK_Dgram_Bcast::mk_broadcast: Network interface is not up",
244 if (ACE_BIT_ENABLED (flags
.ifr_flags
,
248 if (ACE_BIT_ENABLED (flags
.ifr_flags
,
251 if (ACE_OS::ioctl (s
,
253 (char *) &if_req
) == -1)
254 ACE_ERROR ((LM_ERROR
, "%p [%s]\n",
255 "ACE_SOCK_Dgram_Bcast::mk_broadcast: ioctl (get broadaddr)",
259 ACE_INET_Addr
addr (reinterpret_cast <sockaddr_in
*>
260 (&if_req
.ifr_broadaddr
),
261 sizeof if_req
.ifr_broadaddr
);
262 ACE_NEW_RETURN (this->if_list_
,
263 ACE_Bcast_Node (addr
,
271 ACE_ERROR ((LM_ERROR
, "%p [%s]\n",
272 "ACE_SOCK_Dgram_Bcast::mk_broadcast: Broadcast is not enable for this interface.",
277 ACE_UNUSED_ARG (host_name
);
279 ACE_INET_Addr
addr (u_short (0),
280 ACE_UINT32 (INADDR_BROADCAST
));
281 ACE_NEW_RETURN (this->if_list_
,
282 ACE_Bcast_Node (addr
,
285 #endif /* !ACE_WIN32 && !__INTERIX */
286 if (this->if_list_
== 0)
295 // Broadcast the datagram to every interface. Returns the average
296 // number of bytes sent.
299 ACE_SOCK_Dgram_Bcast::send (const void *buf
,
304 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
305 ssize_t iterations
= 0;
306 ssize_t total_bytes
= 0;
308 if (this->if_list_
== 0)
311 for (ACE_Bcast_Node
*temp
= this->if_list_
;
315 temp
->bcast_addr_
.set_port_number (port_number
);
317 ssize_t bytes_sent
= ACE_SOCK_Dgram::send (buf
,
322 if (bytes_sent
== -1)
325 total_bytes
+= bytes_sent
;
330 return iterations
== 0 ? 0 : total_bytes
/ iterations
;
333 #if defined (ACE_HAS_MSG)
334 // Broadcast datagram to every interfaces.
337 ACE_SOCK_Dgram_Bcast::send (const iovec iov
[],
342 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
344 if (this->if_list_
== 0)
347 // Send the message to every interface.
349 for (ACE_Bcast_Node
*temp
= this->if_list_
;
353 temp
->bcast_addr_
.set_port_number (port_number
);
355 if (ACE_SOCK_Dgram::send (iov
,
365 // Broadcast an iovec of size N to ADDR as a datagram (note that addr
366 // must be preassigned to the broadcast address of the subnet...).
369 ACE_SOCK_Dgram_Bcast::send (const iovec iov
[],
371 const ACE_Addr
&addr
,
374 ACE_TRACE ("ACE_SOCK_Dgram_Bcast::send");
376 return ACE_SOCK_Dgram::send (iov
, n
, addr
, flags
);
378 #endif /* ACE_HAS_MSG */
380 ACE_END_VERSIONED_NAMESPACE_DECL