shutdown.c revision 266e564d
1266e564dSmrg/* $Xorg: shutdown.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
2266e564dSmrg/******************************************************************************
3266e564dSmrg
4266e564dSmrg
5266e564dSmrgCopyright 1993, 1998  The Open Group
6266e564dSmrg
7266e564dSmrgPermission to use, copy, modify, distribute, and sell this software and its
8266e564dSmrgdocumentation for any purpose is hereby granted without fee, provided that
9266e564dSmrgthe above copyright notice appear in all copies and that both that
10266e564dSmrgcopyright notice and this permission notice appear in supporting
11266e564dSmrgdocumentation.
12266e564dSmrg
13266e564dSmrgThe above copyright notice and this permission notice shall be included in
14266e564dSmrgall copies or substantial portions of the Software.
15266e564dSmrg
16266e564dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17266e564dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18266e564dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19266e564dSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20266e564dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21266e564dSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22266e564dSmrg
23266e564dSmrgExcept as contained in this notice, the name of The Open Group shall not be
24266e564dSmrgused in advertising or otherwise to promote the sale, use or other dealings
25266e564dSmrgin this Software without prior written authorization from The Open Group.
26266e564dSmrg
27266e564dSmrgAuthor: Ralph Mor, X Consortium
28266e564dSmrg******************************************************************************/
29266e564dSmrg/* $XFree86: xc/lib/ICE/shutdown.c,v 3.3 2001/08/01 00:44:37 tsi Exp $ */
30266e564dSmrg
31266e564dSmrg#ifdef HAVE_CONFIG_H
32266e564dSmrg#include <config.h>
33266e564dSmrg#endif
34266e564dSmrg#include <X11/ICE/ICElib.h>
35266e564dSmrg#include "ICElibint.h"
36266e564dSmrg#include <X11/Xtrans/Xtrans.h>
37266e564dSmrg
38266e564dSmrg
39266e564dSmrgStatus
40266e564dSmrgIceProtocolShutdown (iceConn, majorOpcode)
41266e564dSmrg
42266e564dSmrgIceConn iceConn;
43266e564dSmrgint	majorOpcode;
44266e564dSmrg
45266e564dSmrg{
46266e564dSmrg    if (iceConn->proto_ref_count == 0 || iceConn->process_msg_info == NULL ||
47266e564dSmrg        majorOpcode < 1 || majorOpcode > _IceLastMajorOpcode)
48266e564dSmrg    {
49266e564dSmrg	return (0);
50266e564dSmrg    }
51266e564dSmrg    else
52266e564dSmrg    {
53266e564dSmrg	/*
54266e564dSmrg	 * Make sure this majorOpcode is really being used.
55266e564dSmrg	 */
56266e564dSmrg
57266e564dSmrg	int i;
58266e564dSmrg
59266e564dSmrg	for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++)
60266e564dSmrg	{
61266e564dSmrg	    if (iceConn->process_msg_info[
62266e564dSmrg		i - iceConn->his_min_opcode].in_use &&
63266e564dSmrg                iceConn->process_msg_info[
64266e564dSmrg		i - iceConn->his_min_opcode].my_opcode == majorOpcode)
65266e564dSmrg		break;
66266e564dSmrg	}
67266e564dSmrg
68266e564dSmrg	if (i > iceConn->his_max_opcode)
69266e564dSmrg	{
70266e564dSmrg	    return (0);
71266e564dSmrg	}
72266e564dSmrg	else
73266e564dSmrg	{
74266e564dSmrg	    /*
75266e564dSmrg	     * OK, we can shut down the protocol.
76266e564dSmrg	     */
77266e564dSmrg
78266e564dSmrg	    iceConn->process_msg_info[
79266e564dSmrg		i - iceConn->his_min_opcode].in_use = False;
80266e564dSmrg	    iceConn->proto_ref_count--;
81266e564dSmrg
82266e564dSmrg	    return (1);
83266e564dSmrg	}
84266e564dSmrg    }
85266e564dSmrg}
86266e564dSmrg
87266e564dSmrg
88266e564dSmrg
89266e564dSmrgvoid
90266e564dSmrgIceSetShutdownNegotiation (iceConn, negotiate)
91266e564dSmrg
92266e564dSmrgIceConn     	iceConn;
93266e564dSmrgBool		negotiate;
94266e564dSmrg
95266e564dSmrg{
96266e564dSmrg    iceConn->skip_want_to_close = negotiate ? False : True;
97266e564dSmrg}
98266e564dSmrg
99266e564dSmrg
100266e564dSmrg
101266e564dSmrgBool
102266e564dSmrgIceCheckShutdownNegotiation (iceConn)
103266e564dSmrg
104266e564dSmrgIceConn     iceConn;
105266e564dSmrg
106266e564dSmrg{
107266e564dSmrg    return (iceConn->skip_want_to_close ? False : True);
108266e564dSmrg}
109266e564dSmrg
110266e564dSmrg
111266e564dSmrg
112266e564dSmrgIceCloseStatus
113266e564dSmrgIceCloseConnection (iceConn)
114266e564dSmrg
115266e564dSmrgIceConn     iceConn;
116266e564dSmrg
117266e564dSmrg{
118266e564dSmrg    int refCountReachedZero;
119266e564dSmrg    IceCloseStatus status;
120266e564dSmrg
121266e564dSmrg    /*
122266e564dSmrg     * If this connection object was never valid, we can close
123266e564dSmrg     * it right now.  This happens if IceAcceptConnection was
124266e564dSmrg     * called, but after calling IceProcessMessages several times
125266e564dSmrg     * the connection was rejected (because of authentication or
126266e564dSmrg     * some other reason).
127266e564dSmrg     */
128266e564dSmrg
129266e564dSmrg    if (iceConn->listen_obj &&
130266e564dSmrg	iceConn->connection_status != IceConnectAccepted)
131266e564dSmrg    {
132266e564dSmrg	_IceConnectionClosed (iceConn);		/* invoke watch procs */
133266e564dSmrg	_IceFreeConnection (iceConn);
134266e564dSmrg	return (IceClosedNow);
135266e564dSmrg    }
136266e564dSmrg
137266e564dSmrg
138266e564dSmrg    /*---------------------------------------------------------------
139266e564dSmrg
140266e564dSmrg    ACTIONS:
141266e564dSmrg
142266e564dSmrg    A = Invoke Watch Procedures
143266e564dSmrg    B = Set free-asap bit
144266e564dSmrg    C = Free connection
145266e564dSmrg    D = Initialize shutdown negotiation
146266e564dSmrg    N = do nothing
147266e564dSmrg
148266e564dSmrg
149266e564dSmrg    ACTION TABLE:
150266e564dSmrg
151266e564dSmrg    IO	       free-      dispatch   protocol   shutdown
152266e564dSmrg    error      asap bit   level      refcount   negotiation     ACTION
153266e564dSmrg    occured    set        reached 0  reached 0
154266e564dSmrg
155266e564dSmrg        0          0          0          0          0		N
156266e564dSmrg        0          0          0          0          1		N
157266e564dSmrg        0          0          0          1          0		AB
158266e564dSmrg        0          0          0          1          1		N
159266e564dSmrg        0          0          1          0          0		N
160266e564dSmrg        0          0          1          0          1		N
161266e564dSmrg        0          0          1          1          0		AC
162266e564dSmrg        0          0          1          1          1		D
163266e564dSmrg        0          1          0          0          0		N
164266e564dSmrg        0          1          0          0          1		N
165266e564dSmrg        0          1          0          1          0		N
166266e564dSmrg        0          1          0          1          1		N
167266e564dSmrg        0          1          1          0          0		C
168266e564dSmrg        0          1          1          0          1		D
169266e564dSmrg        0          1          1          1          0		C
170266e564dSmrg        0          1          1          1          1		D
171266e564dSmrg        1          0          0          0          0		AB
172266e564dSmrg        1          0          0          0          1		AB
173266e564dSmrg        1          0          0          1          0		AB
174266e564dSmrg        1          0          0          1          1		AB
175266e564dSmrg        1          0          1          0          0		AC
176266e564dSmrg        1          0          1          0          1		AC
177266e564dSmrg        1          0          1          1          0		AC
178266e564dSmrg        1          0          1          1          1		AC
179266e564dSmrg        1          1          0          0          0		N
180266e564dSmrg        1          1          0          0          1		N
181266e564dSmrg        1          1          0          1          0		N
182266e564dSmrg        1          1          0          1          1		N
183266e564dSmrg        1          1          1          0          0		C
184266e564dSmrg        1          1          1          0          1		C
185266e564dSmrg        1          1          1          1          0		C
186266e564dSmrg        1          1          1          1          1		C
187266e564dSmrg
188266e564dSmrg    ---------------------------------------------------------------*/
189266e564dSmrg
190266e564dSmrg    if (iceConn->open_ref_count > 0)
191266e564dSmrg	iceConn->open_ref_count--;
192266e564dSmrg
193266e564dSmrg    refCountReachedZero = iceConn->open_ref_count == 0 &&
194266e564dSmrg	iceConn->proto_ref_count == 0;
195266e564dSmrg
196266e564dSmrg    status = IceConnectionInUse;
197266e564dSmrg
198266e564dSmrg    if (!iceConn->free_asap && (!iceConn->io_ok ||
199266e564dSmrg	(iceConn->io_ok && refCountReachedZero &&
200266e564dSmrg	iceConn->skip_want_to_close)))
201266e564dSmrg    {
202266e564dSmrg	/*
203266e564dSmrg	 * Invoke the watch procedures now.
204266e564dSmrg	 */
205266e564dSmrg
206266e564dSmrg	_IceConnectionClosed (iceConn);
207266e564dSmrg	status = IceClosedNow;	     /* may be overwritten by IceClosedASAP */
208266e564dSmrg    }
209266e564dSmrg
210266e564dSmrg    if (!iceConn->free_asap && iceConn->dispatch_level != 0 &&
211266e564dSmrg	(!iceConn->io_ok ||
212266e564dSmrg	(iceConn->io_ok && refCountReachedZero &&
213266e564dSmrg	iceConn->skip_want_to_close)))
214266e564dSmrg    {
215266e564dSmrg	/*
216266e564dSmrg	 * Set flag so we free the connection as soon as possible.
217266e564dSmrg	 */
218266e564dSmrg
219266e564dSmrg	iceConn->free_asap = True;
220266e564dSmrg	status = IceClosedASAP;
221266e564dSmrg    }
222266e564dSmrg
223266e564dSmrg    if (iceConn->io_ok && iceConn->dispatch_level == 0 &&
224266e564dSmrg	!iceConn->skip_want_to_close && refCountReachedZero)
225266e564dSmrg    {
226266e564dSmrg	/*
227266e564dSmrg	 * Initiate shutdown negotiation.
228266e564dSmrg	 */
229266e564dSmrg
230266e564dSmrg	IceSimpleMessage (iceConn, 0, ICE_WantToClose);
231266e564dSmrg	IceFlush (iceConn);
232266e564dSmrg
233266e564dSmrg	iceConn->want_to_close = 1;
234266e564dSmrg
235266e564dSmrg	status = IceStartedShutdownNegotiation;
236266e564dSmrg    }
237266e564dSmrg    else if (iceConn->dispatch_level == 0 &&
238266e564dSmrg	(!iceConn->io_ok || (iceConn->io_ok && iceConn->skip_want_to_close &&
239266e564dSmrg	(iceConn->free_asap || (!iceConn->free_asap && refCountReachedZero)))))
240266e564dSmrg    {
241266e564dSmrg	/*
242266e564dSmrg	 * Free the connection.
243266e564dSmrg	 */
244266e564dSmrg
245266e564dSmrg	_IceFreeConnection (iceConn);
246266e564dSmrg
247266e564dSmrg	status = IceClosedNow;
248266e564dSmrg    }
249266e564dSmrg
250266e564dSmrg    return (status);
251266e564dSmrg}
252266e564dSmrg
253266e564dSmrg
254266e564dSmrg
255266e564dSmrgvoid
256266e564dSmrg_IceFreeConnection (iceConn)
257266e564dSmrg
258266e564dSmrgIceConn iceConn;
259266e564dSmrg
260266e564dSmrg{
261266e564dSmrg    if (iceConn->listen_obj == NULL)
262266e564dSmrg    {
263266e564dSmrg	/*
264266e564dSmrg	 * This iceConn was created with IceOpenConnection.
265266e564dSmrg	 * We keep track of all open IceConn's, so we need
266266e564dSmrg	 * to remove it from the list.
267266e564dSmrg	 */
268266e564dSmrg
269266e564dSmrg	int i;
270266e564dSmrg
271266e564dSmrg	for (i = 0; i < _IceConnectionCount; i++)
272266e564dSmrg	    if (_IceConnectionObjs[i] == iceConn)
273266e564dSmrg		break;
274266e564dSmrg
275266e564dSmrg	if (i < _IceConnectionCount)
276266e564dSmrg	{
277266e564dSmrg	    if (i < _IceConnectionCount - 1)
278266e564dSmrg	    {
279266e564dSmrg		_IceConnectionObjs[i] =
280266e564dSmrg		    _IceConnectionObjs[_IceConnectionCount - 1];
281266e564dSmrg		_IceConnectionStrings[i] =
282266e564dSmrg		    _IceConnectionStrings[_IceConnectionCount - 1];
283266e564dSmrg	    }
284266e564dSmrg
285266e564dSmrg	    _IceConnectionCount--;
286266e564dSmrg	}
287266e564dSmrg    }
288266e564dSmrg
289266e564dSmrg    if (iceConn->trans_conn)
290266e564dSmrg	_IceTransClose (iceConn->trans_conn);
291266e564dSmrg
292266e564dSmrg    if (iceConn->connection_string)
293266e564dSmrg	free (iceConn->connection_string);
294266e564dSmrg
295266e564dSmrg    if (iceConn->vendor)
296266e564dSmrg	free (iceConn->vendor);
297266e564dSmrg
298266e564dSmrg    if (iceConn->release)
299266e564dSmrg	free (iceConn->release);
300266e564dSmrg
301266e564dSmrg    if (iceConn->inbuf)
302266e564dSmrg	free (iceConn->inbuf);
303266e564dSmrg
304266e564dSmrg    if (iceConn->outbuf)
305266e564dSmrg	free (iceConn->outbuf);
306266e564dSmrg
307266e564dSmrg    if (iceConn->scratch)
308266e564dSmrg	free (iceConn->scratch);
309266e564dSmrg
310266e564dSmrg    if (iceConn->process_msg_info)
311266e564dSmrg	free ((char *) iceConn->process_msg_info);
312266e564dSmrg
313266e564dSmrg    if (iceConn->connect_to_you)
314266e564dSmrg	free ((char *) iceConn->connect_to_you);
315266e564dSmrg
316266e564dSmrg    if (iceConn->protosetup_to_you)
317266e564dSmrg	free ((char *) iceConn->protosetup_to_you);
318266e564dSmrg
319266e564dSmrg    if (iceConn->connect_to_me)
320266e564dSmrg	free ((char *) iceConn->connect_to_me);
321266e564dSmrg
322266e564dSmrg    if (iceConn->protosetup_to_me)
323266e564dSmrg	free ((char *) iceConn->protosetup_to_me);
324266e564dSmrg
325266e564dSmrg    free ((char *) iceConn);
326266e564dSmrg}
327266e564dSmrg
328266e564dSmrg
329266e564dSmrg
330266e564dSmrg
331