shutdown.c revision 266e564d
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 (iceConn, majorOpcode)
41
42IceConn iceConn;
43int	majorOpcode;
44
45{
46    if (iceConn->proto_ref_count == 0 || iceConn->process_msg_info == NULL ||
47        majorOpcode < 1 || majorOpcode > _IceLastMajorOpcode)
48    {
49	return (0);
50    }
51    else
52    {
53	/*
54	 * Make sure this majorOpcode is really being used.
55	 */
56
57	int i;
58
59	for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++)
60	{
61	    if (iceConn->process_msg_info[
62		i - iceConn->his_min_opcode].in_use &&
63                iceConn->process_msg_info[
64		i - iceConn->his_min_opcode].my_opcode == majorOpcode)
65		break;
66	}
67
68	if (i > iceConn->his_max_opcode)
69	{
70	    return (0);
71	}
72	else
73	{
74	    /*
75	     * OK, we can shut down the protocol.
76	     */
77
78	    iceConn->process_msg_info[
79		i - iceConn->his_min_opcode].in_use = False;
80	    iceConn->proto_ref_count--;
81
82	    return (1);
83	}
84    }
85}
86
87
88
89void
90IceSetShutdownNegotiation (iceConn, negotiate)
91
92IceConn     	iceConn;
93Bool		negotiate;
94
95{
96    iceConn->skip_want_to_close = negotiate ? False : True;
97}
98
99
100
101Bool
102IceCheckShutdownNegotiation (iceConn)
103
104IceConn     iceConn;
105
106{
107    return (iceConn->skip_want_to_close ? False : True);
108}
109
110
111
112IceCloseStatus
113IceCloseConnection (iceConn)
114
115IceConn     iceConn;
116
117{
118    int refCountReachedZero;
119    IceCloseStatus status;
120
121    /*
122     * If this connection object was never valid, we can close
123     * it right now.  This happens if IceAcceptConnection was
124     * called, but after calling IceProcessMessages several times
125     * the connection was rejected (because of authentication or
126     * some other reason).
127     */
128
129    if (iceConn->listen_obj &&
130	iceConn->connection_status != IceConnectAccepted)
131    {
132	_IceConnectionClosed (iceConn);		/* invoke watch procs */
133	_IceFreeConnection (iceConn);
134	return (IceClosedNow);
135    }
136
137
138    /*---------------------------------------------------------------
139
140    ACTIONS:
141
142    A = Invoke Watch Procedures
143    B = Set free-asap bit
144    C = Free connection
145    D = Initialize shutdown negotiation
146    N = do nothing
147
148
149    ACTION TABLE:
150
151    IO	       free-      dispatch   protocol   shutdown
152    error      asap bit   level      refcount   negotiation     ACTION
153    occured    set        reached 0  reached 0
154
155        0          0          0          0          0		N
156        0          0          0          0          1		N
157        0          0          0          1          0		AB
158        0          0          0          1          1		N
159        0          0          1          0          0		N
160        0          0          1          0          1		N
161        0          0          1          1          0		AC
162        0          0          1          1          1		D
163        0          1          0          0          0		N
164        0          1          0          0          1		N
165        0          1          0          1          0		N
166        0          1          0          1          1		N
167        0          1          1          0          0		C
168        0          1          1          0          1		D
169        0          1          1          1          0		C
170        0          1          1          1          1		D
171        1          0          0          0          0		AB
172        1          0          0          0          1		AB
173        1          0          0          1          0		AB
174        1          0          0          1          1		AB
175        1          0          1          0          0		AC
176        1          0          1          0          1		AC
177        1          0          1          1          0		AC
178        1          0          1          1          1		AC
179        1          1          0          0          0		N
180        1          1          0          0          1		N
181        1          1          0          1          0		N
182        1          1          0          1          1		N
183        1          1          1          0          0		C
184        1          1          1          0          1		C
185        1          1          1          1          0		C
186        1          1          1          1          1		C
187
188    ---------------------------------------------------------------*/
189
190    if (iceConn->open_ref_count > 0)
191	iceConn->open_ref_count--;
192
193    refCountReachedZero = iceConn->open_ref_count == 0 &&
194	iceConn->proto_ref_count == 0;
195
196    status = IceConnectionInUse;
197
198    if (!iceConn->free_asap && (!iceConn->io_ok ||
199	(iceConn->io_ok && refCountReachedZero &&
200	iceConn->skip_want_to_close)))
201    {
202	/*
203	 * Invoke the watch procedures now.
204	 */
205
206	_IceConnectionClosed (iceConn);
207	status = IceClosedNow;	     /* may be overwritten by IceClosedASAP */
208    }
209
210    if (!iceConn->free_asap && iceConn->dispatch_level != 0 &&
211	(!iceConn->io_ok ||
212	(iceConn->io_ok && refCountReachedZero &&
213	iceConn->skip_want_to_close)))
214    {
215	/*
216	 * Set flag so we free the connection as soon as possible.
217	 */
218
219	iceConn->free_asap = True;
220	status = IceClosedASAP;
221    }
222
223    if (iceConn->io_ok && iceConn->dispatch_level == 0 &&
224	!iceConn->skip_want_to_close && refCountReachedZero)
225    {
226	/*
227	 * Initiate shutdown negotiation.
228	 */
229
230	IceSimpleMessage (iceConn, 0, ICE_WantToClose);
231	IceFlush (iceConn);
232
233	iceConn->want_to_close = 1;
234
235	status = IceStartedShutdownNegotiation;
236    }
237    else if (iceConn->dispatch_level == 0 &&
238	(!iceConn->io_ok || (iceConn->io_ok && iceConn->skip_want_to_close &&
239	(iceConn->free_asap || (!iceConn->free_asap && refCountReachedZero)))))
240    {
241	/*
242	 * Free the connection.
243	 */
244
245	_IceFreeConnection (iceConn);
246
247	status = IceClosedNow;
248    }
249
250    return (status);
251}
252
253
254
255void
256_IceFreeConnection (iceConn)
257
258IceConn iceConn;
259
260{
261    if (iceConn->listen_obj == NULL)
262    {
263	/*
264	 * This iceConn was created with IceOpenConnection.
265	 * We keep track of all open IceConn's, so we need
266	 * to remove it from the list.
267	 */
268
269	int i;
270
271	for (i = 0; i < _IceConnectionCount; i++)
272	    if (_IceConnectionObjs[i] == iceConn)
273		break;
274
275	if (i < _IceConnectionCount)
276	{
277	    if (i < _IceConnectionCount - 1)
278	    {
279		_IceConnectionObjs[i] =
280		    _IceConnectionObjs[_IceConnectionCount - 1];
281		_IceConnectionStrings[i] =
282		    _IceConnectionStrings[_IceConnectionCount - 1];
283	    }
284
285	    _IceConnectionCount--;
286	}
287    }
288
289    if (iceConn->trans_conn)
290	_IceTransClose (iceConn->trans_conn);
291
292    if (iceConn->connection_string)
293	free (iceConn->connection_string);
294
295    if (iceConn->vendor)
296	free (iceConn->vendor);
297
298    if (iceConn->release)
299	free (iceConn->release);
300
301    if (iceConn->inbuf)
302	free (iceConn->inbuf);
303
304    if (iceConn->outbuf)
305	free (iceConn->outbuf);
306
307    if (iceConn->scratch)
308	free (iceConn->scratch);
309
310    if (iceConn->process_msg_info)
311	free ((char *) iceConn->process_msg_info);
312
313    if (iceConn->connect_to_you)
314	free ((char *) iceConn->connect_to_you);
315
316    if (iceConn->protosetup_to_you)
317	free ((char *) iceConn->protosetup_to_you);
318
319    if (iceConn->connect_to_me)
320	free ((char *) iceConn->connect_to_me);
321
322    if (iceConn->protosetup_to_me)
323	free ((char *) iceConn->protosetup_to_me);
324
325    free ((char *) iceConn);
326}
327
328
329
330
331