shutdown.c revision 266e564d
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 (iceConn, majorOpcode) 41 42IceConn iceConn; 43int majorOpcode; 44 45{ 46 if (iceConn->proto_ref_count == 0 || iceConn->process_msg_info == NULL || 47 majorOpcode < 1 || majorOpcode > _IceLastMajorOpcode) 48 { 49 return (0); 50 } 51 else 52 { 53 /* 54 * Make sure this majorOpcode is really being used. 55 */ 56 57 int i; 58 59 for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++) 60 { 61 if (iceConn->process_msg_info[ 62 i - iceConn->his_min_opcode].in_use && 63 iceConn->process_msg_info[ 64 i - iceConn->his_min_opcode].my_opcode == majorOpcode) 65 break; 66 } 67 68 if (i > iceConn->his_max_opcode) 69 { 70 return (0); 71 } 72 else 73 { 74 /* 75 * OK, we can shut down the protocol. 76 */ 77 78 iceConn->process_msg_info[ 79 i - iceConn->his_min_opcode].in_use = False; 80 iceConn->proto_ref_count--; 81 82 return (1); 83 } 84 } 85} 86 87 88 89void 90IceSetShutdownNegotiation (iceConn, negotiate) 91 92IceConn iceConn; 93Bool negotiate; 94 95{ 96 iceConn->skip_want_to_close = negotiate ? False : True; 97} 98 99 100 101Bool 102IceCheckShutdownNegotiation (iceConn) 103 104IceConn iceConn; 105 106{ 107 return (iceConn->skip_want_to_close ? False : True); 108} 109 110 111 112IceCloseStatus 113IceCloseConnection (iceConn) 114 115IceConn iceConn; 116 117{ 118 int refCountReachedZero; 119 IceCloseStatus status; 120 121 /* 122 * If this connection object was never valid, we can close 123 * it right now. This happens if IceAcceptConnection was 124 * called, but after calling IceProcessMessages several times 125 * the connection was rejected (because of authentication or 126 * some other reason). 127 */ 128 129 if (iceConn->listen_obj && 130 iceConn->connection_status != IceConnectAccepted) 131 { 132 _IceConnectionClosed (iceConn); /* invoke watch procs */ 133 _IceFreeConnection (iceConn); 134 return (IceClosedNow); 135 } 136 137 138 /*--------------------------------------------------------------- 139 140 ACTIONS: 141 142 A = Invoke Watch Procedures 143 B = Set free-asap bit 144 C = Free connection 145 D = Initialize shutdown negotiation 146 N = do nothing 147 148 149 ACTION TABLE: 150 151 IO free- dispatch protocol shutdown 152 error asap bit level refcount negotiation ACTION 153 occured set reached 0 reached 0 154 155 0 0 0 0 0 N 156 0 0 0 0 1 N 157 0 0 0 1 0 AB 158 0 0 0 1 1 N 159 0 0 1 0 0 N 160 0 0 1 0 1 N 161 0 0 1 1 0 AC 162 0 0 1 1 1 D 163 0 1 0 0 0 N 164 0 1 0 0 1 N 165 0 1 0 1 0 N 166 0 1 0 1 1 N 167 0 1 1 0 0 C 168 0 1 1 0 1 D 169 0 1 1 1 0 C 170 0 1 1 1 1 D 171 1 0 0 0 0 AB 172 1 0 0 0 1 AB 173 1 0 0 1 0 AB 174 1 0 0 1 1 AB 175 1 0 1 0 0 AC 176 1 0 1 0 1 AC 177 1 0 1 1 0 AC 178 1 0 1 1 1 AC 179 1 1 0 0 0 N 180 1 1 0 0 1 N 181 1 1 0 1 0 N 182 1 1 0 1 1 N 183 1 1 1 0 0 C 184 1 1 1 0 1 C 185 1 1 1 1 0 C 186 1 1 1 1 1 C 187 188 ---------------------------------------------------------------*/ 189 190 if (iceConn->open_ref_count > 0) 191 iceConn->open_ref_count--; 192 193 refCountReachedZero = iceConn->open_ref_count == 0 && 194 iceConn->proto_ref_count == 0; 195 196 status = IceConnectionInUse; 197 198 if (!iceConn->free_asap && (!iceConn->io_ok || 199 (iceConn->io_ok && refCountReachedZero && 200 iceConn->skip_want_to_close))) 201 { 202 /* 203 * Invoke the watch procedures now. 204 */ 205 206 _IceConnectionClosed (iceConn); 207 status = IceClosedNow; /* may be overwritten by IceClosedASAP */ 208 } 209 210 if (!iceConn->free_asap && iceConn->dispatch_level != 0 && 211 (!iceConn->io_ok || 212 (iceConn->io_ok && refCountReachedZero && 213 iceConn->skip_want_to_close))) 214 { 215 /* 216 * Set flag so we free the connection as soon as possible. 217 */ 218 219 iceConn->free_asap = True; 220 status = IceClosedASAP; 221 } 222 223 if (iceConn->io_ok && iceConn->dispatch_level == 0 && 224 !iceConn->skip_want_to_close && refCountReachedZero) 225 { 226 /* 227 * Initiate shutdown negotiation. 228 */ 229 230 IceSimpleMessage (iceConn, 0, ICE_WantToClose); 231 IceFlush (iceConn); 232 233 iceConn->want_to_close = 1; 234 235 status = IceStartedShutdownNegotiation; 236 } 237 else if (iceConn->dispatch_level == 0 && 238 (!iceConn->io_ok || (iceConn->io_ok && iceConn->skip_want_to_close && 239 (iceConn->free_asap || (!iceConn->free_asap && refCountReachedZero))))) 240 { 241 /* 242 * Free the connection. 243 */ 244 245 _IceFreeConnection (iceConn); 246 247 status = IceClosedNow; 248 } 249 250 return (status); 251} 252 253 254 255void 256_IceFreeConnection (iceConn) 257 258IceConn iceConn; 259 260{ 261 if (iceConn->listen_obj == NULL) 262 { 263 /* 264 * This iceConn was created with IceOpenConnection. 265 * We keep track of all open IceConn's, so we need 266 * to remove it from the list. 267 */ 268 269 int i; 270 271 for (i = 0; i < _IceConnectionCount; i++) 272 if (_IceConnectionObjs[i] == iceConn) 273 break; 274 275 if (i < _IceConnectionCount) 276 { 277 if (i < _IceConnectionCount - 1) 278 { 279 _IceConnectionObjs[i] = 280 _IceConnectionObjs[_IceConnectionCount - 1]; 281 _IceConnectionStrings[i] = 282 _IceConnectionStrings[_IceConnectionCount - 1]; 283 } 284 285 _IceConnectionCount--; 286 } 287 } 288 289 if (iceConn->trans_conn) 290 _IceTransClose (iceConn->trans_conn); 291 292 if (iceConn->connection_string) 293 free (iceConn->connection_string); 294 295 if (iceConn->vendor) 296 free (iceConn->vendor); 297 298 if (iceConn->release) 299 free (iceConn->release); 300 301 if (iceConn->inbuf) 302 free (iceConn->inbuf); 303 304 if (iceConn->outbuf) 305 free (iceConn->outbuf); 306 307 if (iceConn->scratch) 308 free (iceConn->scratch); 309 310 if (iceConn->process_msg_info) 311 free ((char *) iceConn->process_msg_info); 312 313 if (iceConn->connect_to_you) 314 free ((char *) iceConn->connect_to_you); 315 316 if (iceConn->protosetup_to_you) 317 free ((char *) iceConn->protosetup_to_you); 318 319 if (iceConn->connect_to_me) 320 free ((char *) iceConn->connect_to_me); 321 322 if (iceConn->protosetup_to_me) 323 free ((char *) iceConn->protosetup_to_me); 324 325 free ((char *) iceConn); 326} 327 328 329 330 331