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