Use =default for skeleton copy constructor
[ACE_TAO.git] / TAO / tao / Strategies / SCIOP_Connector.cpp
blob2dcc7944a35136a852b132c4ff59db019261b30d
1 #include "tao/Strategies/SCIOP_Connector.h"
2 #include "tao/Strategies/SCIOP_Profile.h"
4 #if TAO_HAS_SCIOP == 1
6 #include "tao/debug.h"
7 #include "tao/ORB_Core.h"
8 #include "tao/Client_Strategy_Factory.h"
9 #include "tao/SystemException.h"
10 #include "tao/Base_Transport_Property.h"
11 #include "tao/Protocols_Hooks.h"
12 #include "tao/Transport_Cache_Manager.h"
13 #include "tao/Connect_Strategy.h"
14 #include "tao/Thread_Lane_Resources.h"
15 #include "tao/Transport.h"
16 #include "tao/Wait_Strategy.h"
17 #include "tao/Profile_Transport_Resolver.h"
19 #include "ace/OS_NS_strings.h"
20 #include "ace/Strategies_T.h"
21 #include <cstring>
23 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
25 TAO_SCIOP_Connector::TAO_SCIOP_Connector ()
26 : TAO_Connector (TAO_TAG_SCIOP_PROFILE),
27 connect_strategy_ (),
28 base_connector_ (0)
32 TAO_SCIOP_Connector::~TAO_SCIOP_Connector ()
36 int
37 TAO_SCIOP_Connector::open (TAO_ORB_Core *orb_core)
39 // @todo: The functionality of the following two statements could
40 // be done in the constructor, but that involves changing the
41 // interface of the pluggable transport factory.
43 // Set the ORB Core
44 this->orb_core (orb_core);
46 // Create our connect strategy
47 if (this->create_connect_strategy () == -1)
48 return -1;
50 /// Our connect creation strategy
51 TAO_SCIOP_CONNECT_CREATION_STRATEGY *connect_creation_strategy = 0;
53 ACE_NEW_RETURN (connect_creation_strategy,
54 TAO_SCIOP_CONNECT_CREATION_STRATEGY
55 (orb_core->thr_mgr (),
56 orb_core),
57 -1);
59 /// Our activation strategy
60 TAO_SCIOP_CONNECT_CONCURRENCY_STRATEGY *concurrency_strategy = 0;
62 ACE_NEW_RETURN (concurrency_strategy,
63 TAO_SCIOP_CONNECT_CONCURRENCY_STRATEGY (orb_core),
64 -1);
66 return this->base_connector_.open (this->orb_core ()->reactor (),
67 connect_creation_strategy,
68 &this->connect_strategy_,
69 concurrency_strategy);
72 int
73 TAO_SCIOP_Connector::close ()
75 delete this->base_connector_.concurrency_strategy ();
76 delete this->base_connector_.creation_strategy ();
77 return this->base_connector_.close ();
80 int
81 TAO_SCIOP_Connector::set_validate_endpoint (TAO_Endpoint *endpoint)
83 TAO_SCIOP_Endpoint *sciop_endpoint =
84 this->remote_endpoint (endpoint);
86 if (sciop_endpoint == 0)
87 return -1;
89 const ACE_INET_Addr &remote_address =
90 sciop_endpoint->object_addr ();
92 // Verify that the remote ACE_INET_Addr was initialized properly.
93 // Failure can occur if hostname lookup failed when initializing the
94 // remote ACE_INET_Addr.
95 if (remote_address.get_type () != AF_INET)
97 if (TAO_debug_level > 0)
99 TAOLIB_DEBUG ((LM_DEBUG,
100 ACE_TEXT ("TAO (%P|%t) SCIOP connection failed.\n")
101 ACE_TEXT ("TAO (%P|%t) This is most likely ")
102 ACE_TEXT ("due to a hostname lookup ")
103 ACE_TEXT ("failure.\n")));
106 return -1;
109 return 0;
112 TAO_Transport *
113 TAO_SCIOP_Connector::make_connection (TAO::Profile_Transport_Resolver *r,
114 TAO_Transport_Descriptor_Interface &desc,
115 ACE_Time_Value *timeout)
117 TAO_Endpoint *tao_endpoint = desc.endpoint ();
119 TAO_Transport *transport = 0;
121 // @@ ATL folks, is this while loop needed?
122 // TAO_Default_Endpoint_Selector has this code already, i.e., the
123 // loop.
124 while (tao_endpoint != 0)
126 TAO_SCIOP_Endpoint *sciop_endpoint = this->remote_endpoint (tao_endpoint);
128 if (sciop_endpoint != 0)
130 transport =
131 this->make_connection_i (r, desc, timeout, sciop_endpoint);
132 if (transport)
134 break;
137 tao_endpoint = tao_endpoint->next();
140 return transport;
144 TAO_Transport *
145 TAO_SCIOP_Connector::make_connection_i (TAO::Profile_Transport_Resolver *r,
146 TAO_Transport_Descriptor_Interface &desc,
147 ACE_Time_Value *timeout,
148 TAO_SCIOP_Endpoint *sciop_endpoint)
150 const ACE_INET_Addr &remote_address =
151 sciop_endpoint->object_addr ();
153 if (TAO_debug_level > 2)
154 TAOLIB_DEBUG ((LM_DEBUG,
155 ACE_TEXT("TAO (%P|%t) - SCIOP_Connector::make_connection_i, ")
156 ACE_TEXT("to <%C:%d> which should %s\n"),
157 sciop_endpoint->host(),
158 sciop_endpoint->port(),
159 r->blocked_connect () ? ACE_TEXT("block") : ACE_TEXT("nonblock")));
161 // Get the right synch options
162 ACE_Synch_Options synch_options;
164 this->active_connect_strategy_->synch_options (timeout, synch_options);
166 // The code used to set the timeout to zero, with the intent of
167 // polling the reactor for connection completion. However, the side-effect
168 // was to cause the connection to timeout immediately.
170 TAO_SCIOP_Connection_Handler *svc_handler = 0;
172 // Connect.
173 ACE_Multihomed_INET_Addr multihomed;
174 if (multihomed.set(remote_address.get_port_number(),
175 remote_address.get_ip_address()))
176 return 0;
178 ACE_Multihomed_INET_Addr local_address;
180 bool pn =
181 sciop_endpoint->is_preferred_network ();
183 if (pn)
184 local_address.set ((u_short) 0,
185 sciop_endpoint->preferred_network ());
187 int result =
188 this->base_connector_.connect (svc_handler,
189 multihomed,
190 synch_options,
191 local_address);
193 // Make sure that we always do a remove_reference
194 ACE_Event_Handler_var svc_handler_auto_ptr (svc_handler);
196 TAO_Transport *transport = svc_handler->transport ();
198 if (result == -1)
200 // No immediate result, wait for completion
201 if (errno == EWOULDBLOCK)
203 // Try to wait until connection completion. Incase we block, then we
204 // get a connected transport or not. In case of non block we get
205 // a connected or not connected transport
206 if (!this->wait_for_connection_completion (r,
207 desc,
208 transport,
209 timeout))
211 if (TAO_debug_level > 2)
212 TAOLIB_ERROR ((LM_ERROR, "TAO (%P|%t) - SCIOP_Connector::"
213 "make_connection_i, "
214 "wait for completion failed\n"));
217 else
219 // Transport is not usable
220 transport = 0;
224 // In case of errors transport is zero
225 if (transport == 0)
227 // Give users a clue to the problem.
228 if (TAO_debug_level)
230 TAOLIB_ERROR ((LM_ERROR,
231 ACE_TEXT("TAO (%P|%t) - SCIOP_Connector::make_connection_i, ")
232 ACE_TEXT("connection to <%C:%d> failed (%p)\n"),
233 sciop_endpoint->host (), sciop_endpoint->port (),
234 ACE_TEXT("errno")));
237 return 0;
240 TAO_Leader_Follower &leader_follower = this->orb_core ()->leader_follower ();
242 if (svc_handler->keep_waiting (leader_follower))
244 svc_handler->connection_pending ();
247 if (svc_handler->error_detected (leader_follower))
249 svc_handler->cancel_pending_connection ();
250 return 0;
253 // At this point, the connection has be successfully connected.
254 // #REFCOUNT# is one.
255 if (TAO_debug_level > 2)
256 TAOLIB_DEBUG ((LM_DEBUG,
257 "TAO (%P|%t) - SCIOP_Connector::make_connection_i, "
258 "new %C connection to <%C:%d> on Transport[%d]\n",
259 transport->is_connected() ? "connected" : "not connected",
260 sciop_endpoint->host (), sciop_endpoint->port (),
261 svc_handler->peer ().get_handle ()));
263 // Add the handler to Cache
264 int retval =
265 this->orb_core ()->lane_resources ().transport_cache ().cache_transport (&desc,
266 transport);
268 // Failure in adding to cache.
269 if (retval == -1)
271 // Close the handler.
272 svc_handler->close ();
274 if (TAO_debug_level > 0)
276 TAOLIB_ERROR ((LM_ERROR,
277 "TAO (%P|%t) - SCIOP_Connector::make_connection_i, "
278 "could not add the new connection to cache\n"));
281 return 0;
284 if (svc_handler->error_detected (leader_follower))
286 svc_handler->cancel_pending_connection ();
287 transport->purge_entry();
288 return 0;
291 if (transport->is_connected () &&
292 transport->wait_strategy ()->register_handler () != 0)
294 // Registration failures.
296 // Purge from the connection cache, if we are not in the cache, this
297 // just does nothing.
298 (void) transport->purge_entry ();
300 // Close the handler.
301 (void) transport->close_connection ();
303 if (TAO_debug_level > 0)
304 TAOLIB_ERROR ((LM_ERROR,
305 "TAO (%P|%t) - SCIOP_Connector [%d]::make_connection_i, "
306 "could not register the transport "
307 "in the reactor.\n",
308 transport->id ()));
310 return 0;
313 svc_handler_auto_ptr.release ();
314 return transport;
317 TAO_Profile *
318 TAO_SCIOP_Connector::create_profile (TAO_InputCDR& cdr)
320 TAO_Profile *pfile = 0;
321 ACE_NEW_RETURN (pfile,
322 TAO_SCIOP_Profile (this->orb_core ()),
325 int const r = pfile->decode (cdr);
326 if (r == -1)
328 pfile->_decr_refcnt ();
329 pfile = 0;
332 return pfile;
335 TAO_Profile *
336 TAO_SCIOP_Connector::make_profile ()
338 // The endpoint should be of the form:
339 // N.n@host:port/object_key
340 // or:
341 // host:port/object_key
343 TAO_Profile *profile = 0;
344 ACE_NEW_THROW_EX (profile,
345 TAO_SCIOP_Profile (this->orb_core ()),
346 CORBA::NO_MEMORY (
347 CORBA::SystemException::_tao_minor_code (
348 TAO::VMCID,
349 ENOMEM),
350 CORBA::COMPLETED_NO));
352 return profile;
356 TAO_SCIOP_Connector::check_prefix (const char *endpoint)
358 // Check for a valid string
359 if (!endpoint || !*endpoint)
360 return -1; // Failure
362 const char *protocol[] = { "sciop", "scioploc" };
364 size_t const slot = std::strchr (endpoint, ':') - endpoint;
365 size_t const len0 = std::strlen (protocol[0]);
366 size_t const len1 = std::strlen (protocol[1]);
368 // Check for the proper prefix in the IOR. If the proper prefix
369 // isn't in the IOR then it is not an IOR we can use.
370 if (slot == len0
371 && ACE_OS::strncasecmp (endpoint, protocol[0], len0) == 0)
372 return 0;
373 else if (slot == len1
374 && ACE_OS::strncasecmp (endpoint, protocol[1], len1) == 0)
375 return 0;
377 return -1;
378 // Failure: not an SCIOP IOR
379 // DO NOT throw an exception here.
382 char
383 TAO_SCIOP_Connector::object_key_delimiter () const
385 return TAO_SCIOP_Profile::object_key_delimiter_;
388 TAO_SCIOP_Endpoint *
389 TAO_SCIOP_Connector::remote_endpoint (TAO_Endpoint *endpoint)
391 if (endpoint->tag () != TAO_TAG_SCIOP_PROFILE)
392 return 0;
394 TAO_SCIOP_Endpoint *sciop_endpoint =
395 dynamic_cast<TAO_SCIOP_Endpoint *> (endpoint );
396 if (sciop_endpoint == 0)
397 return 0;
399 return sciop_endpoint;
403 TAO_SCIOP_Connector::cancel_svc_handler (
404 TAO_Connection_Handler * svc_handler)
406 TAO_SCIOP_Connection_Handler* handler=
407 dynamic_cast<TAO_SCIOP_Connection_Handler*>(svc_handler);
409 if (handler)
410 // Cancel from the connector
411 return this->base_connector_.cancel (handler);
413 return -1;
416 TAO_END_VERSIONED_NAMESPACE_DECL
418 #endif /* TAO_HAS_SCIOP == 1 */