shutdown.c revision c5629e66
1/* $Xorg: shutdown.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ 2/****************************************************************************** 3 4 5Copyright 1993, 1998 The Open Group 6 7Permission to use, copy, modify, distribute, and sell this software and its 8documentation for any purpose is hereby granted without fee, provided that 9the above copyright notice appear in all copies and that both that 10copyright notice and this permission notice appear in supporting 11documentation. 12 13The above copyright notice and this permission notice shall be included in 14all copies or substantial portions of the Software. 15 16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 20AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 23Except as contained in this notice, the name of The Open Group shall not be 24used in advertising or otherwise to promote the sale, use or other dealings 25in this Software without prior written authorization from The Open Group. 26 27Author: Ralph Mor, X Consortium 28******************************************************************************/ 29/* $XFree86: xc/lib/ICE/shutdown.c,v 3.3 2001/08/01 00:44:37 tsi Exp $ */ 30 31#ifdef HAVE_CONFIG_H 32#include <config.h> 33#endif 34#include <X11/ICE/ICElib.h> 35#include "ICElibint.h" 36#include <X11/Xtrans/Xtrans.h> 37 38 39Status 40IceProtocolShutdown ( 41 IceConn iceConn, 42 int majorOpcode 43) 44{ 45 if (iceConn->proto_ref_count == 0 || iceConn->process_msg_info == NULL || 46 majorOpcode < 1 || majorOpcode > _IceLastMajorOpcode) 47 { 48 return (0); 49 } 50 else 51 { 52 /* 53 * Make sure this majorOpcode is really being used. 54 */ 55 56 int i; 57 58 for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++) 59 { 60 if (iceConn->process_msg_info[ 61 i - iceConn->his_min_opcode].in_use && 62 iceConn->process_msg_info[ 63 i - iceConn->his_min_opcode].my_opcode == majorOpcode) 64 break; 65 } 66 67 if (i > iceConn->his_max_opcode) 68 { 69 return (0); 70 } 71 else 72 { 73 /* 74 * OK, we can shut down the protocol. 75 */ 76 77 iceConn->process_msg_info[ 78 i - iceConn->his_min_opcode].in_use = False; 79 iceConn->proto_ref_count--; 80 81 return (1); 82 } 83 } 84} 85 86 87 88void 89IceSetShutdownNegotiation ( 90 IceConn iceConn, 91 Bool negotiate 92) 93{ 94 iceConn->skip_want_to_close = negotiate ? False : True; 95} 96 97 98 99Bool 100IceCheckShutdownNegotiation ( 101 IceConn iceConn 102) 103{ 104 return (iceConn->skip_want_to_close ? False : True); 105} 106 107 108 109IceCloseStatus 110IceCloseConnection ( 111 IceConn iceConn 112) 113{ 114 int refCountReachedZero; 115 IceCloseStatus status; 116 117 /* 118 * If this connection object was never valid, we can close 119 * it right now. This happens if IceAcceptConnection was 120 * called, but after calling IceProcessMessages several times 121 * the connection was rejected (because of authentication or 122 * some other reason). 123 */ 124 125 if (iceConn->listen_obj && 126 iceConn->connection_status != IceConnectAccepted) 127 { 128 _IceConnectionClosed (iceConn); /* invoke watch procs */ 129 _IceFreeConnection (iceConn); 130 return (IceClosedNow); 131 } 132 133 134 /*--------------------------------------------------------------- 135 136 ACTIONS: 137 138 A = Invoke Watch Procedures 139 B = Set free-asap bit 140 C = Free connection 141 D = Initialize shutdown negotiation 142 N = do nothing 143 144 145 ACTION TABLE: 146 147 IO free- dispatch protocol shutdown 148 error asap bit level refcount negotiation ACTION 149 occured set reached 0 reached 0 150 151 0 0 0 0 0 N 152 0 0 0 0 1 N 153 0 0 0 1 0 AB 154 0 0 0 1 1 N 155 0 0 1 0 0 N 156 0 0 1 0 1 N 157 0 0 1 1 0 AC 158 0 0 1 1 1 D 159 0 1 0 0 0 N 160 0 1 0 0 1 N 161 0 1 0 1 0 N 162 0 1 0 1 1 N 163 0 1 1 0 0 C 164 0 1 1 0 1 D 165 0 1 1 1 0 C 166 0 1 1 1 1 D 167 1 0 0 0 0 AB 168 1 0 0 0 1 AB 169 1 0 0 1 0 AB 170 1 0 0 1 1 AB 171 1 0 1 0 0 AC 172 1 0 1 0 1 AC 173 1 0 1 1 0 AC 174 1 0 1 1 1 AC 175 1 1 0 0 0 N 176 1 1 0 0 1 N 177 1 1 0 1 0 N 178 1 1 0 1 1 N 179 1 1 1 0 0 C 180 1 1 1 0 1 C 181 1 1 1 1 0 C 182 1 1 1 1 1 C 183 184 ---------------------------------------------------------------*/ 185 186 if (iceConn->open_ref_count > 0) 187 iceConn->open_ref_count--; 188 189 refCountReachedZero = iceConn->open_ref_count == 0 && 190 iceConn->proto_ref_count == 0; 191 192 status = IceConnectionInUse; 193 194 if (!iceConn->free_asap && (!iceConn->io_ok || 195 (iceConn->io_ok && refCountReachedZero && 196 iceConn->skip_want_to_close))) 197 { 198 /* 199 * Invoke the watch procedures now. 200 */ 201 202 _IceConnectionClosed (iceConn); 203 status = IceClosedNow; /* may be overwritten by IceClosedASAP */ 204 } 205 206 if (!iceConn->free_asap && iceConn->dispatch_level != 0 && 207 (!iceConn->io_ok || 208 (iceConn->io_ok && refCountReachedZero && 209 iceConn->skip_want_to_close))) 210 { 211 /* 212 * Set flag so we free the connection as soon as possible. 213 */ 214 215 iceConn->free_asap = True; 216 status = IceClosedASAP; 217 } 218 219 if (iceConn->io_ok && iceConn->dispatch_level == 0 && 220 !iceConn->skip_want_to_close && refCountReachedZero) 221 { 222 /* 223 * Initiate shutdown negotiation. 224 */ 225 226 IceSimpleMessage (iceConn, 0, ICE_WantToClose); 227 IceFlush (iceConn); 228 229 iceConn->want_to_close = 1; 230 231 status = IceStartedShutdownNegotiation; 232 } 233 else if (iceConn->dispatch_level == 0 && 234 (!iceConn->io_ok || (iceConn->io_ok && iceConn->skip_want_to_close && 235 (iceConn->free_asap || (!iceConn->free_asap && refCountReachedZero))))) 236 { 237 /* 238 * Free the connection. 239 */ 240 241 _IceFreeConnection (iceConn); 242 243 status = IceClosedNow; 244 } 245 246 return (status); 247} 248 249 250 251void 252_IceFreeConnection ( 253 IceConn iceConn 254) 255{ 256 if (iceConn->listen_obj == NULL) 257 { 258 /* 259 * This iceConn was created with IceOpenConnection. 260 * We keep track of all open IceConn's, so we need 261 * to remove it from the list. 262 */ 263 264 int i; 265 266 for (i = 0; i < _IceConnectionCount; i++) 267 if (_IceConnectionObjs[i] == iceConn) 268 break; 269 270 if (i < _IceConnectionCount) 271 { 272 if (i < _IceConnectionCount - 1) 273 { 274 _IceConnectionObjs[i] = 275 _IceConnectionObjs[_IceConnectionCount - 1]; 276 _IceConnectionStrings[i] = 277 _IceConnectionStrings[_IceConnectionCount - 1]; 278 } 279 280 _IceConnectionCount--; 281 } 282 } 283 284 if (iceConn->trans_conn) 285 _IceTransClose (iceConn->trans_conn); 286 287 if (iceConn->connection_string) 288 free (iceConn->connection_string); 289 290 if (iceConn->vendor) 291 free (iceConn->vendor); 292 293 if (iceConn->release) 294 free (iceConn->release); 295 296 if (iceConn->inbuf) 297 free (iceConn->inbuf); 298 299 if (iceConn->outbuf) 300 free (iceConn->outbuf); 301 302 if (iceConn->scratch) 303 free (iceConn->scratch); 304 305 if (iceConn->process_msg_info) 306 free ((char *) iceConn->process_msg_info); 307 308 if (iceConn->connect_to_you) 309 free ((char *) iceConn->connect_to_you); 310 311 if (iceConn->protosetup_to_you) 312 free ((char *) iceConn->protosetup_to_you); 313 314 if (iceConn->connect_to_me) 315 free ((char *) iceConn->connect_to_me); 316 317 if (iceConn->protosetup_to_me) 318 free ((char *) iceConn->protosetup_to_me); 319 320 free ((char *) iceConn); 321} 322 323 324 325 326