summaryrefslogtreecommitdiffstats
path: root/dcop/KDE-ICE/connect.c
diff options
context:
space:
mode:
Diffstat (limited to 'dcop/KDE-ICE/connect.c')
-rw-r--r--dcop/KDE-ICE/connect.c547
1 files changed, 547 insertions, 0 deletions
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 <string.h>
+
+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);
+ }
+}