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