1266e564dSmrg/****************************************************************************** 2266e564dSmrg 3266e564dSmrg 4266e564dSmrgCopyright 1993, 1998 The Open Group 5266e564dSmrg 6266e564dSmrgPermission to use, copy, modify, distribute, and sell this software and its 7266e564dSmrgdocumentation for any purpose is hereby granted without fee, provided that 8266e564dSmrgthe above copyright notice appear in all copies and that both that 9266e564dSmrgcopyright notice and this permission notice appear in supporting 10266e564dSmrgdocumentation. 11266e564dSmrg 12266e564dSmrgThe above copyright notice and this permission notice shall be included in 13266e564dSmrgall copies or substantial portions of the Software. 14266e564dSmrg 15266e564dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16266e564dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17266e564dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18266e564dSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 19266e564dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20266e564dSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21266e564dSmrg 22266e564dSmrgExcept as contained in this notice, the name of The Open Group shall not be 23266e564dSmrgused in advertising or otherwise to promote the sale, use or other dealings 24266e564dSmrgin this Software without prior written authorization from The Open Group. 25266e564dSmrg 26266e564dSmrgAuthor: Ralph Mor, X Consortium 27266e564dSmrg******************************************************************************/ 28266e564dSmrg 29266e564dSmrg#ifdef WIN32 30266e564dSmrg#define _WILLWINSOCK_ 31266e564dSmrg#endif 32266e564dSmrg#ifdef HAVE_CONFIG_H 33266e564dSmrg#include <config.h> 34266e564dSmrg#endif 35266e564dSmrg#include <X11/ICE/ICElib.h> 36266e564dSmrg#include "ICElibint.h" 37266e564dSmrg#include <X11/Xtrans/Xtrans.h> 38266e564dSmrg#include <stdio.h> 39266e564dSmrg#ifdef WIN32 40266e564dSmrg#include <X11/Xwinsock.h> 41266e564dSmrg#include <X11/Xw32defs.h> 42266e564dSmrg#endif 43266e564dSmrg 44a3129944Smrg 45266e564dSmrg/* 46266e564dSmrg * scratch buffer 47266e564dSmrg */ 48266e564dSmrg 49266e564dSmrgchar * 50c5629e66SmrgIceAllocScratch ( 51c5629e66Smrg IceConn iceConn, 52c5629e66Smrg unsigned long size 53c5629e66Smrg) 54266e564dSmrg{ 55266e564dSmrg if (!iceConn->scratch || size > iceConn->scratch_size) 56266e564dSmrg { 57a3129944Smrg free (iceConn->scratch); 58266e564dSmrg 59fb5e8d76Smrg iceConn->scratch = malloc (size); 60266e564dSmrg iceConn->scratch_size = size; 61266e564dSmrg } 62266e564dSmrg 63266e564dSmrg return (iceConn->scratch); 64266e564dSmrg} 65266e564dSmrg 661009a292Smrg/* 671009a292Smrg * Fatal IO error. First notify each protocol's IceIOErrorProc 681009a292Smrg * callback, then invoke the application IO error handler. 691009a292Smrg */ 701009a292Smrg 711009a292Smrgstatic void _X_COLD 721009a292SmrgIceFatalIOError ( 731009a292Smrg IceConn iceConn 741009a292Smrg) 751009a292Smrg{ 761009a292Smrg iceConn->io_ok = False; 771009a292Smrg 781009a292Smrg if (iceConn->connection_status == IceConnectPending) 791009a292Smrg { 801009a292Smrg /* 811009a292Smrg * Don't invoke IO error handler if we are in the 821009a292Smrg * middle of a connection setup. 831009a292Smrg */ 841009a292Smrg 851009a292Smrg return; 861009a292Smrg } 87266e564dSmrg 881009a292Smrg if (iceConn->process_msg_info) 891009a292Smrg { 901009a292Smrg for (int i = iceConn->his_min_opcode; 911009a292Smrg i <= iceConn->his_max_opcode; i++) 921009a292Smrg { 931009a292Smrg _IceProcessMsgInfo *process; 941009a292Smrg 951009a292Smrg process = &iceConn->process_msg_info[i - iceConn->his_min_opcode]; 961009a292Smrg 971009a292Smrg if ((process != NULL) && process->in_use) 981009a292Smrg { 991009a292Smrg IceIOErrorProc IOErrProc = process->accept_flag ? 1001009a292Smrg process->protocol->accept_client->io_error_proc : 1011009a292Smrg process->protocol->orig_client->io_error_proc; 1021009a292Smrg 1031009a292Smrg if (IOErrProc) 1041009a292Smrg (*IOErrProc) (iceConn); 1051009a292Smrg } 1061009a292Smrg } 1071009a292Smrg } 1081009a292Smrg 1091009a292Smrg (*_IceIOErrorHandler) (iceConn); 1101009a292Smrg return; 1111009a292Smrg} 112a3129944Smrg 113266e564dSmrg/* 114266e564dSmrg * Output/Input buffer functions 115266e564dSmrg */ 116266e564dSmrg 117266e564dSmrgint 118c5629e66SmrgIceFlush ( 119c5629e66Smrg IceConn iceConn 120c5629e66Smrg) 121266e564dSmrg{ 1221009a292Smrg /* 1231009a292Smrg * Should be impossible, unless we messed up our buffer math somewhere, 1241009a292Smrg * or one of our pointers has been corrupted. 1251009a292Smrg */ 1261009a292Smrg if (_X_UNLIKELY(iceConn->outbufptr > iceConn->outbufmax)) 1271009a292Smrg { 1281009a292Smrg IceFatalIOError (iceConn); 1291009a292Smrg return 0; 1301009a292Smrg } 1311009a292Smrg 132266e564dSmrg _IceWrite (iceConn, 133266e564dSmrg (unsigned long) (iceConn->outbufptr - iceConn->outbuf), 134266e564dSmrg iceConn->outbuf); 135266e564dSmrg 136266e564dSmrg iceConn->outbufptr = iceConn->outbuf; 137266e564dSmrg return 1; 138266e564dSmrg} 139266e564dSmrg 140266e564dSmrg 141266e564dSmrgint 142c5629e66SmrgIceGetOutBufSize ( 143c5629e66Smrg IceConn iceConn 144c5629e66Smrg) 145266e564dSmrg{ 146266e564dSmrg return (iceConn->outbufmax - iceConn->outbuf); 147266e564dSmrg} 148266e564dSmrg 149266e564dSmrg 150266e564dSmrgint 151c5629e66SmrgIceGetInBufSize ( 152c5629e66Smrg IceConn iceConn 153c5629e66Smrg) 154266e564dSmrg{ 155266e564dSmrg return (iceConn->inbufmax - iceConn->inbuf); 156266e564dSmrg} 157266e564dSmrg 158266e564dSmrg 159a3129944Smrg 160266e564dSmrg/* 161266e564dSmrg * informational functions 162266e564dSmrg */ 163266e564dSmrg 164266e564dSmrgIceConnectStatus 165c5629e66SmrgIceConnectionStatus ( 166c5629e66Smrg IceConn iceConn 167c5629e66Smrg) 168266e564dSmrg{ 169266e564dSmrg return (iceConn->connection_status); 170266e564dSmrg} 171266e564dSmrg 172266e564dSmrg 173266e564dSmrgchar * 174c5629e66SmrgIceVendor ( 175c5629e66Smrg IceConn iceConn 176c5629e66Smrg) 177266e564dSmrg{ 178266e564dSmrg return strdup(iceConn->vendor); 179266e564dSmrg} 180266e564dSmrg 181266e564dSmrg 182266e564dSmrgchar * 183c5629e66SmrgIceRelease ( 184c5629e66Smrg IceConn iceConn 185c5629e66Smrg) 186266e564dSmrg{ 187266e564dSmrg return strdup(iceConn->release); 188266e564dSmrg} 189266e564dSmrg 190266e564dSmrg 191266e564dSmrgint 192c5629e66SmrgIceProtocolVersion ( 193c5629e66Smrg IceConn iceConn 194c5629e66Smrg) 195266e564dSmrg{ 196266e564dSmrg return (_IceVersions[iceConn->my_ice_version_index].major_version); 197266e564dSmrg} 198266e564dSmrg 199266e564dSmrg 200266e564dSmrgint 201c5629e66SmrgIceProtocolRevision ( 202c5629e66Smrg IceConn iceConn 203c5629e66Smrg) 204266e564dSmrg{ 205266e564dSmrg return (_IceVersions[iceConn->my_ice_version_index].minor_version); 206266e564dSmrg} 207266e564dSmrg 208266e564dSmrg 209266e564dSmrgint 210c5629e66SmrgIceConnectionNumber ( 211c5629e66Smrg IceConn iceConn 212c5629e66Smrg) 213266e564dSmrg{ 214266e564dSmrg return (_IceTransGetConnectionNumber (iceConn->trans_conn)); 215266e564dSmrg} 216266e564dSmrg 217266e564dSmrg 218266e564dSmrgchar * 219c5629e66SmrgIceConnectionString ( 220c5629e66Smrg IceConn iceConn 221c5629e66Smrg) 222266e564dSmrg{ 223266e564dSmrg if (iceConn->connection_string) 224266e564dSmrg { 225266e564dSmrg return strdup(iceConn->connection_string); 226266e564dSmrg } 227266e564dSmrg else 228266e564dSmrg return (NULL); 229266e564dSmrg} 230266e564dSmrg 231266e564dSmrg 232266e564dSmrgunsigned long 233c5629e66SmrgIceLastSentSequenceNumber ( 234c5629e66Smrg IceConn iceConn 235c5629e66Smrg) 236266e564dSmrg{ 237266e564dSmrg return (iceConn->send_sequence); 238266e564dSmrg} 239266e564dSmrg 240266e564dSmrg 241266e564dSmrgunsigned long 242c5629e66SmrgIceLastReceivedSequenceNumber ( 243c5629e66Smrg IceConn iceConn 244c5629e66Smrg) 245266e564dSmrg{ 246266e564dSmrg return (iceConn->receive_sequence); 247266e564dSmrg} 248266e564dSmrg 249266e564dSmrg 250266e564dSmrgBool 251c5629e66SmrgIceSwapping ( 252c5629e66Smrg IceConn iceConn 253c5629e66Smrg) 254266e564dSmrg{ 255266e564dSmrg return (iceConn->swap); 256266e564dSmrg} 257266e564dSmrg 258266e564dSmrg 259a3129944Smrg 260266e564dSmrg/* 261266e564dSmrg * Read "n" bytes from a connection. 262266e564dSmrg * 263266e564dSmrg * Return Status 0 if we detected an EXPECTED closed connection. 264266e564dSmrg * 265266e564dSmrg */ 266266e564dSmrg 267266e564dSmrgStatus 268c5629e66Smrg_IceRead ( 269c5629e66Smrg register IceConn iceConn, 270c5629e66Smrg unsigned long nbytes, 271c5629e66Smrg register char *ptr 272c5629e66Smrg) 273266e564dSmrg{ 274266e564dSmrg register unsigned long nleft; 275266e564dSmrg 276266e564dSmrg nleft = nbytes; 277266e564dSmrg while (nleft > 0) 278266e564dSmrg { 279266e564dSmrg int nread; 280266e564dSmrg 281266e564dSmrg if (iceConn->io_ok) 282266e564dSmrg nread = _IceTransRead (iceConn->trans_conn, ptr, (int) nleft); 283266e564dSmrg else 284266e564dSmrg return (1); 285266e564dSmrg 286266e564dSmrg if (nread <= 0) 287266e564dSmrg { 288266e564dSmrg#ifdef WIN32 289266e564dSmrg errno = WSAGetLastError(); 290266e564dSmrg#endif 291266e564dSmrg if (iceConn->want_to_close) 292266e564dSmrg { 293266e564dSmrg /* 294266e564dSmrg * We sent a WantToClose message and now we detected that 295266e564dSmrg * the other side closed the connection. 296266e564dSmrg */ 297266e564dSmrg 298266e564dSmrg _IceConnectionClosed (iceConn); /* invoke watch procs */ 299266e564dSmrg 300266e564dSmrg return (0); 301266e564dSmrg } 3029ef0b394Smrg else 303266e564dSmrg { 3041009a292Smrg IceFatalIOError (iceConn); 305266e564dSmrg return (1); 306266e564dSmrg } 307266e564dSmrg } 308266e564dSmrg 309266e564dSmrg nleft -= nread; 310266e564dSmrg ptr += nread; 311266e564dSmrg } 312266e564dSmrg 313266e564dSmrg return (1); 314266e564dSmrg} 315266e564dSmrg 316266e564dSmrg 317a3129944Smrg 318266e564dSmrg/* 319266e564dSmrg * If we read a message header with a bad major or minor opcode, 320266e564dSmrg * we need to advance to the end of the message. This way, the next 321266e564dSmrg * message can be processed correctly. 322266e564dSmrg */ 323266e564dSmrg 324266e564dSmrgvoid 325c5629e66Smrg_IceReadSkip ( 326c5629e66Smrg register IceConn iceConn, 327c5629e66Smrg register unsigned long nbytes 328c5629e66Smrg) 329266e564dSmrg{ 330266e564dSmrg char temp[512]; 331266e564dSmrg 332266e564dSmrg while (nbytes > 0) 333266e564dSmrg { 334266e564dSmrg unsigned long rbytes = nbytes > 512 ? 512 : nbytes; 335266e564dSmrg 336266e564dSmrg _IceRead (iceConn, rbytes, temp); 337266e564dSmrg nbytes -= rbytes; 338266e564dSmrg } 339266e564dSmrg} 340266e564dSmrg 341266e564dSmrg 342a3129944Smrg 343266e564dSmrg/* 344266e564dSmrg * Write "n" bytes to a connection. 345266e564dSmrg */ 346266e564dSmrg 347266e564dSmrgvoid 348c5629e66Smrg_IceWrite ( 349c5629e66Smrg register IceConn iceConn, 350c5629e66Smrg unsigned long nbytes, 351c5629e66Smrg register char *ptr 352c5629e66Smrg) 353266e564dSmrg{ 354266e564dSmrg register unsigned long nleft; 355266e564dSmrg 356266e564dSmrg nleft = nbytes; 357266e564dSmrg while (nleft > 0) 358266e564dSmrg { 359266e564dSmrg int nwritten; 360266e564dSmrg 361266e564dSmrg if (iceConn->io_ok) 362266e564dSmrg nwritten = _IceTransWrite (iceConn->trans_conn, ptr, (int) nleft); 363266e564dSmrg else 364266e564dSmrg return; 365266e564dSmrg 366266e564dSmrg if (nwritten <= 0) 367266e564dSmrg { 368266e564dSmrg#ifdef WIN32 369266e564dSmrg errno = WSAGetLastError(); 370266e564dSmrg#endif 3711009a292Smrg IceFatalIOError (iceConn); 372266e564dSmrg return; 373266e564dSmrg } 374266e564dSmrg 375266e564dSmrg nleft -= nwritten; 376266e564dSmrg ptr += nwritten; 377266e564dSmrg } 378266e564dSmrg} 379266e564dSmrg 380266e564dSmrg 381a3129944Smrg 382266e564dSmrgvoid 383c5629e66Smrg_IceAddOpcodeMapping ( 384c5629e66Smrg IceConn iceConn, 385c5629e66Smrg int hisOpcode, 386c5629e66Smrg int myOpcode 387c5629e66Smrg) 388266e564dSmrg{ 389266e564dSmrg if (hisOpcode <= 0 || hisOpcode > 255) 390266e564dSmrg { 391266e564dSmrg return; 392266e564dSmrg } 393266e564dSmrg else if (iceConn->process_msg_info == NULL) 394266e564dSmrg { 395fb5e8d76Smrg iceConn->process_msg_info = malloc (sizeof (_IceProcessMsgInfo)); 396266e564dSmrg iceConn->his_min_opcode = iceConn->his_max_opcode = hisOpcode; 397266e564dSmrg } 398266e564dSmrg else if (hisOpcode < iceConn->his_min_opcode) 399266e564dSmrg { 400266e564dSmrg _IceProcessMsgInfo *oldVec = iceConn->process_msg_info; 401266e564dSmrg int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1; 402266e564dSmrg int newsize = iceConn->his_max_opcode - hisOpcode + 1; 403266e564dSmrg int i; 404266e564dSmrg 405fb5e8d76Smrg iceConn->process_msg_info = malloc ( 406266e564dSmrg newsize * sizeof (_IceProcessMsgInfo)); 407266e564dSmrg 4083bf3b463Smrg if (iceConn->process_msg_info == NULL) { 4093bf3b463Smrg iceConn->process_msg_info = oldVec; 4103bf3b463Smrg return; 4113bf3b463Smrg } 4123bf3b463Smrg 413266e564dSmrg memcpy (&iceConn->process_msg_info[ 414266e564dSmrg iceConn->his_min_opcode - hisOpcode], oldVec, 415266e564dSmrg oldsize * sizeof (_IceProcessMsgInfo)); 416266e564dSmrg 417fb5e8d76Smrg free (oldVec); 418266e564dSmrg 419266e564dSmrg for (i = hisOpcode + 1; i < iceConn->his_min_opcode; i++) 420266e564dSmrg { 421266e564dSmrg iceConn->process_msg_info[i - 422266e564dSmrg iceConn->his_min_opcode].in_use = False; 423266e564dSmrg 424266e564dSmrg iceConn->process_msg_info[i - 425266e564dSmrg iceConn->his_min_opcode].protocol = NULL; 426266e564dSmrg } 427266e564dSmrg 428266e564dSmrg iceConn->his_min_opcode = hisOpcode; 429266e564dSmrg } 430266e564dSmrg else if (hisOpcode > iceConn->his_max_opcode) 431266e564dSmrg { 432266e564dSmrg _IceProcessMsgInfo *oldVec = iceConn->process_msg_info; 433266e564dSmrg int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1; 434266e564dSmrg int newsize = hisOpcode - iceConn->his_min_opcode + 1; 435266e564dSmrg int i; 436266e564dSmrg 437fb5e8d76Smrg iceConn->process_msg_info = malloc ( 438266e564dSmrg newsize * sizeof (_IceProcessMsgInfo)); 439266e564dSmrg 4403bf3b463Smrg if (iceConn->process_msg_info == NULL) { 4413bf3b463Smrg iceConn->process_msg_info = oldVec; 4423bf3b463Smrg return; 4433bf3b463Smrg } 4443bf3b463Smrg 445266e564dSmrg memcpy (iceConn->process_msg_info, oldVec, 446266e564dSmrg oldsize * sizeof (_IceProcessMsgInfo)); 447266e564dSmrg 448fb5e8d76Smrg free (oldVec); 449266e564dSmrg 450266e564dSmrg for (i = iceConn->his_max_opcode + 1; i < hisOpcode; i++) 451266e564dSmrg { 452266e564dSmrg iceConn->process_msg_info[i - 453266e564dSmrg iceConn->his_min_opcode].in_use = False; 454266e564dSmrg 455266e564dSmrg iceConn->process_msg_info[i - 456266e564dSmrg iceConn->his_min_opcode].protocol = NULL; 457266e564dSmrg } 458266e564dSmrg 459266e564dSmrg iceConn->his_max_opcode = hisOpcode; 460266e564dSmrg } 461266e564dSmrg 462266e564dSmrg iceConn->process_msg_info[hisOpcode - 463266e564dSmrg iceConn->his_min_opcode].in_use = True; 464266e564dSmrg 465266e564dSmrg iceConn->process_msg_info[hisOpcode - 466266e564dSmrg iceConn->his_min_opcode].my_opcode = myOpcode; 467266e564dSmrg 468266e564dSmrg iceConn->process_msg_info[hisOpcode - 469266e564dSmrg iceConn->his_min_opcode].protocol = &_IceProtocols[myOpcode - 1]; 470266e564dSmrg} 471266e564dSmrg 472266e564dSmrg 473a3129944Smrg 474266e564dSmrgchar * 475266e564dSmrgIceGetPeerName (IceConn iceConn) 476266e564dSmrg{ 477266e564dSmrg return (_IceTransGetPeerNetworkId (iceConn->trans_conn)); 478266e564dSmrg} 479266e564dSmrg 480a3129944Smrg 481266e564dSmrgchar * 482266e564dSmrg_IceGetPeerName (IceConn iceConn) 483266e564dSmrg{ 484266e564dSmrg return (IceGetPeerName(iceConn)); 485266e564dSmrg} 486