shutdown.c revision a3129944
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 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 78void 79IceSetShutdownNegotiation ( 80 IceConn iceConn, 81 Bool negotiate 82) 83{ 84 iceConn->skip_want_to_close = negotiate ? False : True; 85} 86 87 88 89Bool 90IceCheckShutdownNegotiation ( 91 IceConn iceConn 92) 93{ 94 return (iceConn->skip_want_to_close ? False : True); 95} 96 97 98 99IceCloseStatus 100IceCloseConnection ( 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 241void 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