Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / QoS / SOCK_Dgram_Mcast_QoS.cpp
blob511386ef638111f8d2578133c6c18b8606e167c8
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()
7 #endif /* ACE_WIN32 */
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");
31 int
32 ACE_SOCK_Dgram_Mcast_QoS::open (const ACE_INET_Addr &addr,
33 const ACE_QoS_Params &qos_params,
34 int protocol_family,
35 int protocol,
36 ACE_Protocol_Info *protocolinfo,
37 ACE_SOCK_GROUP g,
38 u_long flags,
39 int reuse_addr)
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
46 // earlier.
47 if (this->get_handle () != ACE_INVALID_HANDLE)
48 return 0;
50 ACELIB_DEBUG ((LM_DEBUG,
51 "Get Handle Returns Invalid Handle\n"));
53 if (ACE_SOCK::open (SOCK_DGRAM,
54 protocol_family,
55 protocol,
56 protocolinfo,
58 flags,
59 reuse_addr) == -1)
60 return -1;
62 return this->open_i (addr, 0, reuse_addr);
66 int
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,
70 int protocol_family,
71 int protocol,
72 int reuse_addr,
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
82 // ones.
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.
96 if (net_if == 0)
98 ACE_INET_Addr *if_addrs = 0;
99 size_t if_cnt;
101 if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0)
102 return -1;
104 size_t nr_subscribed = 0;
106 if (if_cnt < 2)
108 if (this->subscribe (mcast_addr,
109 qos_params,
110 reuse_addr,
111 ACE_TEXT ("0.0.0.0"),
112 protocol_family,
113 protocol,
114 protocolinfo) == 0)
115 ++nr_subscribed;
117 else
118 // Iterate through all the interfaces, figure out which ones
119 // offer multicast service, and subscribe to them.
120 while (if_cnt > 0)
122 --if_cnt;
124 // Convert to 0-based for indexing, next loop check.
125 if (if_addrs[if_cnt].is_loopback())
126 continue;
127 if (this->subscribe (mcast_addr,
128 qos_params,
129 reuse_addr,
130 ACE_TEXT_CHAR_TO_TCHAR
131 (if_addrs[if_cnt].get_host_addr()),
132 protocol_family,
133 protocol,
134 protocolinfo) == 0)
135 ++nr_subscribed;
138 delete [] if_addrs;
140 if (nr_subscribed == 0)
142 errno = ENODEV;
143 return -1;
145 else
146 // 1 indicates a "short-circuit" return. This handles the
147 // rather bizarre semantics of checking all the interfaces on
148 // NT.
149 return 1;
151 #else
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,
163 mcast_addr,
164 net_if) == -1)
165 return -1;
166 else
167 return 0;
171 ACE_SOCK_Dgram_Mcast_QoS::subscribe (const ACE_INET_Addr &mcast_addr,
172 const ACE_QoS_Params &qos_params,
173 int reuse_addr,
174 const ACE_TCHAR *net_if,
175 int protocol_family,
176 int protocol,
177 ACE_Protocol_Info *protocolinfo,
178 ACE_SOCK_GROUP g,
179 u_long flags,
180 ACE_QoS_Session *qos_session)
182 ACE_TRACE ("ACE_SOCK_Dgram_Mcast_QoS::subscribe");
184 if (this->open (mcast_addr,
185 qos_params,
186 protocol_family,
187 protocol,
188 protocolinfo,
190 flags,
191 reuse_addr) == -1)
192 return -1;
194 // The following method call only applies to Win32 currently.
195 int result = this->subscribe_ifs (mcast_addr,
196 qos_params,
197 net_if,
198 protocol_family,
199 protocol,
200 reuse_addr,
201 protocolinfo);
202 // Check for the "short-circuit" return value of 1 (for NT).
203 if (result != 0)
204 return result;
206 // Tell network device driver to read datagrams with a
207 // <mcast_request_if_> IP interface.
208 else
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")),
218 -1);
220 else
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")),
229 -1);
232 ip_mreq ret_mreq;
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
240 && errno != ENOTSUP)
241 return -1;
243 else
244 if (qos_params.socket_qos () != 0 && qos_session != 0)
245 qos_session->qos (*(qos_params.socket_qos ()));
247 return 0;
251 ACE_END_VERSIONED_NAMESPACE_DECL