shutdown.c revision a3129944
1266e564dSmrg/******************************************************************************
2266e564dSmrg
3266e564dSmrg
4266e564dSmrgCopyright 1993, 1998  The Open Group
5266e564dSmrg
6266e564dSmrgPermission to use, copy, modify, distribute, and sell this software and its
7266e564dSmrgdocumentation for any purpose is hereby granted without fee, provided that
8266e564dSmrgthe above copyright notice appear in all copies and that both that
9266e564dSmrgcopyright notice and this permission notice appear in supporting
10266e564dSmrgdocumentation.
11266e564dSmrg
12266e564dSmrgThe above copyright notice and this permission notice shall be included in
13266e564dSmrgall copies or substantial portions of the Software.
14266e564dSmrg
15266e564dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16266e564dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17266e564dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18266e564dSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19266e564dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20266e564dSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21266e564dSmrg
22266e564dSmrgExcept as contained in this notice, the name of The Open Group shall not be
23266e564dSmrgused in advertising or otherwise to promote the sale, use or other dealings
24266e564dSmrgin this Software without prior written authorization from The Open Group.
25266e564dSmrg
26266e564dSmrgAuthor: Ralph Mor, X Consortium
27266e564dSmrg******************************************************************************/
28266e564dSmrg
29266e564dSmrg#ifdef HAVE_CONFIG_H
30266e564dSmrg#include <config.h>
31266e564dSmrg#endif
32266e564dSmrg#include <X11/ICE/ICElib.h>
33266e564dSmrg#include "ICElibint.h"
34266e564dSmrg#include <X11/Xtrans/Xtrans.h>
35266e564dSmrg
36266e564dSmrg
37266e564dSmrgStatus
38c5629e66SmrgIceProtocolShutdown (
39c5629e66Smrg	IceConn iceConn,
40c5629e66Smrg	int	majorOpcode
41c5629e66Smrg)
42266e564dSmrg{
43a3129944Smrg    int i;
44a3129944Smrg
45266e564dSmrg    if (iceConn->proto_ref_count == 0 || iceConn->process_msg_info == NULL ||
46266e564dSmrg        majorOpcode < 1 || majorOpcode > _IceLastMajorOpcode)
47266e564dSmrg    {
48266e564dSmrg	return (0);
49266e564dSmrg    }
50266e564dSmrg
51266e564dSmrg
52a3129944Smrg    /*
53a3129944Smrg     * Make sure this majorOpcode is really being used.
54a3129944Smrg     */
55266e564dSmrg
56a3129944Smrg    for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++)
57a3129944Smrg    {
58a3129944Smrg	int n = i - iceConn->his_min_opcode;
59a3129944Smrg	if (iceConn->process_msg_info[n].in_use &&
60a3129944Smrg	    iceConn->process_msg_info[n].my_opcode == majorOpcode)
61266e564dSmrg	{
62a3129944Smrg
63266e564dSmrg	    /*
64266e564dSmrg	     * OK, we can shut down the protocol.
65266e564dSmrg	     */
66266e564dSmrg
67a3129944Smrg	    iceConn->process_msg_info[n].in_use = False;
68266e564dSmrg	    iceConn->proto_ref_count--;
69266e564dSmrg	    return (1);
70266e564dSmrg	}
71266e564dSmrg    }
72a3129944Smrg
73a3129944Smrg    return (0);
74266e564dSmrg}
75266e564dSmrg
76266e564dSmrg
77a3129944Smrg
78266e564dSmrgvoid
79c5629e66SmrgIceSetShutdownNegotiation (
80c5629e66Smrg	IceConn     	iceConn,
81c5629e66Smrg	Bool		negotiate
82c5629e66Smrg)
83266e564dSmrg{
84266e564dSmrg    iceConn->skip_want_to_close = negotiate ? False : True;
85266e564dSmrg}
86266e564dSmrg
87266e564dSmrg
88a3129944Smrg
89266e564dSmrgBool
90c5629e66SmrgIceCheckShutdownNegotiation (
91c5629e66Smrg	IceConn     iceConn
92c5629e66Smrg)
93266e564dSmrg{
94266e564dSmrg    return (iceConn->skip_want_to_close ? False : True);
95266e564dSmrg}
96266e564dSmrg
97266e564dSmrg
98a3129944Smrg
99266e564dSmrgIceCloseStatus
100c5629e66SmrgIceCloseConnection (
101c5629e66Smrg	IceConn     iceConn
102c5629e66Smrg)
103266e564dSmrg{
104266e564dSmrg    int refCountReachedZero;
105266e564dSmrg    IceCloseStatus status;
106266e564dSmrg
107266e564dSmrg    /*
108266e564dSmrg     * If this connection object was never valid, we can close
109266e564dSmrg     * it right now.  This happens if IceAcceptConnection was
110266e564dSmrg     * called, but after calling IceProcessMessages several times
111266e564dSmrg     * the connection was rejected (because of authentication or
112266e564dSmrg     * some other reason).
113266e564dSmrg     */
114266e564dSmrg
115266e564dSmrg    if (iceConn->listen_obj &&
116266e564dSmrg	iceConn->connection_status != IceConnectAccepted)
117266e564dSmrg    {
118266e564dSmrg	_IceConnectionClosed (iceConn);		/* invoke watch procs */
119266e564dSmrg	_IceFreeConnection (iceConn);
120266e564dSmrg	return (IceClosedNow);
121266e564dSmrg    }
122266e564dSmrg
123266e564dSmrg
124266e564dSmrg    /*---------------------------------------------------------------
125266e564dSmrg
126266e564dSmrg    ACTIONS:
127266e564dSmrg
128266e564dSmrg    A = Invoke Watch Procedures
129266e564dSmrg    B = Set free-asap bit
130266e564dSmrg    C = Free connection
131266e564dSmrg    D = Initialize shutdown negotiation
132266e564dSmrg    N = do nothing
133266e564dSmrg
134266e564dSmrg
135266e564dSmrg    ACTION TABLE:
136266e564dSmrg
137266e564dSmrg    IO	       free-      dispatch   protocol   shutdown
138266e564dSmrg    error      asap bit   level      refcount   negotiation     ACTION
139266e564dSmrg    occured    set        reached 0  reached 0
1409ef0b394Smrg
141266e564dSmrg        0          0          0          0          0		N
142266e564dSmrg        0          0          0          0          1		N
143266e564dSmrg        0          0          0          1          0		AB
144266e564dSmrg        0          0          0          1          1		N
145266e564dSmrg        0          0          1          0          0		N
146266e564dSmrg        0          0          1          0          1		N
147266e564dSmrg        0          0          1          1          0		AC
148266e564dSmrg        0          0          1          1          1		D
149266e564dSmrg        0          1          0          0          0		N
150266e564dSmrg        0          1          0          0          1		N
151266e564dSmrg        0          1          0          1          0		N
152266e564dSmrg        0          1          0          1          1		N
153266e564dSmrg        0          1          1          0          0		C
154266e564dSmrg        0          1          1          0          1		D
155266e564dSmrg        0          1          1          1          0		C
156266e564dSmrg        0          1          1          1          1		D
157266e564dSmrg        1          0          0          0          0		AB
158266e564dSmrg        1          0          0          0          1		AB
159266e564dSmrg        1          0          0          1          0		AB
160266e564dSmrg        1          0          0          1          1		AB
161266e564dSmrg        1          0          1          0          0		AC
162266e564dSmrg        1          0          1          0          1		AC
163266e564dSmrg        1          0          1          1          0		AC
164266e564dSmrg        1          0          1          1          1		AC
165266e564dSmrg        1          1          0          0          0		N
166266e564dSmrg        1          1          0          0          1		N
167266e564dSmrg        1          1          0          1          0		N
168266e564dSmrg        1          1          0          1          1		N
169266e564dSmrg        1          1          1          0          0		C
170266e564dSmrg        1          1          1          0          1		C
171266e564dSmrg        1          1          1          1          0		C
172266e564dSmrg        1          1          1          1          1		C
173266e564dSmrg
174266e564dSmrg    ---------------------------------------------------------------*/
175266e564dSmrg
176266e564dSmrg    if (iceConn->open_ref_count > 0)
177266e564dSmrg	iceConn->open_ref_count--;
178266e564dSmrg
179266e564dSmrg    refCountReachedZero = iceConn->open_ref_count == 0 &&
180266e564dSmrg	iceConn->proto_ref_count == 0;
181266e564dSmrg
182266e564dSmrg    status = IceConnectionInUse;
183266e564dSmrg
184266e564dSmrg    if (!iceConn->free_asap && (!iceConn->io_ok ||
185266e564dSmrg	(iceConn->io_ok && refCountReachedZero &&
186266e564dSmrg	iceConn->skip_want_to_close)))
187266e564dSmrg    {
188266e564dSmrg	/*
189266e564dSmrg	 * Invoke the watch procedures now.
190266e564dSmrg	 */
191266e564dSmrg
192266e564dSmrg	_IceConnectionClosed (iceConn);
193266e564dSmrg	status = IceClosedNow;	     /* may be overwritten by IceClosedASAP */
194266e564dSmrg    }
195266e564dSmrg
196266e564dSmrg    if (!iceConn->free_asap && iceConn->dispatch_level != 0 &&
197266e564dSmrg	(!iceConn->io_ok ||
198266e564dSmrg	(iceConn->io_ok && refCountReachedZero &&
199266e564dSmrg	iceConn->skip_want_to_close)))
200266e564dSmrg    {
201266e564dSmrg	/*
202266e564dSmrg	 * Set flag so we free the connection as soon as possible.
203266e564dSmrg	 */
204266e564dSmrg
205266e564dSmrg	iceConn->free_asap = True;
206266e564dSmrg	status = IceClosedASAP;
207266e564dSmrg    }
208266e564dSmrg
209266e564dSmrg    if (iceConn->io_ok && iceConn->dispatch_level == 0 &&
210266e564dSmrg	!iceConn->skip_want_to_close && refCountReachedZero)
211266e564dSmrg    {
212266e564dSmrg	/*
213266e564dSmrg	 * Initiate shutdown negotiation.
214266e564dSmrg	 */
215266e564dSmrg
216266e564dSmrg	IceSimpleMessage (iceConn, 0, ICE_WantToClose);
217266e564dSmrg	IceFlush (iceConn);
218266e564dSmrg
219266e564dSmrg	iceConn->want_to_close = 1;
220266e564dSmrg
221266e564dSmrg	status = IceStartedShutdownNegotiation;
222266e564dSmrg    }
223266e564dSmrg    else if (iceConn->dispatch_level == 0 &&
224266e564dSmrg	(!iceConn->io_ok || (iceConn->io_ok && iceConn->skip_want_to_close &&
225266e564dSmrg	(iceConn->free_asap || (!iceConn->free_asap && refCountReachedZero)))))
226266e564dSmrg    {
227266e564dSmrg	/*
228266e564dSmrg	 * Free the connection.
229266e564dSmrg	 */
230266e564dSmrg
231266e564dSmrg	_IceFreeConnection (iceConn);
232266e564dSmrg
233266e564dSmrg	status = IceClosedNow;
234266e564dSmrg    }
235266e564dSmrg
236266e564dSmrg    return (status);
237266e564dSmrg}
238266e564dSmrg
239266e564dSmrg
240a3129944Smrg
241266e564dSmrgvoid
242c5629e66Smrg_IceFreeConnection (
243c5629e66Smrg	IceConn iceConn
244c5629e66Smrg)
245266e564dSmrg{
246266e564dSmrg    if (iceConn->listen_obj == NULL)
247266e564dSmrg    {
248266e564dSmrg	/*
249266e564dSmrg	 * This iceConn was created with IceOpenConnection.
250266e564dSmrg	 * We keep track of all open IceConn's, so we need
251266e564dSmrg	 * to remove it from the list.
252266e564dSmrg	 */
253266e564dSmrg
254266e564dSmrg	int i;
255266e564dSmrg
256266e564dSmrg	for (i = 0; i < _IceConnectionCount; i++)
257266e564dSmrg	    if (_IceConnectionObjs[i] == iceConn)
258266e564dSmrg		break;
259266e564dSmrg
260266e564dSmrg	if (i < _IceConnectionCount)
261266e564dSmrg	{
262266e564dSmrg	    if (i < _IceConnectionCount - 1)
263266e564dSmrg	    {
264266e564dSmrg		_IceConnectionObjs[i] =
265266e564dSmrg		    _IceConnectionObjs[_IceConnectionCount - 1];
266266e564dSmrg		_IceConnectionStrings[i] =
267266e564dSmrg		    _IceConnectionStrings[_IceConnectionCount - 1];
268266e564dSmrg	    }
269266e564dSmrg
270266e564dSmrg	    _IceConnectionCount--;
271266e564dSmrg	}
272266e564dSmrg    }
273266e564dSmrg
274266e564dSmrg    if (iceConn->trans_conn)
275266e564dSmrg	_IceTransClose (iceConn->trans_conn);
276266e564dSmrg
277a3129944Smrg    free (iceConn->connection_string);
278a3129944Smrg    free (iceConn->vendor);
279a3129944Smrg    free (iceConn->release);
280a3129944Smrg    free (iceConn->inbuf);
281a3129944Smrg    free (iceConn->outbuf);
282a3129944Smrg    free (iceConn->scratch);
283a3129944Smrg    free (iceConn->process_msg_info);
284a3129944Smrg    free (iceConn->connect_to_you);
285a3129944Smrg    free (iceConn->protosetup_to_you);
286a3129944Smrg    free (iceConn->connect_to_me);
287a3129944Smrg    free (iceConn->protosetup_to_me);
288fb5e8d76Smrg    free (iceConn);
289266e564dSmrg}
290266e564dSmrg
291266e564dSmrg
292266e564dSmrg
293266e564dSmrg
294