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