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