1 #include "SOCK_Dgram_Mcast_QoS.h"
2 #include "ace/Log_Category.h"
3 #include "ace/OS_NS_sys_socket.h"
5 #if defined (ACE_WIN32)
6 #include "ace/Sock_Connect.h" // needed for subscribe_ifs()
9 #if !defined (__ACE_INLINE__)
10 #include "SOCK_Dgram_Mcast_QoS.inl"
11 #endif /* __ACE_INLINE__ */
13 // This is a workaround for platforms with non-standard
14 // definitions of the ip_mreq structure
15 #if ! defined (IMR_MULTIADDR)
16 #define IMR_MULTIADDR imr_multiaddr
17 #endif /* ! defined (IMR_MULTIADDR) */
19 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
21 ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Dgram_Mcast_QoS
)
23 // Dummy default constructor...
25 ACE_SOCK_Dgram_Mcast_QoS::ACE_SOCK_Dgram_Mcast_QoS (options opts
)
26 : ACE_SOCK_Dgram_Mcast (opts
)
28 ACE_TRACE ("ACE_SOCK_Dgram_Mcast_QoS::ACE_SOCK_Dgram_Mcast_QoS");
32 ACE_SOCK_Dgram_Mcast_QoS::open (const ACE_INET_Addr
&addr
,
33 const ACE_QoS_Params
&qos_params
,
36 ACE_Protocol_Info
*protocolinfo
,
41 ACE_TRACE ("ACE_SOCK_Dgram_Mcast_QoS::open");
43 ACE_UNUSED_ARG (qos_params
);
45 // Only perform the <open> initialization if we haven't been opened
47 if (this->get_handle () != ACE_INVALID_HANDLE
)
50 ACELIB_DEBUG ((LM_DEBUG
,
51 "Get Handle Returns Invalid Handle\n"));
53 if (ACE_SOCK::open (SOCK_DGRAM
,
62 return this->open_i (addr
, 0, reuse_addr
);
67 ACE_SOCK_Dgram_Mcast_QoS::subscribe_ifs (const ACE_INET_Addr
&mcast_addr
,
68 const ACE_QoS_Params
&qos_params
,
69 const ACE_TCHAR
*net_if
,
73 ACE_Protocol_Info
*protocolinfo
)
75 ACE_TRACE ("ACE_SOCK_Dgram_Mcast_QoS::subscribe_ifs");
76 #if defined (ACE_WIN32)
77 // Windows NT's winsock has trouble with multicast subscribes in the
78 // presence of multiple network interfaces when the IP address is
79 // given as INADDR_ANY. It will pick the first interface and only
80 // accept mcast there. So, to work around this, cycle through all
81 // of the interfaces known and subscribe to all the non-loopback
84 // Note that this only needs to be done on NT, but there's no way to
85 // tell at this point if the code will be running on NT - only if it
86 // is compiled for NT-only or for NT/95, and that doesn't really
87 // help us. It doesn't hurt to do this on Win95, it's just a little
88 // slower than it normally would be.
90 // NOTE - <ACE_Sock_Connect::get_ip_interfaces> doesn't always get all
91 // of the interfaces. In particular, it may not get a PPP interface. This
92 // is a limitation of the way <ACE_Sock_Connect::get_ip_interfaces> works
93 // with MSVC. The reliable way of getting the interface list is
94 // available only with MSVC 5.
98 ACE_INET_Addr
*if_addrs
= 0;
101 if (ACE::get_ip_interfaces (if_cnt
, if_addrs
) != 0)
104 size_t nr_subscribed
= 0;
108 if (this->subscribe (mcast_addr
,
111 ACE_TEXT ("0.0.0.0"),
118 // Iterate through all the interfaces, figure out which ones
119 // offer multicast service, and subscribe to them.
124 // Convert to 0-based for indexing, next loop check.
125 if (if_addrs
[if_cnt
].is_loopback())
127 if (this->subscribe (mcast_addr
,
130 ACE_TEXT_CHAR_TO_TCHAR
131 (if_addrs
[if_cnt
].get_host_addr()),
140 if (nr_subscribed
== 0)
146 // 1 indicates a "short-circuit" return. This handles the
147 // rather bizarre semantics of checking all the interfaces on
152 ACE_UNUSED_ARG (mcast_addr
);
153 ACE_UNUSED_ARG (qos_params
);
154 ACE_UNUSED_ARG (protocol_family
);
155 ACE_UNUSED_ARG (protocol
);
156 ACE_UNUSED_ARG (reuse_addr
);
157 ACE_UNUSED_ARG (protocolinfo
);
158 #endif /* ACE_WIN32 */
159 // Otherwise, do it like everyone else...
161 // Create multicast request.
162 if (this->make_multicast_ifaddr (0,
171 ACE_SOCK_Dgram_Mcast_QoS::subscribe (const ACE_INET_Addr
&mcast_addr
,
172 const ACE_QoS_Params
&qos_params
,
174 const ACE_TCHAR
*net_if
,
177 ACE_Protocol_Info
*protocolinfo
,
180 ACE_QoS_Session
*qos_session
)
182 ACE_TRACE ("ACE_SOCK_Dgram_Mcast_QoS::subscribe");
184 if (this->open (mcast_addr
,
194 // The following method call only applies to Win32 currently.
195 int result
= this->subscribe_ifs (mcast_addr
,
202 // Check for the "short-circuit" return value of 1 (for NT).
206 // Tell network device driver to read datagrams with a
207 // <mcast_request_if_> IP interface.
210 // Check if the mcast_addr passed into this method is the
211 // same as the QoS session address.
212 if (qos_session
!= 0 && mcast_addr
== qos_session
->dest_addr ())
214 // Subscribe to the QoS session.
215 if (this->qos_manager_
.join_qos_session (qos_session
) == -1)
216 ACELIB_ERROR_RETURN ((LM_ERROR
,
217 ACE_TEXT ("Unable to join QoS Session\n")),
222 if (this->close () != 0)
223 ACELIB_ERROR ((LM_ERROR
,
224 ACE_TEXT ("Unable to close socket\n")));
225 ACELIB_ERROR_RETURN ((LM_ERROR
,
226 ACE_TEXT ("Dest Addr in the QoS Session does")
227 ACE_TEXT (" not match the address passed into")
228 ACE_TEXT (" subscribe\n")),
233 this->make_multicast_ifaddr (&ret_mreq
, mcast_addr
, net_if
);
235 // XX This is windows stuff only. fredk
236 if (ACE_OS::join_leaf (this->get_handle (),
237 reinterpret_cast<const sockaddr
*> (&ret_mreq
.IMR_MULTIADDR
.s_addr
),
238 sizeof ret_mreq
.IMR_MULTIADDR
.s_addr
,
239 qos_params
) == ACE_INVALID_HANDLE
244 if (qos_params
.socket_qos () != 0 && qos_session
!= 0)
245 qos_session
->qos (*(qos_params
.socket_qos ()));
251 ACE_END_VERSIONED_NAMESPACE_DECL