1 /******************************************************************************
2
3
4 Copyright 1993, 1998 The Open Group
5
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
10 documentation.
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of The Open Group shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from The Open Group.
25
26 Author: Ralph Mor, X Consortium
27 ******************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32 #include <X11/ICE/ICElib.h>
33 #include "ICElibint.h"
34 #include <X11/Xtrans/Xtrans.h>
35
36
37 Status
IceProtocolShutdown(IceConn iceConn,int majorOpcode)38 IceProtocolShutdown (
39 IceConn iceConn,
40 int majorOpcode
41 )
42 {
43 int i;
44
45 if (iceConn->proto_ref_count == 0 || iceConn->process_msg_info == NULL ||
46 majorOpcode < 1 || majorOpcode > _IceLastMajorOpcode)
47 {
48 return (0);
49 }
50
51
52 /*
53 * Make sure this majorOpcode is really being used.
54 */
55
56 for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++)
57 {
58 int n = i - iceConn->his_min_opcode;
59 if (iceConn->process_msg_info[n].in_use &&
60 iceConn->process_msg_info[n].my_opcode == majorOpcode)
61 {
62
63 /*
64 * OK, we can shut down the protocol.
65 */
66
67 iceConn->process_msg_info[n].in_use = False;
68 iceConn->proto_ref_count--;
69 return (1);
70 }
71 }
72
73 return (0);
74 }
75
76
77
78 void
IceSetShutdownNegotiation(IceConn iceConn,Bool negotiate)79 IceSetShutdownNegotiation (
80 IceConn iceConn,
81 Bool negotiate
82 )
83 {
84 iceConn->skip_want_to_close = negotiate ? False : True;
85 }
86
87
88
89 Bool
IceCheckShutdownNegotiation(IceConn iceConn)90 IceCheckShutdownNegotiation (
91 IceConn iceConn
92 )
93 {
94 return (iceConn->skip_want_to_close ? False : True);
95 }
96
97
98
99 IceCloseStatus
IceCloseConnection(IceConn iceConn)100 IceCloseConnection (
101 IceConn iceConn
102 )
103 {
104 int refCountReachedZero;
105 IceCloseStatus status;
106
107 /*
108 * If this connection object was never valid, we can close
109 * it right now. This happens if IceAcceptConnection was
110 * called, but after calling IceProcessMessages several times
111 * the connection was rejected (because of authentication or
112 * some other reason).
113 */
114
115 if (iceConn->listen_obj &&
116 iceConn->connection_status != IceConnectAccepted)
117 {
118 _IceConnectionClosed (iceConn); /* invoke watch procs */
119 _IceFreeConnection (iceConn);
120 return (IceClosedNow);
121 }
122
123
124 /*---------------------------------------------------------------
125
126 ACTIONS:
127
128 A = Invoke Watch Procedures
129 B = Set free-asap bit
130 C = Free connection
131 D = Initialize shutdown negotiation
132 N = do nothing
133
134
135 ACTION TABLE:
136
137 IO free- dispatch protocol shutdown
138 error asap bit level refcount negotiation ACTION
139 occured set reached 0 reached 0
140
141 0 0 0 0 0 N
142 0 0 0 0 1 N
143 0 0 0 1 0 AB
144 0 0 0 1 1 N
145 0 0 1 0 0 N
146 0 0 1 0 1 N
147 0 0 1 1 0 AC
148 0 0 1 1 1 D
149 0 1 0 0 0 N
150 0 1 0 0 1 N
151 0 1 0 1 0 N
152 0 1 0 1 1 N
153 0 1 1 0 0 C
154 0 1 1 0 1 D
155 0 1 1 1 0 C
156 0 1 1 1 1 D
157 1 0 0 0 0 AB
158 1 0 0 0 1 AB
159 1 0 0 1 0 AB
160 1 0 0 1 1 AB
161 1 0 1 0 0 AC
162 1 0 1 0 1 AC
163 1 0 1 1 0 AC
164 1 0 1 1 1 AC
165 1 1 0 0 0 N
166 1 1 0 0 1 N
167 1 1 0 1 0 N
168 1 1 0 1 1 N
169 1 1 1 0 0 C
170 1 1 1 0 1 C
171 1 1 1 1 0 C
172 1 1 1 1 1 C
173
174 ---------------------------------------------------------------*/
175
176 if (iceConn->open_ref_count > 0)
177 iceConn->open_ref_count--;
178
179 refCountReachedZero = iceConn->open_ref_count == 0 &&
180 iceConn->proto_ref_count == 0;
181
182 status = IceConnectionInUse;
183
184 if (!iceConn->free_asap && (!iceConn->io_ok ||
185 (iceConn->io_ok && refCountReachedZero &&
186 iceConn->skip_want_to_close)))
187 {
188 /*
189 * Invoke the watch procedures now.
190 */
191
192 _IceConnectionClosed (iceConn);
193 status = IceClosedNow; /* may be overwritten by IceClosedASAP */
194 }
195
196 if (!iceConn->free_asap && iceConn->dispatch_level != 0 &&
197 (!iceConn->io_ok ||
198 (iceConn->io_ok && refCountReachedZero &&
199 iceConn->skip_want_to_close)))
200 {
201 /*
202 * Set flag so we free the connection as soon as possible.
203 */
204
205 iceConn->free_asap = True;
206 status = IceClosedASAP;
207 }
208
209 if (iceConn->io_ok && iceConn->dispatch_level == 0 &&
210 !iceConn->skip_want_to_close && refCountReachedZero)
211 {
212 /*
213 * Initiate shutdown negotiation.
214 */
215
216 IceSimpleMessage (iceConn, 0, ICE_WantToClose);
217 IceFlush (iceConn);
218
219 iceConn->want_to_close = 1;
220
221 status = IceStartedShutdownNegotiation;
222 }
223 else if (iceConn->dispatch_level == 0 &&
224 (!iceConn->io_ok || (iceConn->io_ok && iceConn->skip_want_to_close &&
225 (iceConn->free_asap || (!iceConn->free_asap && refCountReachedZero)))))
226 {
227 /*
228 * Free the connection.
229 */
230
231 _IceFreeConnection (iceConn);
232
233 status = IceClosedNow;
234 }
235
236 return (status);
237 }
238
239
240
241 void
_IceFreeConnection(IceConn iceConn)242 _IceFreeConnection (
243 IceConn iceConn
244 )
245 {
246 if (iceConn->listen_obj == NULL)
247 {
248 /*
249 * This iceConn was created with IceOpenConnection.
250 * We keep track of all open IceConn's, so we need
251 * to remove it from the list.
252 */
253
254 int i;
255
256 for (i = 0; i < _IceConnectionCount; i++)
257 if (_IceConnectionObjs[i] == iceConn)
258 break;
259
260 if (i < _IceConnectionCount)
261 {
262 if (i < _IceConnectionCount - 1)
263 {
264 _IceConnectionObjs[i] =
265 _IceConnectionObjs[_IceConnectionCount - 1];
266 _IceConnectionStrings[i] =
267 _IceConnectionStrings[_IceConnectionCount - 1];
268 }
269
270 _IceConnectionCount--;
271 }
272 }
273
274 if (iceConn->trans_conn)
275 _IceTransClose (iceConn->trans_conn);
276
277 free (iceConn->connection_string);
278 free (iceConn->vendor);
279 free (iceConn->release);
280 free (iceConn->inbuf);
281 free (iceConn->outbuf);
282 free (iceConn->scratch);
283 free (iceConn->process_msg_info);
284 free (iceConn->connect_to_you);
285 free (iceConn->protosetup_to_you);
286 free (iceConn->connect_to_me);
287 free (iceConn->protosetup_to_me);
288 free (iceConn);
289 }
290
291
292
293
294