From ce4a32fe52ef09d8f5ff1dd22c001110902b60a2 Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- dcop/KDE-ICE/connect.c | 547 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 547 insertions(+) create mode 100644 dcop/KDE-ICE/connect.c (limited to 'dcop/KDE-ICE/connect.c') diff --git a/dcop/KDE-ICE/connect.c b/dcop/KDE-ICE/connect.c new file mode 100644 index 000000000..99c947b38 --- /dev/null +++ b/dcop/KDE-ICE/connect.c @@ -0,0 +1,547 @@ +/* $XConsortium: connect.c /main/32 1996/12/10 15:58:34 swick $ */ +/****************************************************************************** + + +Copyright (c) 1993 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +Author: Ralph Mor, X Consortium +******************************************************************************/ +/* $XFree86: xc/lib/ICE/connect.c,v 3.2.2.2 1998/05/19 14:21:32 dawes Exp $ */ + +#include "KDE-ICE/ICElib.h" +#include "KDE-ICE/ICElibint.h" +#include "KDE-ICE/Xtrans.h" +#include "globals.h" +#include + +static XtransConnInfo ConnectToPeer(char *networkIdsList, char **actualConnectionRet); + +#ifndef X_NOT_STDC_ENV +#define Strstr strstr +#else +static char *Strstr(s1, s2) + char *s1, *s2; +{ + int n1, n2; + + n1 = strlen(s1); + n2 = strlen(s2); + for ( ; n1 >= n2; s1++, n1--) { + if (!strncmp(s1, s2, n2)) + return s1; + } + return NULL; +} +#endif + +IceConn +IceOpenConnection (networkIdsList, context, mustAuthenticate, majorOpcodeCheck, + errorLength, errorStringRet) + +char *networkIdsList; +IcePointer context; +Bool mustAuthenticate; +int majorOpcodeCheck; +int errorLength; +char *errorStringRet; + +{ + IceConn iceConn; + int extra, i, j; + int endian; + Bool gotReply, ioErrorOccured; + unsigned long setup_sequence; + iceByteOrderMsg *pByteOrderMsg; + iceConnectionSetupMsg *pSetupMsg; + char *pData; + IceReplyWaitInfo replyWait; + _IceReply reply; + int authUsableCount; + int authUsableFlags[MAX_ICE_AUTH_NAMES]; + int authIndices[MAX_ICE_AUTH_NAMES]; + + if (errorStringRet && errorLength > 0) + *errorStringRet = '\0'; + + if (networkIdsList == NULL || *networkIdsList == '\0') + { + strncpy (errorStringRet, + "networkIdsList argument is NULL", errorLength); + return (NULL); + } + + /* + * Check to see if we can use a previously created ICE connection. + * + * If iceConn->want_to_close is True, or iceConn->free_asap is True, + * we can not use the iceConn. + * + * If 'context' is non-NULL, we will only use a previously opened ICE + * connection if the specified 'context' is equal to the context + * associated with the ICE connection, or if the context associated + * with the ICE connection is NULL. + * + * If 'majorOpcodeCheck' is non-zero, it will contain a protocol major + * opcode that we should make sure is not already active on the ICE + * connection. Some clients will want two seperate connections for the + * same protocol to the same destination client. + */ + + for (i = 0; i < _IceConnectionCount; i++) + { + char *strptr; + if ((strptr = (char *) Strstr ( + networkIdsList, _IceConnectionStrings[i])) != NULL) + { + char ch = *(strptr + strlen (_IceConnectionStrings[i])); + if (ch == ',' || ch == '\0') + { + /* + * OK, we found a connection. Make sure we can reuse it. + */ + + IceConn newIceConn = _IceConnectionObjs[i]; + + if (newIceConn->want_to_close || newIceConn->free_asap || + (context && newIceConn->context && + newIceConn->context != context)) + { + /* force a new connection to be created */ + break; + } + + if (majorOpcodeCheck) + { + for (j = newIceConn->his_min_opcode; + j <= newIceConn->his_max_opcode; j++) + { + if (newIceConn->process_msg_info[ + j - newIceConn->his_min_opcode].in_use && + newIceConn->process_msg_info[ + j - newIceConn->his_min_opcode].my_opcode == + majorOpcodeCheck) + break; + } + + if (j <= newIceConn->his_max_opcode || + (newIceConn->protosetup_to_you && + newIceConn->protosetup_to_you->my_opcode == + majorOpcodeCheck)) + { + /* force a new connection to be created */ + break; + } + } + + newIceConn->open_ref_count++; + if (context && !newIceConn->context) + newIceConn->context = context; + return (newIceConn); + } + } + } + + if ((iceConn = (IceConn) malloc (sizeof (struct _IceConn))) == NULL) + { + strncpy (errorStringRet, "Can't malloc", errorLength); + return (NULL); + } + + + /* + * Open a network connection with the peer client. + */ + + if ((iceConn->trans_conn = ConnectToPeer (networkIdsList, + &iceConn->connection_string)) == NULL) + { + free ((char *) iceConn); + strncpy (errorStringRet, "Could not open network socket", errorLength); + return (NULL); + } + + /* + * Set close-on-exec so that programs that fork() don't get confused. + */ + + _kde_IceTransSetOption (iceConn->trans_conn, TRANS_CLOSEONEXEC, 1); + + iceConn->listen_obj = NULL; + + iceConn->connection_status = IceConnectPending; + iceConn->io_ok = True; + iceConn->dispatch_level = 0; + iceConn->context = context; + iceConn->my_ice_version_index = 0; + iceConn->send_sequence = 0; + iceConn->receive_sequence = 0; + + iceConn->vendor = NULL; + iceConn->release = NULL; + iceConn->outbuf = NULL; + + iceConn->scratch = NULL; + iceConn->scratch_size = 0; + + iceConn->process_msg_info = NULL; + + iceConn->connect_to_you = NULL; + iceConn->protosetup_to_you = NULL; + + iceConn->connect_to_me = NULL; + iceConn->protosetup_to_me = NULL; + + if ((iceConn->inbuf = iceConn->inbufptr = + (char *) malloc (ICE_INBUFSIZE)) == NULL) + { + _IceFreeConnection (iceConn); + strncpy (errorStringRet, "Can't malloc", errorLength); + return (NULL); + } + memset (iceConn->inbuf, 0, ICE_INBUFSIZE); + + iceConn->inbufmax = iceConn->inbuf + ICE_INBUFSIZE; + + if ((iceConn->outbuf = iceConn->outbufptr = + (char *) malloc (ICE_OUTBUFSIZE)) == NULL) + { + _IceFreeConnection (iceConn); + strncpy (errorStringRet, "Can't malloc", errorLength); + return (NULL); + } + memset (iceConn->outbuf, 0, ICE_OUTBUFSIZE); + + iceConn->outbufmax = iceConn->outbuf + ICE_OUTBUFSIZE; + + iceConn->open_ref_count = 1; + iceConn->proto_ref_count = 0; + + iceConn->skip_want_to_close = False; + iceConn->want_to_close = False; + iceConn->free_asap = False; + + iceConn->saved_reply_waits = NULL; + iceConn->ping_waits = NULL; + + iceConn->connect_to_you = (_IceConnectToYouInfo *) malloc ( + sizeof (_IceConnectToYouInfo)); + iceConn->connect_to_you->auth_active = 0; + + /* + * Send our byte order. + */ + + IceGetHeader (iceConn, 0, ICE_ByteOrder, + SIZEOF (iceByteOrderMsg), iceByteOrderMsg, pByteOrderMsg); + + endian = 1; + if (*(char *) &endian) + pByteOrderMsg->byteOrder = IceLSBfirst; + else + pByteOrderMsg->byteOrder = IceMSBfirst; + + IceFlush (iceConn); + + + /* + * Now read the ByteOrder message from the other client. + * iceConn->swap should be set to the appropriate boolean + * value after the call to IceProcessMessages. + */ + + iceConn->waiting_for_byteorder = True; + + ioErrorOccured = False; + while (iceConn->waiting_for_byteorder == True && !ioErrorOccured) + { + ioErrorOccured = (IceProcessMessages ( + iceConn, NULL, NULL) == IceProcessMessagesIOError); + } + + if (ioErrorOccured) + { + _IceFreeConnection (iceConn); + strncpy (errorStringRet, "IO error occurred opening connection", + errorLength); + return (NULL); + } + + if (iceConn->connection_status == IceConnectRejected) + { + /* + * We failed to get the required ByteOrder message. + */ + + _IceFreeConnection (iceConn); + strncpy (errorStringRet, + "Internal error - did not receive the expected ByteOrder message", + errorLength); + return (NULL); + } + + + /* + * Determine which authentication methods are available for + * the Connection Setup authentication. + */ + + _IceGetPoValidAuthIndices ( + "ICE", iceConn->connection_string, + _IceAuthCount, _IceAuthNames, &authUsableCount, authIndices); + + for (i = 0; i < _IceAuthCount; i++) + { + authUsableFlags[i] = 0; + for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++) + authUsableFlags[i] = (authIndices[j] == i); + } + + + /* + * Now send a Connection Setup message. + */ + + extra = STRING_BYTES (IceVendorString) + STRING_BYTES (IceReleaseString); + + for (i = 0; i < _IceAuthCount; i++) + if (authUsableFlags[i]) + { + extra += STRING_BYTES (_IceAuthNames[i]); + } + + extra += (_IceVersionCount * 4); + + IceGetHeaderExtra (iceConn, 0, ICE_ConnectionSetup, + SIZEOF (iceConnectionSetupMsg), WORD64COUNT (extra), + iceConnectionSetupMsg, pSetupMsg, pData); + + setup_sequence = iceConn->send_sequence; + + pSetupMsg->versionCount = _IceVersionCount; + pSetupMsg->authCount = authUsableCount; + pSetupMsg->mustAuthenticate = mustAuthenticate; + + STORE_STRING (pData, IceVendorString); + STORE_STRING (pData, IceReleaseString); + + for (i = 0; i < _IceAuthCount; i++) + if (authUsableFlags[i]) + { + STORE_STRING (pData, _IceAuthNames[i]); + } + + for (i = 0; i < _IceVersionCount; i++) + { + STORE_CARD16 (pData, _IceVersions[i].major_version); + STORE_CARD16 (pData, _IceVersions[i].minor_version); + } + + IceFlush (iceConn); + + + /* + * Process messages until we get a Connection Reply or an Error Message. + * Authentication will take place behind the scenes. + */ + + replyWait.sequence_of_request = setup_sequence; + replyWait.major_opcode_of_request = 0; + replyWait.minor_opcode_of_request = ICE_ConnectionSetup; + replyWait.reply = (IcePointer) &reply; + + gotReply = False; + ioErrorOccured = False; + + while (!gotReply && !ioErrorOccured) + { + ioErrorOccured = (IceProcessMessages ( + iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError); + + if (ioErrorOccured) + { + strncpy (errorStringRet, "IO error occurred opening connection", + errorLength); + _IceFreeConnection (iceConn); + iceConn = NULL; + } + else if (gotReply) + { + if (reply.type == ICE_CONNECTION_REPLY) + { + if (reply.connection_reply.version_index >= _IceVersionCount) + { + strncpy (errorStringRet, + "Got a bad version index in the Connection Reply", + errorLength); + + free (reply.connection_reply.vendor); + free (reply.connection_reply.release); + _IceFreeConnection (iceConn); + iceConn = NULL; + } + else + { + iceConn->my_ice_version_index = + reply.connection_reply.version_index; + iceConn->vendor = reply.connection_reply.vendor; + iceConn->release = reply.connection_reply.release; + + _IceConnectionObjs[_IceConnectionCount] = iceConn; + _IceConnectionStrings[_IceConnectionCount] = + iceConn->connection_string; + _IceConnectionCount++; + + free ((char *) iceConn->connect_to_you); + iceConn->connect_to_you = NULL; + + iceConn->connection_status = IceConnectAccepted; + } + } + else /* reply.type == ICE_CONNECTION_ERROR */ + { + /* Connection failed */ + + strncpy (errorStringRet, reply.connection_error.error_message, + errorLength); + + free (reply.connection_error.error_message); + + _IceFreeConnection (iceConn); + iceConn = NULL; + } + } + } + + if (iceConn && _IceWatchProcs) + { +#ifdef MINIX + _kde_IceTransSetOption(iceConn->trans_conn, TRANS_NONBLOCKING, 1); +#endif + /* + * Notify the watch procedures that an iceConn was opened. + */ + + _IceConnectionOpened (iceConn); + } + + return (iceConn); +} + + + +IcePointer +IceGetConnectionContext (iceConn) + +IceConn iceConn; + +{ + return (iceConn->context); +} + + + +/* ------------------------------------------------------------------------- * + * local routines * + * ------------------------------------------------------------------------- */ + +#define ICE_CONNECTION_RETRIES 5 + + +static XtransConnInfo +ConnectToPeer (char *networkIdsList, char **actualConnectionRet) +{ + char address[256]; + char *ptr, *endptr, *delim; + int madeConnection = 0; + int len, retry; + int connect_stat; + XtransConnInfo trans_conn = NULL; + + *actualConnectionRet = NULL; + + ptr = networkIdsList; + endptr = networkIdsList + strlen (networkIdsList); + + while (ptr < endptr && !madeConnection) + { + if ((delim = (char *) strchr (ptr, ',')) == NULL) + delim = endptr; + + len = delim - ptr; + if (len > (int) sizeof(address) - 1) + len = sizeof(address) - 1; + strncpy (address, ptr, len); + address[len] = '\0'; + + ptr = delim + 1; + + for (retry = ICE_CONNECTION_RETRIES; retry >= 0; retry--) + { + if ((trans_conn = (XtransConnInfo)_kde_IceTransOpenCOTSClient (address)) == NULL) + { + break; + } + + if ((connect_stat = _kde_IceTransConnect (trans_conn, address)) < 0) + { + _kde_IceTransClose (trans_conn); + + if (connect_stat == TRANS_TRY_CONNECT_AGAIN) + { + sleep(1); + continue; + } + else + break; + } + else + { + madeConnection = 1; + break; + } + } + } + + + if (madeConnection) + { + /* + * We need to return the actual network connection string + */ + + *actualConnectionRet = (char *) malloc (strlen (address) + 1); + strcpy (*actualConnectionRet, address); + + + /* + * Return the file descriptor + */ + + return (trans_conn); + } + else + { + return (NULL); + } +} -- cgit v1.2.1