1 /******************************************************************************
2 
3 
4 Copyright 1993, 1998  The Open Group
5 
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
10 documentation.
11 
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14 
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22 Except as contained in this notice, the name of The Open Group shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from The Open Group.
25 
26 Author: 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 
37 Status
IceProtocolShutdown(IceConn iceConn,int majorOpcode)38 IceProtocolShutdown (
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 
78 void
IceSetShutdownNegotiation(IceConn iceConn,Bool negotiate)79 IceSetShutdownNegotiation (
80 	IceConn     	iceConn,
81 	Bool		negotiate
82 )
83 {
84     iceConn->skip_want_to_close = negotiate ? False : True;
85 }
86 
87 
88 
89 Bool
IceCheckShutdownNegotiation(IceConn iceConn)90 IceCheckShutdownNegotiation (
91 	IceConn     iceConn
92 )
93 {
94     return (iceConn->skip_want_to_close ? False : True);
95 }
96 
97 
98 
99 IceCloseStatus
IceCloseConnection(IceConn iceConn)100 IceCloseConnection (
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 
241 void
_IceFreeConnection(IceConn iceConn)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