misc.c revision 1009a292
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 WIN32 30#define _WILLWINSOCK_ 31#endif 32#ifdef HAVE_CONFIG_H 33#include <config.h> 34#endif 35#include <X11/ICE/ICElib.h> 36#include "ICElibint.h" 37#include <X11/Xtrans/Xtrans.h> 38#include <stdio.h> 39#ifdef WIN32 40#include <X11/Xwinsock.h> 41#include <X11/Xw32defs.h> 42#endif 43 44 45/* 46 * scratch buffer 47 */ 48 49char * 50IceAllocScratch ( 51 IceConn iceConn, 52 unsigned long size 53) 54{ 55 if (!iceConn->scratch || size > iceConn->scratch_size) 56 { 57 free (iceConn->scratch); 58 59 iceConn->scratch = malloc (size); 60 iceConn->scratch_size = size; 61 } 62 63 return (iceConn->scratch); 64} 65 66/* 67 * Fatal IO error. First notify each protocol's IceIOErrorProc 68 * callback, then invoke the application IO error handler. 69 */ 70 71static void _X_COLD 72IceFatalIOError ( 73 IceConn iceConn 74) 75{ 76 iceConn->io_ok = False; 77 78 if (iceConn->connection_status == IceConnectPending) 79 { 80 /* 81 * Don't invoke IO error handler if we are in the 82 * middle of a connection setup. 83 */ 84 85 return; 86 } 87 88 if (iceConn->process_msg_info) 89 { 90 for (int i = iceConn->his_min_opcode; 91 i <= iceConn->his_max_opcode; i++) 92 { 93 _IceProcessMsgInfo *process; 94 95 process = &iceConn->process_msg_info[i - iceConn->his_min_opcode]; 96 97 if ((process != NULL) && process->in_use) 98 { 99 IceIOErrorProc IOErrProc = process->accept_flag ? 100 process->protocol->accept_client->io_error_proc : 101 process->protocol->orig_client->io_error_proc; 102 103 if (IOErrProc) 104 (*IOErrProc) (iceConn); 105 } 106 } 107 } 108 109 (*_IceIOErrorHandler) (iceConn); 110 return; 111} 112 113/* 114 * Output/Input buffer functions 115 */ 116 117int 118IceFlush ( 119 IceConn iceConn 120) 121{ 122 /* 123 * Should be impossible, unless we messed up our buffer math somewhere, 124 * or one of our pointers has been corrupted. 125 */ 126 if (_X_UNLIKELY(iceConn->outbufptr > iceConn->outbufmax)) 127 { 128 IceFatalIOError (iceConn); 129 return 0; 130 } 131 132 _IceWrite (iceConn, 133 (unsigned long) (iceConn->outbufptr - iceConn->outbuf), 134 iceConn->outbuf); 135 136 iceConn->outbufptr = iceConn->outbuf; 137 return 1; 138} 139 140 141int 142IceGetOutBufSize ( 143 IceConn iceConn 144) 145{ 146 return (iceConn->outbufmax - iceConn->outbuf); 147} 148 149 150int 151IceGetInBufSize ( 152 IceConn iceConn 153) 154{ 155 return (iceConn->inbufmax - iceConn->inbuf); 156} 157 158 159 160/* 161 * informational functions 162 */ 163 164IceConnectStatus 165IceConnectionStatus ( 166 IceConn iceConn 167) 168{ 169 return (iceConn->connection_status); 170} 171 172 173char * 174IceVendor ( 175 IceConn iceConn 176) 177{ 178 return strdup(iceConn->vendor); 179} 180 181 182char * 183IceRelease ( 184 IceConn iceConn 185) 186{ 187 return strdup(iceConn->release); 188} 189 190 191int 192IceProtocolVersion ( 193 IceConn iceConn 194) 195{ 196 return (_IceVersions[iceConn->my_ice_version_index].major_version); 197} 198 199 200int 201IceProtocolRevision ( 202 IceConn iceConn 203) 204{ 205 return (_IceVersions[iceConn->my_ice_version_index].minor_version); 206} 207 208 209int 210IceConnectionNumber ( 211 IceConn iceConn 212) 213{ 214 return (_IceTransGetConnectionNumber (iceConn->trans_conn)); 215} 216 217 218char * 219IceConnectionString ( 220 IceConn iceConn 221) 222{ 223 if (iceConn->connection_string) 224 { 225 return strdup(iceConn->connection_string); 226 } 227 else 228 return (NULL); 229} 230 231 232unsigned long 233IceLastSentSequenceNumber ( 234 IceConn iceConn 235) 236{ 237 return (iceConn->send_sequence); 238} 239 240 241unsigned long 242IceLastReceivedSequenceNumber ( 243 IceConn iceConn 244) 245{ 246 return (iceConn->receive_sequence); 247} 248 249 250Bool 251IceSwapping ( 252 IceConn iceConn 253) 254{ 255 return (iceConn->swap); 256} 257 258 259 260/* 261 * Read "n" bytes from a connection. 262 * 263 * Return Status 0 if we detected an EXPECTED closed connection. 264 * 265 */ 266 267Status 268_IceRead ( 269 register IceConn iceConn, 270 unsigned long nbytes, 271 register char *ptr 272) 273{ 274 register unsigned long nleft; 275 276 nleft = nbytes; 277 while (nleft > 0) 278 { 279 int nread; 280 281 if (iceConn->io_ok) 282 nread = _IceTransRead (iceConn->trans_conn, ptr, (int) nleft); 283 else 284 return (1); 285 286 if (nread <= 0) 287 { 288#ifdef WIN32 289 errno = WSAGetLastError(); 290#endif 291 if (iceConn->want_to_close) 292 { 293 /* 294 * We sent a WantToClose message and now we detected that 295 * the other side closed the connection. 296 */ 297 298 _IceConnectionClosed (iceConn); /* invoke watch procs */ 299 300 return (0); 301 } 302 else 303 { 304 IceFatalIOError (iceConn); 305 return (1); 306 } 307 } 308 309 nleft -= nread; 310 ptr += nread; 311 } 312 313 return (1); 314} 315 316 317 318/* 319 * If we read a message header with a bad major or minor opcode, 320 * we need to advance to the end of the message. This way, the next 321 * message can be processed correctly. 322 */ 323 324void 325_IceReadSkip ( 326 register IceConn iceConn, 327 register unsigned long nbytes 328) 329{ 330 char temp[512]; 331 332 while (nbytes > 0) 333 { 334 unsigned long rbytes = nbytes > 512 ? 512 : nbytes; 335 336 _IceRead (iceConn, rbytes, temp); 337 nbytes -= rbytes; 338 } 339} 340 341 342 343/* 344 * Write "n" bytes to a connection. 345 */ 346 347void 348_IceWrite ( 349 register IceConn iceConn, 350 unsigned long nbytes, 351 register char *ptr 352) 353{ 354 register unsigned long nleft; 355 356 nleft = nbytes; 357 while (nleft > 0) 358 { 359 int nwritten; 360 361 if (iceConn->io_ok) 362 nwritten = _IceTransWrite (iceConn->trans_conn, ptr, (int) nleft); 363 else 364 return; 365 366 if (nwritten <= 0) 367 { 368#ifdef WIN32 369 errno = WSAGetLastError(); 370#endif 371 IceFatalIOError (iceConn); 372 return; 373 } 374 375 nleft -= nwritten; 376 ptr += nwritten; 377 } 378} 379 380 381 382void 383_IceAddOpcodeMapping ( 384 IceConn iceConn, 385 int hisOpcode, 386 int myOpcode 387) 388{ 389 if (hisOpcode <= 0 || hisOpcode > 255) 390 { 391 return; 392 } 393 else if (iceConn->process_msg_info == NULL) 394 { 395 iceConn->process_msg_info = malloc (sizeof (_IceProcessMsgInfo)); 396 iceConn->his_min_opcode = iceConn->his_max_opcode = hisOpcode; 397 } 398 else if (hisOpcode < iceConn->his_min_opcode) 399 { 400 _IceProcessMsgInfo *oldVec = iceConn->process_msg_info; 401 int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1; 402 int newsize = iceConn->his_max_opcode - hisOpcode + 1; 403 int i; 404 405 iceConn->process_msg_info = malloc ( 406 newsize * sizeof (_IceProcessMsgInfo)); 407 408 memcpy (&iceConn->process_msg_info[ 409 iceConn->his_min_opcode - hisOpcode], oldVec, 410 oldsize * sizeof (_IceProcessMsgInfo)); 411 412 free (oldVec); 413 414 for (i = hisOpcode + 1; i < iceConn->his_min_opcode; i++) 415 { 416 iceConn->process_msg_info[i - 417 iceConn->his_min_opcode].in_use = False; 418 419 iceConn->process_msg_info[i - 420 iceConn->his_min_opcode].protocol = NULL; 421 } 422 423 iceConn->his_min_opcode = hisOpcode; 424 } 425 else if (hisOpcode > iceConn->his_max_opcode) 426 { 427 _IceProcessMsgInfo *oldVec = iceConn->process_msg_info; 428 int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1; 429 int newsize = hisOpcode - iceConn->his_min_opcode + 1; 430 int i; 431 432 iceConn->process_msg_info = malloc ( 433 newsize * sizeof (_IceProcessMsgInfo)); 434 435 memcpy (iceConn->process_msg_info, oldVec, 436 oldsize * sizeof (_IceProcessMsgInfo)); 437 438 free (oldVec); 439 440 for (i = iceConn->his_max_opcode + 1; i < hisOpcode; i++) 441 { 442 iceConn->process_msg_info[i - 443 iceConn->his_min_opcode].in_use = False; 444 445 iceConn->process_msg_info[i - 446 iceConn->his_min_opcode].protocol = NULL; 447 } 448 449 iceConn->his_max_opcode = hisOpcode; 450 } 451 452 iceConn->process_msg_info[hisOpcode - 453 iceConn->his_min_opcode].in_use = True; 454 455 iceConn->process_msg_info[hisOpcode - 456 iceConn->his_min_opcode].my_opcode = myOpcode; 457 458 iceConn->process_msg_info[hisOpcode - 459 iceConn->his_min_opcode].protocol = &_IceProtocols[myOpcode - 1]; 460} 461 462 463 464char * 465IceGetPeerName (IceConn iceConn) 466{ 467 return (_IceTransGetPeerNetworkId (iceConn->trans_conn)); 468} 469 470 471char * 472_IceGetPeerName (IceConn iceConn) 473{ 474 return (IceGetPeerName(iceConn)); 475} 476