misc.c revision 3bf3b463
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 if (iceConn->process_msg_info == NULL) { 409 iceConn->process_msg_info = oldVec; 410 return; 411 } 412 413 memcpy (&iceConn->process_msg_info[ 414 iceConn->his_min_opcode - hisOpcode], oldVec, 415 oldsize * sizeof (_IceProcessMsgInfo)); 416 417 free (oldVec); 418 419 for (i = hisOpcode + 1; i < iceConn->his_min_opcode; i++) 420 { 421 iceConn->process_msg_info[i - 422 iceConn->his_min_opcode].in_use = False; 423 424 iceConn->process_msg_info[i - 425 iceConn->his_min_opcode].protocol = NULL; 426 } 427 428 iceConn->his_min_opcode = hisOpcode; 429 } 430 else if (hisOpcode > iceConn->his_max_opcode) 431 { 432 _IceProcessMsgInfo *oldVec = iceConn->process_msg_info; 433 int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1; 434 int newsize = hisOpcode - iceConn->his_min_opcode + 1; 435 int i; 436 437 iceConn->process_msg_info = malloc ( 438 newsize * sizeof (_IceProcessMsgInfo)); 439 440 if (iceConn->process_msg_info == NULL) { 441 iceConn->process_msg_info = oldVec; 442 return; 443 } 444 445 memcpy (iceConn->process_msg_info, oldVec, 446 oldsize * sizeof (_IceProcessMsgInfo)); 447 448 free (oldVec); 449 450 for (i = iceConn->his_max_opcode + 1; i < hisOpcode; i++) 451 { 452 iceConn->process_msg_info[i - 453 iceConn->his_min_opcode].in_use = False; 454 455 iceConn->process_msg_info[i - 456 iceConn->his_min_opcode].protocol = NULL; 457 } 458 459 iceConn->his_max_opcode = hisOpcode; 460 } 461 462 iceConn->process_msg_info[hisOpcode - 463 iceConn->his_min_opcode].in_use = True; 464 465 iceConn->process_msg_info[hisOpcode - 466 iceConn->his_min_opcode].my_opcode = myOpcode; 467 468 iceConn->process_msg_info[hisOpcode - 469 iceConn->his_min_opcode].protocol = &_IceProtocols[myOpcode - 1]; 470} 471 472 473 474char * 475IceGetPeerName (IceConn iceConn) 476{ 477 return (_IceTransGetPeerNetworkId (iceConn->trans_conn)); 478} 479 480 481char * 482_IceGetPeerName (IceConn iceConn) 483{ 484 return (IceGetPeerName(iceConn)); 485} 486