shutdown.c revision a3129944
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    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
78void
79IceSetShutdownNegotiation (
80	IceConn     	iceConn,
81	Bool		negotiate
82)
83{
84    iceConn->skip_want_to_close = negotiate ? False : True;
85}
86
87
88
89Bool
90IceCheckShutdownNegotiation (
91	IceConn     iceConn
92)
93{
94    return (iceConn->skip_want_to_close ? False : True);
95}
96
97
98
99IceCloseStatus
100IceCloseConnection (
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
241void
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