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