upload tizen2.0 source
[framework/uifw/xorg/lib/libice.git] / src / shutdown.c
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
38 IceProtocolShutdown (
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 \f
86 void
87 IceSetShutdownNegotiation (
88         IceConn         iceConn,
89         Bool            negotiate
90 )
91 {
92     iceConn->skip_want_to_close = negotiate ? False : True;
93 }
94
95
96 \f
97 Bool
98 IceCheckShutdownNegotiation (
99         IceConn     iceConn
100 )
101 {
102     return (iceConn->skip_want_to_close ? False : True);
103 }
104
105
106 \f
107 IceCloseStatus
108 IceCloseConnection (
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 \f
249 void
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