connect.c revision c5629e66
1266e564dSmrg/* $Xorg: connect.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */ 2266e564dSmrg/****************************************************************************** 3266e564dSmrg 4266e564dSmrg 5266e564dSmrgCopyright 1993, 1998 The Open Group 6266e564dSmrg 7266e564dSmrgPermission to use, copy, modify, distribute, and sell this software and its 8266e564dSmrgdocumentation for any purpose is hereby granted without fee, provided that 9266e564dSmrgthe above copyright notice appear in all copies and that both that 10266e564dSmrgcopyright notice and this permission notice appear in supporting 11266e564dSmrgdocumentation. 12266e564dSmrg 13266e564dSmrgThe above copyright notice and this permission notice shall be included in 14266e564dSmrgall copies or substantial portions of the Software. 15266e564dSmrg 16266e564dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17266e564dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18266e564dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19266e564dSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 20266e564dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21266e564dSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22266e564dSmrg 23266e564dSmrgExcept as contained in this notice, the name of The Open Group shall not be 24266e564dSmrgused in advertising or otherwise to promote the sale, use or other dealings 25266e564dSmrgin this Software without prior written authorization from The Open Group. 26266e564dSmrg 27266e564dSmrgAuthor: Ralph Mor, X Consortium 28266e564dSmrg******************************************************************************/ 29266e564dSmrg/* $XFree86: xc/lib/ICE/connect.c,v 3.9 2001/12/14 19:53:35 dawes Exp $ */ 30266e564dSmrg 31266e564dSmrg#ifdef HAVE_CONFIG_H 32266e564dSmrg#include <config.h> 33266e564dSmrg#endif 34266e564dSmrg#include <X11/ICE/ICElib.h> 35266e564dSmrg#include "ICElibint.h" 36266e564dSmrg#include <X11/Xtrans/Xtrans.h> 37266e564dSmrg#include "globals.h" 38266e564dSmrg 39266e564dSmrgstatic XtransConnInfo ConnectToPeer(char *networkIdsList, 40266e564dSmrg char **actualConnectionRet); 41266e564dSmrg 42266e564dSmrg#define Strstr strstr 43266e564dSmrg 44266e564dSmrgIceConn 45c5629e66SmrgIceOpenConnection ( 46c5629e66Smrg char *networkIdsList, 47c5629e66Smrg IcePointer context, 48c5629e66Smrg Bool mustAuthenticate, 49c5629e66Smrg int majorOpcodeCheck, 50c5629e66Smrg int errorLength, 51c5629e66Smrg char *errorStringRet 52c5629e66Smrg) 53266e564dSmrg{ 54266e564dSmrg IceConn iceConn; 55266e564dSmrg int extra, i, j; 56266e564dSmrg int endian; 57266e564dSmrg Bool gotReply, ioErrorOccured; 58266e564dSmrg unsigned long setup_sequence; 59266e564dSmrg iceByteOrderMsg *pByteOrderMsg; 60266e564dSmrg iceConnectionSetupMsg *pSetupMsg; 61266e564dSmrg char *pData; 62266e564dSmrg IceReplyWaitInfo replyWait; 63266e564dSmrg _IceReply reply; 64266e564dSmrg int authUsableCount; 65266e564dSmrg int authUsableFlags[MAX_ICE_AUTH_NAMES]; 66266e564dSmrg int authIndices[MAX_ICE_AUTH_NAMES]; 67266e564dSmrg 68266e564dSmrg if (errorStringRet && errorLength > 0) 69266e564dSmrg *errorStringRet = '\0'; 70266e564dSmrg 71266e564dSmrg if (networkIdsList == NULL || *networkIdsList == '\0') 72266e564dSmrg { 73266e564dSmrg strncpy (errorStringRet, 74266e564dSmrg "networkIdsList argument is NULL", errorLength); 75266e564dSmrg return (NULL); 76266e564dSmrg } 77266e564dSmrg 78266e564dSmrg /* 79266e564dSmrg * Check to see if we can use a previously created ICE connection. 80266e564dSmrg * 81266e564dSmrg * If iceConn->want_to_close is True, or iceConn->free_asap is True, 82266e564dSmrg * we can not use the iceConn. 83266e564dSmrg * 84266e564dSmrg * If 'context' is non-NULL, we will only use a previously opened ICE 85266e564dSmrg * connection if the specified 'context' is equal to the context 86266e564dSmrg * associated with the ICE connection, or if the context associated 87266e564dSmrg * with the ICE connection is NULL. 88266e564dSmrg * 89266e564dSmrg * If 'majorOpcodeCheck' is non-zero, it will contain a protocol major 90266e564dSmrg * opcode that we should make sure is not already active on the ICE 91266e564dSmrg * connection. Some clients will want two seperate connections for the 92266e564dSmrg * same protocol to the same destination client. 93266e564dSmrg */ 94266e564dSmrg 95266e564dSmrg for (i = 0; i < _IceConnectionCount; i++) 96266e564dSmrg { 97266e564dSmrg char *strptr; 98266e564dSmrg if ((strptr = (char *) Strstr ( 99266e564dSmrg networkIdsList, _IceConnectionStrings[i])) != NULL) 100266e564dSmrg { 101266e564dSmrg char ch = *(strptr + strlen (_IceConnectionStrings[i])); 102266e564dSmrg if (ch == ',' || ch == '\0') 103266e564dSmrg { 104266e564dSmrg /* 105266e564dSmrg * OK, we found a connection. Make sure we can reuse it. 106266e564dSmrg */ 107266e564dSmrg 108266e564dSmrg IceConn iceConn = _IceConnectionObjs[i]; 109266e564dSmrg 110266e564dSmrg if (iceConn->want_to_close || iceConn->free_asap || 111266e564dSmrg (context && iceConn->context && 112266e564dSmrg iceConn->context != context)) 113266e564dSmrg { 114266e564dSmrg /* force a new connection to be created */ 115266e564dSmrg break; 116266e564dSmrg } 117266e564dSmrg 118266e564dSmrg if (majorOpcodeCheck) 119266e564dSmrg { 120266e564dSmrg for (j = iceConn->his_min_opcode; 121266e564dSmrg j <= iceConn->his_max_opcode; j++) 122266e564dSmrg { 123266e564dSmrg if (iceConn->process_msg_info[ 124266e564dSmrg j - iceConn->his_min_opcode].in_use && 125266e564dSmrg iceConn->process_msg_info[ 126266e564dSmrg j - iceConn->his_min_opcode].my_opcode == 127266e564dSmrg majorOpcodeCheck) 128266e564dSmrg break; 129266e564dSmrg } 130266e564dSmrg 131266e564dSmrg if (j <= iceConn->his_max_opcode || 132266e564dSmrg (iceConn->protosetup_to_you && 133266e564dSmrg iceConn->protosetup_to_you->my_opcode == 134266e564dSmrg majorOpcodeCheck)) 135266e564dSmrg { 136266e564dSmrg /* force a new connection to be created */ 137266e564dSmrg break; 138266e564dSmrg } 139266e564dSmrg } 140266e564dSmrg 141266e564dSmrg iceConn->open_ref_count++; 142266e564dSmrg if (context && !iceConn->context) 143266e564dSmrg iceConn->context = context; 144266e564dSmrg return (iceConn); 145266e564dSmrg } 146266e564dSmrg } 147266e564dSmrg } 148266e564dSmrg 149266e564dSmrg if ((iceConn = (IceConn) malloc (sizeof (struct _IceConn))) == NULL) 150266e564dSmrg { 151266e564dSmrg strncpy (errorStringRet, "Can't malloc", errorLength); 152266e564dSmrg return (NULL); 153266e564dSmrg } 154266e564dSmrg 155266e564dSmrg 156266e564dSmrg /* 157266e564dSmrg * Open a network connection with the peer client. 158266e564dSmrg */ 159266e564dSmrg 160266e564dSmrg if ((iceConn->trans_conn = ConnectToPeer (networkIdsList, 161266e564dSmrg &iceConn->connection_string)) == NULL) 162266e564dSmrg { 163266e564dSmrg free ((char *) iceConn); 164266e564dSmrg strncpy (errorStringRet, "Could not open network socket", errorLength); 165266e564dSmrg return (NULL); 166266e564dSmrg } 167266e564dSmrg 168266e564dSmrg /* 169266e564dSmrg * Set close-on-exec so that programs that fork() don't get confused. 170266e564dSmrg */ 171266e564dSmrg 172266e564dSmrg _IceTransSetOption (iceConn->trans_conn, TRANS_CLOSEONEXEC, 1); 173266e564dSmrg 174266e564dSmrg iceConn->listen_obj = NULL; 175266e564dSmrg 176266e564dSmrg iceConn->connection_status = IceConnectPending; 177266e564dSmrg iceConn->io_ok = True; 178266e564dSmrg iceConn->dispatch_level = 0; 179266e564dSmrg iceConn->context = context; 180266e564dSmrg iceConn->my_ice_version_index = 0; 181266e564dSmrg iceConn->send_sequence = 0; 182266e564dSmrg iceConn->receive_sequence = 0; 183266e564dSmrg 184266e564dSmrg iceConn->vendor = NULL; 185266e564dSmrg iceConn->release = NULL; 186266e564dSmrg iceConn->outbuf = NULL; 187266e564dSmrg 188266e564dSmrg iceConn->scratch = NULL; 189266e564dSmrg iceConn->scratch_size = 0; 190266e564dSmrg 191266e564dSmrg iceConn->process_msg_info = NULL; 192266e564dSmrg 193266e564dSmrg iceConn->connect_to_you = NULL; 194266e564dSmrg iceConn->protosetup_to_you = NULL; 195266e564dSmrg 196266e564dSmrg iceConn->connect_to_me = NULL; 197266e564dSmrg iceConn->protosetup_to_me = NULL; 198266e564dSmrg 199266e564dSmrg if ((iceConn->inbuf = iceConn->inbufptr = 200266e564dSmrg (char *) malloc (ICE_INBUFSIZE)) == NULL) 201266e564dSmrg { 202266e564dSmrg _IceFreeConnection (iceConn); 203266e564dSmrg strncpy (errorStringRet, "Can't malloc", errorLength); 204266e564dSmrg return (NULL); 205266e564dSmrg } 206266e564dSmrg 207266e564dSmrg iceConn->inbufmax = iceConn->inbuf + ICE_INBUFSIZE; 208266e564dSmrg 209266e564dSmrg if ((iceConn->outbuf = iceConn->outbufptr = 210266e564dSmrg (char *) calloc (1, ICE_OUTBUFSIZE)) == NULL) 211266e564dSmrg { 212266e564dSmrg _IceFreeConnection (iceConn); 213266e564dSmrg strncpy (errorStringRet, "Can't malloc", errorLength); 214266e564dSmrg return (NULL); 215266e564dSmrg } 216266e564dSmrg 217266e564dSmrg iceConn->outbufmax = iceConn->outbuf + ICE_OUTBUFSIZE; 218266e564dSmrg 219266e564dSmrg iceConn->open_ref_count = 1; 220266e564dSmrg iceConn->proto_ref_count = 0; 221266e564dSmrg 222266e564dSmrg iceConn->skip_want_to_close = False; 223266e564dSmrg iceConn->want_to_close = False; 224266e564dSmrg iceConn->free_asap = False; 225266e564dSmrg 226266e564dSmrg iceConn->saved_reply_waits = NULL; 227266e564dSmrg iceConn->ping_waits = NULL; 228266e564dSmrg 229266e564dSmrg iceConn->connect_to_you = (_IceConnectToYouInfo *) malloc ( 230266e564dSmrg sizeof (_IceConnectToYouInfo)); 231266e564dSmrg iceConn->connect_to_you->auth_active = 0; 232266e564dSmrg 233266e564dSmrg /* 234266e564dSmrg * Send our byte order. 235266e564dSmrg */ 236266e564dSmrg 237266e564dSmrg IceGetHeader (iceConn, 0, ICE_ByteOrder, 238266e564dSmrg SIZEOF (iceByteOrderMsg), iceByteOrderMsg, pByteOrderMsg); 239266e564dSmrg 240266e564dSmrg endian = 1; 241266e564dSmrg if (*(char *) &endian) 242266e564dSmrg pByteOrderMsg->byteOrder = IceLSBfirst; 243266e564dSmrg else 244266e564dSmrg pByteOrderMsg->byteOrder = IceMSBfirst; 245266e564dSmrg 246266e564dSmrg IceFlush (iceConn); 247266e564dSmrg 248266e564dSmrg 249266e564dSmrg /* 250266e564dSmrg * Now read the ByteOrder message from the other client. 251266e564dSmrg * iceConn->swap should be set to the appropriate boolean 252266e564dSmrg * value after the call to IceProcessMessages. 253266e564dSmrg */ 254266e564dSmrg 255266e564dSmrg iceConn->waiting_for_byteorder = True; 256266e564dSmrg 257266e564dSmrg ioErrorOccured = False; 258266e564dSmrg while (iceConn->waiting_for_byteorder == True && !ioErrorOccured) 259266e564dSmrg { 260266e564dSmrg ioErrorOccured = (IceProcessMessages ( 261266e564dSmrg iceConn, NULL, NULL) == IceProcessMessagesIOError); 262266e564dSmrg } 263266e564dSmrg 264266e564dSmrg if (ioErrorOccured) 265266e564dSmrg { 266266e564dSmrg _IceFreeConnection (iceConn); 267266e564dSmrg strncpy (errorStringRet, "IO error occured opening connection", 268266e564dSmrg errorLength); 269266e564dSmrg return (NULL); 270266e564dSmrg } 271266e564dSmrg 272266e564dSmrg if (iceConn->connection_status == IceConnectRejected) 273266e564dSmrg { 274266e564dSmrg /* 275266e564dSmrg * We failed to get the required ByteOrder message. 276266e564dSmrg */ 277266e564dSmrg 278266e564dSmrg _IceFreeConnection (iceConn); 279266e564dSmrg strncpy (errorStringRet, 280266e564dSmrg "Internal error - did not receive the expected ByteOrder message", 281266e564dSmrg errorLength); 282266e564dSmrg return (NULL); 283266e564dSmrg } 284266e564dSmrg 285266e564dSmrg 286266e564dSmrg /* 287266e564dSmrg * Determine which authentication methods are available for 288266e564dSmrg * the Connection Setup authentication. 289266e564dSmrg */ 290266e564dSmrg 291266e564dSmrg _IceGetPoValidAuthIndices ( 292266e564dSmrg "ICE", iceConn->connection_string, 293266e564dSmrg _IceAuthCount, _IceAuthNames, &authUsableCount, authIndices); 294266e564dSmrg 295266e564dSmrg for (i = 0; i < _IceAuthCount; i++) 296266e564dSmrg { 297266e564dSmrg authUsableFlags[i] = 0; 298266e564dSmrg for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++) 299266e564dSmrg authUsableFlags[i] = (authIndices[j] == i); 300266e564dSmrg } 301266e564dSmrg 302266e564dSmrg 303266e564dSmrg /* 304266e564dSmrg * Now send a Connection Setup message. 305266e564dSmrg */ 306266e564dSmrg 307266e564dSmrg extra = STRING_BYTES (IceVendorString) + STRING_BYTES (IceReleaseString); 308266e564dSmrg 309266e564dSmrg for (i = 0; i < _IceAuthCount; i++) 310266e564dSmrg if (authUsableFlags[i]) 311266e564dSmrg { 312266e564dSmrg extra += STRING_BYTES (_IceAuthNames[i]); 313266e564dSmrg } 314266e564dSmrg 315266e564dSmrg extra += (_IceVersionCount * 4); 316266e564dSmrg 317266e564dSmrg IceGetHeaderExtra (iceConn, 0, ICE_ConnectionSetup, 318266e564dSmrg SIZEOF (iceConnectionSetupMsg), WORD64COUNT (extra), 319266e564dSmrg iceConnectionSetupMsg, pSetupMsg, pData); 320266e564dSmrg 321266e564dSmrg setup_sequence = iceConn->send_sequence; 322266e564dSmrg 323266e564dSmrg pSetupMsg->versionCount = _IceVersionCount; 324266e564dSmrg pSetupMsg->authCount = authUsableCount; 325266e564dSmrg pSetupMsg->mustAuthenticate = mustAuthenticate; 326266e564dSmrg 327266e564dSmrg STORE_STRING (pData, IceVendorString); 328266e564dSmrg STORE_STRING (pData, IceReleaseString); 329266e564dSmrg 330266e564dSmrg for (i = 0; i < _IceAuthCount; i++) 331266e564dSmrg if (authUsableFlags[i]) 332266e564dSmrg { 333266e564dSmrg STORE_STRING (pData, _IceAuthNames[i]); 334266e564dSmrg } 335266e564dSmrg 336266e564dSmrg for (i = 0; i < _IceVersionCount; i++) 337266e564dSmrg { 338266e564dSmrg STORE_CARD16 (pData, _IceVersions[i].major_version); 339266e564dSmrg STORE_CARD16 (pData, _IceVersions[i].minor_version); 340266e564dSmrg } 341266e564dSmrg 342266e564dSmrg IceFlush (iceConn); 343266e564dSmrg 344266e564dSmrg 345266e564dSmrg /* 346266e564dSmrg * Process messages until we get a Connection Reply or an Error Message. 347266e564dSmrg * Authentication will take place behind the scenes. 348266e564dSmrg */ 349266e564dSmrg 350266e564dSmrg replyWait.sequence_of_request = setup_sequence; 351266e564dSmrg replyWait.major_opcode_of_request = 0; 352266e564dSmrg replyWait.minor_opcode_of_request = ICE_ConnectionSetup; 353266e564dSmrg replyWait.reply = (IcePointer) &reply; 354266e564dSmrg 355266e564dSmrg gotReply = False; 356266e564dSmrg ioErrorOccured = False; 357266e564dSmrg 358266e564dSmrg while (!gotReply && !ioErrorOccured) 359266e564dSmrg { 360266e564dSmrg ioErrorOccured = (IceProcessMessages ( 361266e564dSmrg iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError); 362266e564dSmrg 363266e564dSmrg if (ioErrorOccured) 364266e564dSmrg { 365266e564dSmrg strncpy (errorStringRet, "IO error occured opening connection", 366266e564dSmrg errorLength); 367266e564dSmrg _IceFreeConnection (iceConn); 368266e564dSmrg iceConn = NULL; 369266e564dSmrg } 370266e564dSmrg else if (gotReply) 371266e564dSmrg { 372266e564dSmrg if (reply.type == ICE_CONNECTION_REPLY) 373266e564dSmrg { 374266e564dSmrg if (reply.connection_reply.version_index >= _IceVersionCount) 375266e564dSmrg { 376266e564dSmrg strncpy (errorStringRet, 377266e564dSmrg "Got a bad version index in the Connection Reply", 378266e564dSmrg errorLength); 379266e564dSmrg 380266e564dSmrg free (reply.connection_reply.vendor); 381266e564dSmrg free (reply.connection_reply.release); 382266e564dSmrg _IceFreeConnection (iceConn); 383266e564dSmrg iceConn = NULL; 384266e564dSmrg } 385266e564dSmrg else 386266e564dSmrg { 387266e564dSmrg iceConn->my_ice_version_index = 388266e564dSmrg reply.connection_reply.version_index; 389266e564dSmrg iceConn->vendor = reply.connection_reply.vendor; 390266e564dSmrg iceConn->release = reply.connection_reply.release; 391266e564dSmrg 392266e564dSmrg _IceConnectionObjs[_IceConnectionCount] = iceConn; 393266e564dSmrg _IceConnectionStrings[_IceConnectionCount] = 394266e564dSmrg iceConn->connection_string; 395266e564dSmrg _IceConnectionCount++; 396266e564dSmrg 397266e564dSmrg free ((char *) iceConn->connect_to_you); 398266e564dSmrg iceConn->connect_to_you = NULL; 399266e564dSmrg 400266e564dSmrg iceConn->connection_status = IceConnectAccepted; 401266e564dSmrg } 402266e564dSmrg } 403266e564dSmrg else /* reply.type == ICE_CONNECTION_ERROR */ 404266e564dSmrg { 405266e564dSmrg /* Connection failed */ 406266e564dSmrg 407266e564dSmrg strncpy (errorStringRet, reply.connection_error.error_message, 408266e564dSmrg errorLength); 409266e564dSmrg 410266e564dSmrg free (reply.connection_error.error_message); 411266e564dSmrg 412266e564dSmrg _IceFreeConnection (iceConn); 413266e564dSmrg iceConn = NULL; 414266e564dSmrg } 415266e564dSmrg } 416266e564dSmrg } 417266e564dSmrg 418266e564dSmrg if (iceConn && _IceWatchProcs) 419266e564dSmrg { 420266e564dSmrg /* 421266e564dSmrg * Notify the watch procedures that an iceConn was opened. 422266e564dSmrg */ 423266e564dSmrg 424266e564dSmrg _IceConnectionOpened (iceConn); 425266e564dSmrg } 426266e564dSmrg 427266e564dSmrg return (iceConn); 428266e564dSmrg} 429266e564dSmrg 430266e564dSmrg 431266e564dSmrg 432266e564dSmrgIcePointer 433c5629e66SmrgIceGetConnectionContext ( 434c5629e66Smrg IceConn iceConn 435c5629e66Smrg) 436266e564dSmrg{ 437266e564dSmrg return (iceConn->context); 438266e564dSmrg} 439266e564dSmrg 440266e564dSmrg 441266e564dSmrg 442266e564dSmrg/* ------------------------------------------------------------------------- * 443266e564dSmrg * local routines * 444266e564dSmrg * ------------------------------------------------------------------------- */ 445266e564dSmrg 446266e564dSmrg#define ICE_CONNECTION_RETRIES 5 447266e564dSmrg 448266e564dSmrg 449266e564dSmrgstatic XtransConnInfo 450266e564dSmrgConnectToPeer (char *networkIdsList, char **actualConnectionRet) 451266e564dSmrg{ 452266e564dSmrg char addrbuf[256]; 453266e564dSmrg char* address; 454266e564dSmrg char *ptr, *endptr, *delim; 455266e564dSmrg int madeConnection = 0; 456266e564dSmrg int len, retry; 457266e564dSmrg int connect_stat; 458266e564dSmrg int address_size; 459266e564dSmrg XtransConnInfo trans_conn = NULL; 460266e564dSmrg 461266e564dSmrg *actualConnectionRet = NULL; 462266e564dSmrg 463266e564dSmrg ptr = networkIdsList; 464266e564dSmrg len = strlen (networkIdsList); 465266e564dSmrg endptr = networkIdsList + len; 466266e564dSmrg 467266e564dSmrg if (len < sizeof addrbuf) 468266e564dSmrg { 469266e564dSmrg address = addrbuf; 470266e564dSmrg address_size = 256; 471266e564dSmrg } 472266e564dSmrg else 473266e564dSmrg { 474266e564dSmrg address = malloc (len + 1); 475266e564dSmrg address_size = len; 476266e564dSmrg } 477266e564dSmrg 478266e564dSmrg while (ptr < endptr && !madeConnection) 479266e564dSmrg { 480266e564dSmrg if ((delim = (char *) strchr (ptr, ',')) == NULL) 481266e564dSmrg delim = endptr; 482266e564dSmrg 483266e564dSmrg len = delim - ptr; 484266e564dSmrg if (len > address_size - 1) 485266e564dSmrg len = address_size - 1; 486266e564dSmrg strncpy (address, ptr, len); 487266e564dSmrg address[len] = '\0'; 488266e564dSmrg 489266e564dSmrg ptr = delim + 1; 490266e564dSmrg 491266e564dSmrg for (retry = ICE_CONNECTION_RETRIES; retry >= 0; retry--) 492266e564dSmrg { 493266e564dSmrg if ((trans_conn = _IceTransOpenCOTSClient (address)) == NULL) 494266e564dSmrg { 495266e564dSmrg break; 496266e564dSmrg } 497266e564dSmrg 498266e564dSmrg if ((connect_stat = _IceTransConnect (trans_conn, address)) < 0) 499266e564dSmrg { 500266e564dSmrg _IceTransClose (trans_conn); 501266e564dSmrg 502266e564dSmrg if (connect_stat == TRANS_TRY_CONNECT_AGAIN) 503266e564dSmrg { 504266e564dSmrg sleep(1); 505266e564dSmrg continue; 506266e564dSmrg } 507266e564dSmrg else 508266e564dSmrg break; 509266e564dSmrg } 510266e564dSmrg else 511266e564dSmrg { 512266e564dSmrg madeConnection = 1; 513266e564dSmrg break; 514266e564dSmrg } 515266e564dSmrg } 516266e564dSmrg } 517266e564dSmrg 518266e564dSmrg if (madeConnection) 519266e564dSmrg { 520266e564dSmrg /* 521266e564dSmrg * We need to return the actual network connection string 522266e564dSmrg */ 523266e564dSmrg 524266e564dSmrg *actualConnectionRet = strdup(address); 525266e564dSmrg 526266e564dSmrg /* 527266e564dSmrg * Return the file descriptor 528266e564dSmrg */ 529266e564dSmrg } 530266e564dSmrg else trans_conn = NULL; 531266e564dSmrg 532266e564dSmrg if (address != addrbuf) free (address); 533266e564dSmrg 534266e564dSmrg return trans_conn; 535266e564dSmrg} 536