Also use Objects as part of an operation but as a result don't generate Any operation...
[ACE_TAO.git] / ACE / ace / TLI_Connector.cpp
blob42682e4dc29854084bde49728a93f31c3b1f1d8c
1 #include "ace/TLI_Connector.h"
5 #if defined (ACE_HAS_TLI)
7 #if !defined (__ACE_INLINE__)
8 #include "ace/TLI_Connector.inl"
9 #endif /* __ACE_INLINE__ */
11 #include "ace/Handle_Set.h"
12 #include "ace/ACE.h"
13 #include "ace/OS_NS_string.h"
14 #include "ace/Time_Value.h"
16 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
18 ACE_ALLOC_HOOK_DEFINE(ACE_TLI_Connector)
20 void
21 ACE_TLI_Connector::dump (void) const
23 #if defined (ACE_HAS_DUMP)
24 ACE_TRACE ("ACE_TLI_Connector::dump");
25 #endif /* ACE_HAS_DUMP */
28 ACE_TLI_Connector::ACE_TLI_Connector (void)
30 ACE_TRACE ("ACE_TLI_Connector::ACE_TLI_Connector");
33 // Connect the <new_stream> to the <remote_sap>, waiting up to
34 // <timeout> amount of time if necessary. It's amazing how
35 // complicated this is to do in TLI...
37 int
38 ACE_TLI_Connector::connect (ACE_TLI_Stream &new_stream,
39 const ACE_Addr &remote_sap,
40 ACE_Time_Value *timeout,
41 const ACE_Addr &local_sap,
42 int reuse_addr,
43 int flags,
44 int /* perms */,
45 const char device[],
46 struct t_info *info,
47 int rwf,
48 struct netbuf *udata,
49 struct netbuf *opt)
51 ACE_TRACE ("ACE_TLI_Connector::connect");
52 int result = 0;
54 // Only open a new endpoint if we don't already have a valid handle.
56 if (new_stream.get_handle () == ACE_INVALID_HANDLE
57 && new_stream.open (device, flags, info) == ACE_INVALID_HANDLE)
58 return -1;
60 if (local_sap != ACE_Addr::sap_any)
62 // Bind the local endpoint to a specific addr.
64 struct t_bind *localaddr;
66 localaddr = (struct t_bind *)
67 ACE_OS::t_alloc (new_stream.get_handle (), T_BIND, T_ADDR);
69 if (localaddr == 0)
70 result = -1;
71 else
73 int one = 1;
74 #if !defined (ACE_HAS_FORE_ATM_XTI)
75 // Reusing the address causes problems with FORE's API. The
76 // issue may be that t_optmgmt isn't fully supported by
77 // FORE. t_errno is TBADOPT after the t_optmgmt call so
78 // maybe options are configured differently for XTI than for
79 // TLI (at least for FORE's implementation - XTI is supposed
80 // to be a superset of TLI).
81 if (reuse_addr
82 && new_stream.set_option (SOL_SOCKET,
83 SO_REUSEADDR,
84 &one,
85 sizeof one) == -1)
86 result = -1;
87 else
88 #endif /* ACE_HAS_FORE_ATM_XTI */
90 void *addr_buf = local_sap.get_addr ();
91 localaddr->addr.len = local_sap.get_size ();
92 ACE_OS::memcpy(localaddr->addr.buf,
93 addr_buf,
94 localaddr->addr.len);
96 if (ACE_OS::t_bind (new_stream.get_handle (),
97 localaddr,
98 localaddr) == -1)
99 result = -1;
101 ACE_OS::t_free ((char *) localaddr,
102 T_BIND);
106 if (result == -1)
108 new_stream.close ();
109 return -1;
112 // Let TLI select the local endpoint addr.
113 else if (ACE_OS::t_bind (new_stream.get_handle (), 0, 0) == -1)
114 return -1;
116 struct t_call *callptr = 0;
118 callptr = (struct t_call *)
119 ACE_OS::t_alloc (new_stream.get_handle (), T_CALL, T_ADDR);
121 if (callptr == 0)
123 new_stream.close ();
124 return -1;
127 void *addr_buf = remote_sap.get_addr ();
128 callptr->addr.len = remote_sap.get_size ();
129 ACE_OS::memcpy (callptr->addr.buf,
130 addr_buf,
131 callptr->addr.len);
132 //callptr->addr.buf = (char *) remote_sap.get_addr ();
134 if (udata != 0)
135 ACE_OS::memcpy ((void *) &callptr->udata, (void *) udata, sizeof *udata);
136 if (opt != 0)
137 ACE_OS::memcpy ((void *) &callptr->opt, (void *) opt, sizeof *opt);
139 // Connect to remote endpoint.
140 #if defined (ACE_HAS_FORE_ATM_XTI)
141 // FORE's XTI/ATM driver has problems with ioctl/fcntl calls so (at least
142 // for now) always have blocking calls.
143 timeout = 0;
144 #endif /* ACE_HAS_FORE_ATM_XTI */
146 if (timeout != 0) // Enable non-blocking, if required.
148 if (new_stream.enable (ACE_NONBLOCK) == -1)
149 result = -1;
151 // Do a non-blocking connect.
152 if (ACE_OS::t_connect (new_stream.get_handle (), callptr, 0) == -1)
154 result = -1;
156 // Check to see if we simply haven't connected yet on a
157 // non-blocking handle or whether there's really an error.
158 if (t_errno == TNODATA)
160 if (*timeout == ACE_Time_Value::zero)
161 errno = EWOULDBLOCK;
162 else
163 result = this->complete (new_stream, 0, timeout);
165 else if (t_errno == TLOOK && new_stream.look () == T_DISCONNECT)
166 new_stream.rcvdis ();
169 // Do a blocking connect to the server.
170 else if (ACE_OS::t_connect (new_stream.get_handle (), callptr, 0) == -1)
171 result = -1;
173 if (result != -1)
175 new_stream.set_rwflag (rwf);
176 #if defined (I_PUSH) && !defined (ACE_HAS_FORE_ATM_XTI)
177 if (new_stream.get_rwflag ())
178 result = ACE_OS::ioctl (new_stream.get_handle (),
179 I_PUSH,
180 const_cast<char *> ("tirdwr"));
181 #endif /* I_PUSH */
183 else if (!(errno == EWOULDBLOCK || errno == ETIME))
185 // If things have gone wrong, close down and return an error.
186 new_stream.close ();
187 new_stream.set_handle (ACE_INVALID_HANDLE);
190 if (ACE_OS::t_free ((char *) callptr, T_CALL) == -1)
191 return -1;
192 return result;
195 // Try to complete a non-blocking connection.
198 ACE_TLI_Connector::complete (ACE_TLI_Stream &new_stream,
199 ACE_Addr *remote_sap,
200 ACE_Time_Value *tv)
202 ACE_TRACE ("ACE_TLI_Connector::complete");
203 #if defined (ACE_WIN32)
204 if (WaitForSingleObject (new_stream.get_handle(), tv->msec()) == WAIT_OBJECT_0)
206 if (ACE_OS::t_look (new_stream.get_handle()) == T_CONNECT)
207 return t_rcvconnect (new_stream.get_handle(), 0);
208 else
209 return -1;
211 else
212 return -1;
213 #else
214 ACE_HANDLE h = ACE::handle_timed_complete (new_stream.get_handle (),
217 if (h == ACE_INVALID_HANDLE)
219 new_stream.close ();
220 return -1;
222 else // We've successfully connected!
224 if (remote_sap != 0)
226 #if defined (ACE_HAS_XTI) || defined (ACE_HAS_SVR4_TLI)
227 struct netbuf name;
229 name.maxlen = remote_sap->get_size ();
230 name.buf = (char *) remote_sap->get_addr ();
232 if (ACE_OS::t_getname (new_stream.get_handle (),
233 &name,
234 REMOTENAME) == -1)
235 #else /* SunOS4 */
236 if (0)
237 #endif /* ACE_HAS_XTI || ACE_HAS_SVR4_TLI */
239 new_stream.close ();
240 return -1;
244 // Start out with non-blocking disabled on the <new_stream>.
245 new_stream.disable (ACE_NONBLOCK);
247 return 0;
249 #endif /* ACE_WIN32 */
252 ACE_END_VERSIONED_NAMESPACE_DECL
254 #endif /* ACE_HAS_TLI */