Exemplo n.º 1
0
Arquivo: misc.c Projeto: aosm/X11libs
IceWriteData32 (
	IceConn 	iceConn,
	unsigned long  	nbytes,
	int	 	*data
)
{
    int numLongs = nbytes / 4;
    int index = 0;

    while (index < numLongs)
    {
	int spaceLeft, count, i;
	int longsLeft = numLongs - index;

	spaceLeft = iceConn->outbufmax - iceConn->outbufptr - 1;

	if (spaceLeft < 4)
	{
	    IceFlush (iceConn);
	    spaceLeft = iceConn->outbufmax - iceConn->outbufptr - 1;
	}

	count = (longsLeft < spaceLeft / 4) ? longsLeft : spaceLeft / 4;

	for (i = 0; i < count; i++)
	    STORE_CARD32 (iceConn->outbufptr, data[index++]);
    }
}
Exemplo n.º 2
0
Status
SmcRequestSaveYourselfPhase2(SmcConn smcConn,
			     SmcSaveYourselfPhase2Proc saveYourselfPhase2Proc,
			     SmPointer clientData)
{
    IceConn		iceConn = smcConn->iceConn;
    _SmcPhase2Wait 	*wait;

    if (smcConn->phase2_wait)
	wait = smcConn->phase2_wait;
    else
    {
	if ((wait = (_SmcPhase2Wait *) malloc (
	    sizeof (_SmcPhase2Wait))) == NULL)
	{
	    return (0);
	}
    }

    wait->phase2_proc = saveYourselfPhase2Proc;
    wait->client_data = clientData;

    smcConn->phase2_wait = wait;

    IceSimpleMessage (iceConn, _SmcOpcode, SM_SaveYourselfPhase2Request);
    IceFlush (iceConn);

    return (1);
}
Exemplo n.º 3
0
Status
SmcGetProperties(SmcConn smcConn, SmcPropReplyProc propReplyProc,
		 SmPointer clientData)
{
    IceConn		iceConn = smcConn->iceConn;
    _SmcPropReplyWait 	*wait, *ptr;

    if ((wait = (_SmcPropReplyWait *) malloc (
	sizeof (_SmcPropReplyWait))) == NULL)
    {
	return (0);
    }

    wait->prop_reply_proc = propReplyProc;
    wait->client_data = clientData;
    wait->next = NULL;

    ptr = smcConn->prop_reply_waits;
    while (ptr && ptr->next)
	ptr = ptr->next;

    if (ptr == NULL)
	smcConn->prop_reply_waits = wait;
    else
	ptr->next = wait;

    IceSimpleMessage (iceConn, _SmcOpcode, SM_GetProperties);
    IceFlush (iceConn);

    return (1);
}
Exemplo n.º 4
0
Status
IcePing (
	IceConn		 iceConn,
	IcePingReplyProc pingReplyProc,
	IcePointer	 clientData
)
{
    _IcePingWait *newping = malloc (sizeof (_IcePingWait));
    _IcePingWait *ptr = iceConn->ping_waits;

    if (newping == NULL)
	return (0);

    newping->ping_reply_proc = pingReplyProc;
    newping->client_data = clientData;
    newping->next = NULL;

    while (ptr && ptr->next)
	ptr = ptr->next;

    if (ptr == NULL)
	iceConn->ping_waits = newping;
    else
	ptr->next = newping;

    IceSimpleMessage (iceConn, 0, ICE_Ping);
    IceFlush (iceConn);

    return (1);
}
Exemplo n.º 5
0
void
SmcDeleteProperties(SmcConn smcConn, int numProps, char **propNames)
{
    IceConn			iceConn = smcConn->iceConn;
    smDeletePropertiesMsg 	*pMsg;
    char 			*pData;
    int				extra, i;

    extra = 8;

    for (i = 0; i < numProps; i++)
	extra += ARRAY8_BYTES (strlen (propNames[i]));

    IceGetHeaderExtra (iceConn, _SmcOpcode, SM_DeleteProperties,
	SIZEOF (smDeletePropertiesMsg), WORD64COUNT (extra),
	smDeletePropertiesMsg, pMsg, pData);

    STORE_CARD32 (pData, numProps);
    pData += 4;

    for (i = 0; i < numProps; i++)
	STORE_ARRAY8 (pData, strlen (propNames[i]), propNames[i]); 

    IceFlush (iceConn);
}
Exemplo n.º 6
0
Arquivo: misc.c Projeto: aosm/X11libs
IceWriteData16 (
	IceConn 	iceConn,
	unsigned long 	nbytes,
	short  		*data
)
{
    int numShorts = nbytes / 2;
    int index = 0;

    while (index < numShorts)
    {
	int spaceLeft, count, i;
	int shortsLeft = numShorts - index;

	spaceLeft = iceConn->outbufmax - iceConn->outbufptr - 1;

	if (spaceLeft < 2)
	{
	    IceFlush (iceConn);
	    spaceLeft = iceConn->outbufmax - iceConn->outbufptr - 1;
	}

	count = (shortsLeft < spaceLeft / 2) ? shortsLeft : spaceLeft / 2;

	for (i = 0; i < count; i++)
	    STORE_CARD16 (iceConn->outbufptr, data[index++]);
    }
}
Exemplo n.º 7
0
bool KRequestShutdownHelper::requestShutdown( ShutdownConfirm confirm )
    {
#if HAVE_X11
    if( conn == NULL )
        return false;
    SmcRequestSaveYourself( conn, SmSaveBoth, True, SmInteractStyleAny,
        confirm == ShutdownConfirmNo, True );
    // flush the request
    IceFlush(SmcGetIceConnection(conn));
#endif    
    return true;
    }
Exemplo n.º 8
0
void
SmcSaveYourselfDone(SmcConn smcConn, Bool success)
{
    IceConn			iceConn = smcConn->iceConn;
    smSaveYourselfDoneMsg	*pMsg;

    IceGetHeader (iceConn, _SmcOpcode, SM_SaveYourselfDone,
	SIZEOF (smSaveYourselfDoneMsg), smSaveYourselfDoneMsg, pMsg);

    pMsg->success = success;

    IceFlush (iceConn);
}
Exemplo n.º 9
0
void
SmcInteractDone(SmcConn smcConn, Bool cancelShutdown)
{
    IceConn		iceConn = smcConn->iceConn;
    smInteractDoneMsg	*pMsg;

    IceGetHeader (iceConn, _SmcOpcode, SM_InteractDone,
	SIZEOF (smInteractDoneMsg), smInteractDoneMsg, pMsg);

    pMsg->cancelShutdown = cancelShutdown;

    IceFlush (iceConn);
}
Exemplo n.º 10
0
void
SmcRequestSaveYourself(SmcConn smcConn, int saveType, Bool shutdown,
		       int interactStyle, Bool fast, Bool global)
{
    IceConn			iceConn = smcConn->iceConn;
    smSaveYourselfRequestMsg	*pMsg;

    IceGetHeader (iceConn, _SmcOpcode, SM_SaveYourselfRequest,
	SIZEOF (smSaveYourselfRequestMsg), smSaveYourselfRequestMsg, pMsg);

    pMsg->saveType = saveType;
    pMsg->shutdown = shutdown;
    pMsg->interactStyle = interactStyle;
    pMsg->fast = fast;
    pMsg->global = global;

    IceFlush (iceConn);
}
Exemplo n.º 11
0
void
SmcSetProperties(SmcConn smcConn, int numProps, SmProp **props)
{
    IceConn		iceConn = smcConn->iceConn;
    smSetPropertiesMsg	*pMsg;
    char		*pBuf;
    char		*pStart;
    int			bytes;

    IceGetHeader (iceConn, _SmcOpcode, SM_SetProperties,
	SIZEOF (smSetPropertiesMsg), smSetPropertiesMsg, pMsg);

    LISTOF_PROP_BYTES (numProps, props, bytes);
    pMsg->length += WORD64COUNT (bytes);

    pBuf = pStart = IceAllocScratch (iceConn, bytes);
    memset(pStart, 0, bytes);

    STORE_LISTOF_PROPERTY (pBuf, numProps, props);

    IceWriteData (iceConn, bytes, pStart);
    IceFlush (iceConn);
}
Exemplo n.º 12
0
Status
SmcInteractRequest(SmcConn smcConn, int dialogType,
		   SmcInteractProc interactProc, SmPointer clientData)
{
    IceConn			iceConn = smcConn->iceConn;
    smInteractRequestMsg	*pMsg;
    _SmcInteractWait 		*wait, *ptr;

    if ((wait = (_SmcInteractWait *) malloc (
	sizeof (_SmcInteractWait))) == NULL)
    {
	return (0);
    }

    wait->interact_proc = interactProc;
    wait->client_data = clientData;
    wait->next = NULL;

    ptr = smcConn->interact_waits;
    while (ptr && ptr->next)
	ptr = ptr->next;

    if (ptr == NULL)
	smcConn->interact_waits = wait;
    else
	ptr->next = wait;

    IceGetHeader (iceConn, _SmcOpcode, SM_InteractRequest,
	SIZEOF (smInteractRequestMsg), smInteractRequestMsg, pMsg);

    pMsg->dialogType = dialogType;

    IceFlush (iceConn);

    return (1);
}
Exemplo n.º 13
0
SmcConn
SmcOpenConnection(char *networkIdsList, SmPointer context,
		  int xsmpMajorRev, int xsmpMinorRev,
		  unsigned long mask, SmcCallbacks *callbacks,
		  char *previousId, char **clientIdRet,
		  int errorLength, char *errorStringRet)
{
    SmcConn			smcConn;
    IceConn			iceConn;
    char 			*ids;
    IceProtocolSetupStatus	setupstat;
    int				majorVersion;
    int				minorVersion;
    char			*vendor = NULL;
    char			*release = NULL;
    smRegisterClientMsg 	*pMsg;
    char 			*pData;
    int				extra, len;
    IceReplyWaitInfo		replyWait;
    _SmcRegisterClientReply	reply;
    Bool			gotReply, ioErrorOccured;

    const char *auth_names[] = {"MIT-MAGIC-COOKIE-1"};
    IcePoAuthProc auth_procs[] = {_IcePoMagicCookie1Proc};
    int auth_count = 1;

    IcePoVersionRec versions[] = {
        {SmProtoMajor, SmProtoMinor, _SmcProcessMessage}
    };
    int version_count = 1;


    *clientIdRet = NULL;

    if (errorStringRet && errorLength > 0)
	*errorStringRet = '\0';

    if (!_SmcOpcode)
    {
	/*
	 * For now, there is only one version of XSMP, so we don't
	 * have to check {xsmpMajorRev, xsmpMinorRev}.  In the future,
	 * we will check against versions and generate the list
	 * of versions the application actually supports.
	 */

	if ((_SmcOpcode = IceRegisterForProtocolSetup ("XSMP",
	    SmVendorString, SmReleaseString, version_count, versions,
            auth_count, auth_names, auth_procs, NULL)) < 0)
	{
	    if (errorStringRet && errorLength > 0) {
		strncpy (errorStringRet,
			 "Could not register XSMP protocol with ICE",
			 errorLength);
		errorStringRet[errorLength - 1] = '\0';
	    }

	    return (NULL);
	}
    }

    if (networkIdsList == NULL || *networkIdsList == '\0')
    {
	if ((ids = (char *) getenv ("SESSION_MANAGER")) == NULL)
	{
	    if (errorStringRet && errorLength > 0) {
		strncpy (errorStringRet,
			 "SESSION_MANAGER environment variable not defined",
			 errorLength);
		errorStringRet[errorLength - 1] = '\0';
	    }
	    return (NULL);
	}
    }
    else
    {
	ids = networkIdsList;
    }

    if ((iceConn = IceOpenConnection (
	ids, context, 0, _SmcOpcode, errorLength, errorStringRet)) == NULL)
    {
	return (NULL);
    }

    if ((smcConn = (SmcConn) malloc (sizeof (struct _SmcConn))) == NULL)
    {
	if (errorStringRet && errorLength > 0) {
	    strncpy (errorStringRet, "Can't malloc", errorLength);
	    errorStringRet[errorLength - 1] = '\0';
	}
	IceCloseConnection (iceConn);
	return (NULL);
    }

    setupstat = IceProtocolSetup (iceConn, _SmcOpcode,
	(IcePointer) smcConn,
	False /* mustAuthenticate */,
	&majorVersion, &minorVersion,
	&vendor, &release, errorLength, errorStringRet);

    if (setupstat == IceProtocolSetupFailure ||
	setupstat == IceProtocolSetupIOError)
    {
	IceCloseConnection (iceConn);
	free ((char *) smcConn);
	return (NULL);
    }
    else if (setupstat == IceProtocolAlreadyActive)
    {
	/*
	 * This case should never happen, because when we called
	 * IceOpenConnection, we required that the ICE connection
	 * may not already have XSMP active on it.
	 */

	free ((char *) smcConn);
	if (errorStringRet && errorLength > 0) {
	    strncpy (errorStringRet, "Internal error in IceOpenConnection",
		     errorLength);
	    errorStringRet[errorLength - 1] = '\0';
	}
	return (NULL);
    }

    smcConn->iceConn = iceConn;
    smcConn->proto_major_version = majorVersion;
    smcConn->proto_minor_version = minorVersion;
    smcConn->vendor = vendor;
    smcConn->release = release;
    smcConn->client_id = NULL;

    bzero ((char *) &smcConn->callbacks, sizeof (SmcCallbacks));
    set_callbacks (smcConn, mask, callbacks);

    smcConn->interact_waits = NULL;
    smcConn->phase2_wait = NULL;
    smcConn->prop_reply_waits = NULL;

    smcConn->save_yourself_in_progress = False;
    smcConn->shutdown_in_progress = False;


    /*
     * Now register the client
     */

    if (!previousId)
	previousId = "";
    len = strlen (previousId);
    extra = ARRAY8_BYTES (len);

    IceGetHeaderExtra (iceConn, _SmcOpcode, SM_RegisterClient,
	SIZEOF (smRegisterClientMsg), WORD64COUNT (extra),
	smRegisterClientMsg, pMsg, pData);

    STORE_ARRAY8 (pData, len, previousId);

    IceFlush (iceConn);

    replyWait.sequence_of_request = IceLastSentSequenceNumber (iceConn);
    replyWait.major_opcode_of_request = _SmcOpcode;
    replyWait.minor_opcode_of_request = SM_RegisterClient;
    replyWait.reply = (IcePointer) &reply;

    gotReply = False;
    ioErrorOccured = False;

    while (!gotReply && !ioErrorOccured)
    {
	ioErrorOccured = (IceProcessMessages (
	    iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError);

	if (ioErrorOccured)
	{
	    if (errorStringRet && errorLength > 0) {
		strncpy (errorStringRet, "IO error occured opening connection",
			 errorLength);
		errorStringRet[errorLength - 1] = '\0';
	    }
	    free (smcConn->vendor);
	    free (smcConn->release);
	    free ((char *) smcConn);

	    return (NULL);
	}
	else if (gotReply)
	{
	    if (reply.status == 1)
	    {
		/*
		 * The client successfully registered.
		 */

		*clientIdRet = reply.client_id;

		smcConn->client_id = (char *) malloc (
		    strlen (*clientIdRet) + 1);

		strcpy (smcConn->client_id, *clientIdRet);
	    }
	    else
	    {
		/*
		 * Could not register the client because the previous ID
		 * was bad.  So now we register the client with the
		 * previous ID set to NULL.
		 */

		extra = ARRAY8_BYTES (0);

		IceGetHeaderExtra (iceConn, _SmcOpcode, SM_RegisterClient,
		    SIZEOF (smRegisterClientMsg), WORD64COUNT (extra),
		    smRegisterClientMsg, pMsg, pData);

		STORE_ARRAY8 (pData, 0, "");

		IceFlush (iceConn);

		replyWait.sequence_of_request =
		    IceLastSentSequenceNumber (iceConn);

		gotReply = False;
	    }
	}
    }

    return (smcConn);
}
Exemplo n.º 14
0
void FWPprocessMessages(
    IceConn iceConn, 
    IcePointer * client_data,
    int opcode,
    unsigned long length,
    Bool swap)
{
  switch (opcode)
  { 
    /*
     * this is really the only opcode we care about -- the one
     * which indicates an XFindProxy request for a connection
     * to a specified server
     */
    case PM_GetProxyAddr:
    {
      pmGetProxyAddrMsg       	*pMsg;
      char                      *pData, *pStart;
      char                      *serviceName = NULL, *serverAddress = NULL;
      char                      *hostAddress = NULL, *startOptions = NULL;
      char                      *authName = NULL, *authData = NULL;
      int                       authLen;
      struct clientDataStruct * program_data; 
      char *			listen_port_string;
      int			pm_send_msg_len;
      pmGetProxyAddrReplyMsg *	pReply;
      char *			pReplyData;
      struct hostent * 		hostptr;
      struct sockaddr_in	server_sockaddr_in;
      struct sockaddr_in	dummy_sockaddr_in;
      char *			server_name_base;
      char *			config_failure = "unrecognized server or permission denied";
      char *			tmp_str;
      int			rule_number = -1;
      char *			colon;
      char *			tmpAddress = NULL;

      /*
       * this is where we need and get access to that client data we
       * went through such contortions to set up earlier!
       */
      program_data = (struct clientDataStruct *) client_data;
      /*
       * initial check on expected message size
       */ 
      CHECK_AT_LEAST_SIZE (iceConn, global_data.major_opcode, opcode,
          length, SIZEOF (pmGetProxyAddrMsg), IceFatalToProtocol);

      IceReadCompleteMessage (iceConn, SIZEOF (pmGetProxyAddrMsg),
          pmGetProxyAddrMsg, pMsg, pStart);

      if (!IceValidIO (iceConn))
      {
        IceDisposeCompleteMessage (iceConn, pStart);
        return;
      }

      authLen = swap ? lswaps (pMsg->authLen) : pMsg->authLen;

      pData = pStart;

      SKIP_STRING (pData, swap);      /* proxy-service */
      SKIP_STRING (pData, swap);      /* server-address */
      SKIP_STRING (pData, swap);      /* host-address */
      SKIP_STRING (pData, swap);      /* start-options */
      if (authLen > 0)
      {
        SKIP_STRING (pData, swap);              /* auth-name */
        pData += (authLen +  PAD64 (authLen));  /* auth-data */
      }
      /*
       * now a detailed check on message size
       */
      CHECK_COMPLETE_SIZE (iceConn, global_data.major_opcode, opcode,
         length, pData - pStart + SIZEOF (pmGetProxyAddrMsg),
         pStart, IceFatalToProtocol);

      pData = pStart;
      /*
       * extract message data, based on known characteristics
       * of this message type
       */
      EXTRACT_STRING (pData, swap, serviceName);
      EXTRACT_STRING (pData, swap, serverAddress);
      EXTRACT_STRING (pData, swap, hostAddress);
      EXTRACT_STRING (pData, swap, startOptions);
      if (authLen > 0)
      {
        EXTRACT_STRING (pData, swap, authName);
        authData = (char *) malloc (authLen);
        memcpy (authData, pData, authLen);
      }
#ifdef DEBUG
      (void) fprintf (stderr, 
		      "Got GetProxyAddr, serviceName = %s, serverAddr = %s\n",
              	      serviceName, serverAddress);
      (void) fprintf (stderr, 
		      "\thostAddr = %s, options = %s, authLen = %d\n",
              	      hostAddress, startOptions, authLen);
      if (authLen > 0)
          (void) fprintf (stderr, "\tauthName = %s\n", authName);
#endif
      /*
       * need to copy the host port string because strtok() changes it   
       */
      if ((tmp_str = strdup (serverAddress)) == NULL)
      {
        (void) fprintf(stderr, "malloc - serverAddress copy\n");
        goto sendFailure;
      }

      /*
       * before proceeding we want to verify that we are allowed to
       * accept connections from the host who called xfindproxy(); 
       * the thing is, we don't get that host name from Proxy Manager
       * even if the "-host <hostname>" command-line option was present
       * in xfindproxy (and even if it was we shouldn't rely on it --
       * much better to have ProxyMngr query the xfindproxy connect
       * socket for its origin); the upshot of all this that we do
       * a configuration check *only* on the destination (which we
       * assume in this case to be the serverAddress passed in by
       * xfindproxy(); so get the destination IP address!
       */
      server_name_base = strtok(tmp_str, ":");
      if ((hostptr = gethostbyname(server_name_base)) == NULL)
      {
        (void) fprintf(stderr, "gethostbyname (%s) failed\n", server_name_base);
	goto sendFailure;
      }
      memset(&server_sockaddr_in, 0, sizeof(server_sockaddr_in));
      memset(&dummy_sockaddr_in, 0, sizeof(dummy_sockaddr_in)); 
      memcpy((char *) &server_sockaddr_in.sin_addr, 
	     hostptr->h_addr,
	     hostptr->h_length);

      /*
       * need to initialize dummy to something, but doesn't matter
       * what (should eventually be the true host address); 
       * NOTE:  source configuration will always match (see XFWP man
       * page) unless sysadmin explicitly chooses to deny 
       */
      memcpy((char *) &dummy_sockaddr_in.sin_addr, 
	     hostptr->h_addr,
	     hostptr->h_length);

      if ((doConfigCheck(&dummy_sockaddr_in, 
  			 &server_sockaddr_in,
			 global_data.config_info,
			 FINDPROXY,
			 &rule_number)) == FAILURE)
      { 
        (void) fprintf(stderr, "xfindproxy failed config check\n");
      sendFailure:
        /*
         * report failure back to the ProxyMgr
         * 
         */
        pm_send_msg_len = STRING_BYTES(config_failure)
	      		+ STRING_BYTES(NULL);
        IceGetHeaderExtra(iceConn, 
	      	        program_data->major_opcode, 
	      		PM_GetProxyAddrReply,
	       		SIZEOF(pmGetProxyAddrReplyMsg),
	       		WORD64COUNT (pm_send_msg_len),
	       		pmGetProxyAddrReplyMsg,
	       		pReply,
	       		pReplyData);
        pReply->status = PM_Failure;
        STORE_STRING(pReplyData, NULL);
        STORE_STRING(pReplyData, config_failure);
        IceFlush(iceConn);
	free(tmp_str);
        return; 
      }

      /* 
       * okay, you got what you need from the PM to proceed,
       * so extract the fd of the selected connection and use
       * it to set up the remote client listen port and add 
       * the name of the X server to your list of server connections
       */

      /*
       * Before checking to see if you already have a PM connection
       * request for this server, make serverAddress a
       * FQDN so that synonomous names like oregon:0 and oregon.com:0
       * will be recognized as the same Xserver.  If this server
       * already exists, don't allocate another listen port for it -
       * use the already allocated one
       */
      colon = strchr (serverAddress, ':');
      if (colon)
      {
	  struct hostent *hostent;

	  *colon = '\0';
	  hostent = gethostbyname (serverAddress);
	  *colon = ':';

	  if (hostent && hostent->h_name) {
	      tmpAddress = (char *) malloc (strlen (hostent->h_name) + 
					    strlen (colon) + 1);
	      (void) sprintf (tmpAddress, "%s%s", hostent->h_name, colon);
	      serverAddress = tmpAddress;
	  }
      }

      if ((doCheckServerList(serverAddress, 
			    &listen_port_string,
			    program_data->config_info->num_servers)) == FAILURE)
      {
        /*
         * this server name isn't in your list; so set up a new
         * remote client listen port for it; extract the fd from
         * the connection and pass it in as index to array lookup
         */
        if ((doSetupRemClientListen(&listen_port_string,
			            program_data,
				    serverAddress)) == FAILURE)
 	{
          goto sendFailure;
	}
      }
      if (tmpAddress)
	free (tmpAddress);

      /*
       * the PM-sent server address *was* in your list, so send back
       * the rem client listen port you had already associated with 
       * that server (it will presumably be forwarded to the remote
       * client through some other channel)
       * use IceGetHeaderExtra() and the 
       */
      pm_send_msg_len = STRING_BYTES(listen_port_string)
			+ STRING_BYTES(NULL);
      IceGetHeaderExtra(iceConn, 
		        program_data->major_opcode, 
			PM_GetProxyAddrReply,
			SIZEOF(pmGetProxyAddrReplyMsg),
			WORD64COUNT (pm_send_msg_len),
			pmGetProxyAddrReplyMsg,
			pReply,
			pReplyData);
      pReply->status = PM_Success;
      STORE_STRING(pReplyData, listen_port_string);
      STORE_STRING(pReplyData, NULL); 
      IceFlush(iceConn);
      /*
       * before leaving this routine, change the select() timeout
       * here to be equal to the configured client listen timeout
       * (otherwise you'll never *get* to your listen timeout
       * if it's shorter than the startup select() default
       */
      program_data->config_info->select_timeout.tv_sec =
		program_data->config_info->client_listen_timeout;
      break;
    }

    case ICE_Error:
    {
	iceErrorMsg *pMsg;
	char *pStart;

	CHECK_AT_LEAST_SIZE (iceConn, global_data.major_opcode, ICE_Error, 
			     length, sizeof(iceErrorMsg), IceFatalToProtocol);

	IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
				iceErrorMsg, pMsg, pStart);

	if (!IceValidIO (iceConn))
	{
	    IceDisposeCompleteMessage (iceConn, pStart);
	    return;
	}

	if (swap)
	{
	    pMsg->errorClass = lswaps (pMsg->errorClass);
	    pMsg->offendingSequenceNum = lswapl (pMsg->offendingSequenceNum);
	}

	(void) fprintf(stderr, "Proxy Manager reported ICE Error:\n");
	(void) fprintf(stderr, "\tclass = 0x%x, offending minor opcode = %d\n",
		       pMsg->errorClass, pMsg->offendingMinorOpcode);
	(void) fprintf(stderr, "\tseverity = %d, sequence = %ld\n",
		       pMsg->severity, (long)pMsg->offendingSequenceNum);

	IceDisposeCompleteMessage (iceConn, pStart);

	break;
    }

    default:
      break;
  } /* end switch */
}
int
main(int argc, char *argv[])
{
    static XtAppContext 	appContext;
    IceConn			iceConn;
    IceProtocolSetupStatus	setupstat;
    char			*vendor = NULL;
    char			*release = NULL;
    pmGetProxyAddrMsg		*pMsg;
    char 			*pData;
    int				i;
    size_t			len;
    IceReplyWaitInfo		replyWait;
    GetProxyAddrReply		reply;
    int				majorVersion, minorVersion;
    Bool			gotReply, ioErrorOccured;
    char			errorString[255];
    char			*serviceName = NULL, *serverAddress = NULL;
    char			*hostAddress = NULL, *startOptions = NULL;
    char			*managerAddress = NULL;
    Bool			haveAuth = 0;
    char			authName[40];
    char			authData[128];
    char			*authDataBinary = NULL;
    int				authLen = 0;

    for (i = 1; i < argc; i++)
    {
	if (argv[i][0] == '-')
	{
	    switch (argv[i][1])
	    {
	    case 'a':					/* -auth */
		haveAuth = 1;
		continue;

	    case 'm':					/* -manager */
		if (++i >= argc) goto usage;
		managerAddress = (char *) XtNewString (argv[i]);
		continue;

	    case 's':					/* -server */
		if (++i >= argc) goto usage;
		serverAddress = (char *) XtNewString (argv[i]);
		continue;

	    case 'n':					/* -name */
		if (++i >= argc) goto usage;
		serviceName = XtNewString (argv[i]);
		continue;

	    case 'h':					/* -host */
		if (++i >= argc) goto usage;
		hostAddress = XtNewString (argv[i]);
		continue;

	    case 'o':					/* -options */
		if (++i >= argc) goto usage;
		startOptions = XtNewString (argv[i]);
		continue;

	    case 'v':
		puts(PACKAGE_STRING);
		exit(0);
	    }
	}

    usage:
	if (i >= argc)
	    fprintf (stderr, "%s: %s requires an argument\n",
		     argv[0], argv[i-1]);
	else
	    fprintf (stderr, "%s: unrecognized argument '%s'\n",
		     argv[0], argv[i]);
	usage();
    }

    if (serviceName == NULL) {
	fprintf (stderr, "%s: -name serviceName must be specified\n", argv[0]);
	usage();
    }
    if (serverAddress == NULL) {
	fprintf (stderr, "%s: -server serverAddr must be specified\n", argv[0]);
	usage();
    }

    if (managerAddress == NULL) {
	managerAddress = getenv("PROXY_MANAGER");
	if (managerAddress == NULL) {
	    fprintf (stderr, "Error: -manager option must be specified when PROXY_MANAGER is not in the environment\n");
	    exit (1);
	}
    }

    /*
     * Register support for PROXY_MANAGEMENT.
     */

    if ((PMopcode = IceRegisterForProtocolSetup (
	PM_PROTOCOL_NAME,
	"XC", "1.0",
	PMversionCount, PMversions,
	0, /* authcount */
	NULL, /* authnames */ 
        NULL, /* authprocs */
	NULL  /* IceIOErrorProc */ )) < 0)
    {
	fprintf (stderr,
	    "Could not register PROXY_MANAGEMENT protocol with ICE");
	exit (1);
    }


    appContext = XtCreateApplicationContext ();

    InitWatchProcs (appContext);

    if ((iceConn = IceOpenConnection (
	managerAddress, NULL, 0, 0, 256, errorString)) == NULL)
    {
	fprintf (stderr,
	    "Could not open ICE connection to proxy manager: %s", errorString);
	exit (1);
    }

    setupstat = IceProtocolSetup (iceConn, PMopcode, NULL,
	False /* mustAuthenticate */,
	&majorVersion, &minorVersion,
	&vendor, &release, 256, errorString);

    if (setupstat != IceProtocolSetupSuccess)
    {
	IceCloseConnection (iceConn);
	fprintf (stderr,
	    "Could not initialize proxy management protocol: %s\n",
	    errorString);
	exit (1);
    }


    /*
     * If auth data is supplied, read it from stdin.
     */

    if (haveAuth)
    {
	fgets (authName, sizeof (authName), stdin);
	fgets (authData, sizeof (authData), stdin);

	for (i = 0; i < strlen (authName); i++)
	    if (authName[i] == '\n')
	    {
		authName[i] = '\0';
		break;
	    }
	for (i = 0; i < strlen (authData); i++)
	    if (authData[i] == '\n')
	    {
		authData[i] = '\0';
		break;
	    }

	/*
	 * Convert the hex auth data to binary.
	 */

	authLen = cvthexkey (authData, &authDataBinary);

	if (authLen == -1)
	{
	    fprintf (stderr, "Could not convert hex auth data to binary\n");
	    exit (1);
	}
    }


    /*
     * Now send the GetProxyAddr request.
     */

    len = STRING_BYTES (serviceName) +
	  STRING_BYTES (serverAddress) +
	  STRING_BYTES (hostAddress) +
	  STRING_BYTES (startOptions) +
	  (authLen > 0 ? (STRING_BYTES (authName) + authLen) : 0);

    IceGetHeaderExtra (iceConn, PMopcode, PM_GetProxyAddr,
	SIZEOF (pmGetProxyAddrMsg), WORD64COUNT (len),
	pmGetProxyAddrMsg, pMsg, pData);

    pMsg->authLen = (CARD16) authLen;

    STORE_STRING (pData, serviceName);
    STORE_STRING (pData, serverAddress);
    STORE_STRING (pData, hostAddress);
    STORE_STRING (pData, startOptions);
    if (authLen > 0)
    {
	STORE_STRING (pData, authName);
	memcpy (pData, authDataBinary, authLen);
    }

    IceFlush (iceConn);

    replyWait.sequence_of_request = IceLastSentSequenceNumber (iceConn);
    replyWait.major_opcode_of_request = PMopcode;
    replyWait.minor_opcode_of_request = PM_GetProxyAddr;
    replyWait.reply = (IcePointer) &reply;

    gotReply = False;
    ioErrorOccured = False;

    while (!gotReply && !ioErrorOccured)
    {
	ioErrorOccured = (IceProcessMessages (
	    iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError);

	if (ioErrorOccured)
	{
	    fprintf (stderr, "IO error occured\n");
	    exit (1);
	}
	else if (gotReply)
	{
	    if (reply.status == PM_Success)
	    {
		fprintf (stdout, "%s\n", reply.addr);
		exit (0);
	    }
	    else
	    {
		fprintf (stderr, "Error from proxy manager: %s\n",
		    reply.error);
		exit (1);
	    }
	}
    }
    /*NOTREACHED*/
    exit(0);
}
Exemplo n.º 16
0
IceProtocolSetupStatus
IceProtocolSetup (
	IceConn	   iceConn,
	int 	   myOpcode,
	IcePointer clientData,
	Bool       mustAuthenticate,
	int	   *majorVersionRet,
	int	   *minorVersionRet,
	char	   **vendorRet,
	char	   **releaseRet,
	int  	   errorLength,
	char 	   *errorStringRet
)
{
    iceProtocolSetupMsg	*pMsg;
    char		*pData;
    _IceProtocol	*myProtocol;
    int			extra;
    Bool		gotReply, ioErrorOccured;
    int			accepted, i;
    int			hisOpcode;
    unsigned long	setup_sequence;
    IceReplyWaitInfo 	replyWait;
    _IceReply		reply;
    IcePoVersionRec	*versionRec = NULL;
    int			authCount;
    int			*authIndices;

    if (errorStringRet && errorLength > 0)
	*errorStringRet = '\0';

    *majorVersionRet = 0;
    *minorVersionRet = 0;
    *vendorRet = NULL;
    *releaseRet = NULL;

    if (myOpcode < 1 || myOpcode > _IceLastMajorOpcode)
    {
	strncpy (errorStringRet, "myOpcode out of range", errorLength);
	return (IceProtocolSetupFailure);
    }

    myProtocol = &_IceProtocols[myOpcode - 1];

    if (myProtocol->orig_client == NULL)
    {
	strncpy (errorStringRet,
	    "IceRegisterForProtocolSetup was not called", errorLength);
	return (IceProtocolSetupFailure);
    }


    /*
     * Make sure this protocol hasn't been activated already.
     */

    if (iceConn->process_msg_info)
    {
	for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++)
	{
	    if (iceConn->process_msg_info[
		i - iceConn->his_min_opcode].in_use &&
                iceConn->process_msg_info[
		i - iceConn->his_min_opcode ].my_opcode == myOpcode)
		break;
	}

	if (i <= iceConn->his_max_opcode)
	{
	    return (IceProtocolAlreadyActive);
	}
    }

    /*
     * Generate the message.
     */

    if (myProtocol->orig_client->auth_count > 0)
    {
	authIndices = malloc (
	    myProtocol->orig_client->auth_count * sizeof (int));

	_IceGetPoValidAuthIndices (myProtocol->protocol_name,
	    iceConn->connection_string,
	    myProtocol->orig_client->auth_count,
	    (const char **) myProtocol->orig_client->auth_names,
            &authCount, authIndices);

    }
    else
    {
	authCount = 0;
	authIndices = NULL;
    }

    extra = STRING_BYTES (myProtocol->protocol_name) +
            STRING_BYTES (myProtocol->orig_client->vendor) +
            STRING_BYTES (myProtocol->orig_client->release);

    for (i = 0; i < authCount; i++)
    {
	extra += STRING_BYTES (myProtocol->orig_client->auth_names[
	    authIndices[i]]);
    }

    extra += (myProtocol->orig_client->version_count * 4);

    IceGetHeaderExtra (iceConn, 0, ICE_ProtocolSetup,
	SIZEOF (iceProtocolSetupMsg), WORD64COUNT (extra),
	iceProtocolSetupMsg, pMsg, pData);

    setup_sequence = iceConn->send_sequence;

    pMsg->protocolOpcode = myOpcode;
    pMsg->versionCount = myProtocol->orig_client->version_count;
    pMsg->authCount = authCount;
    pMsg->mustAuthenticate = mustAuthenticate;

    STORE_STRING (pData, myProtocol->protocol_name);
    STORE_STRING (pData, myProtocol->orig_client->vendor);
    STORE_STRING (pData, myProtocol->orig_client->release);

    for (i = 0; i < authCount; i++)
    {
	STORE_STRING (pData, myProtocol->orig_client->auth_names[
	    authIndices[i]]);
    }

    for (i = 0; i < myProtocol->orig_client->version_count; i++)
    {
	STORE_CARD16 (pData,
	    myProtocol->orig_client->version_recs[i].major_version);
	STORE_CARD16 (pData,
	    myProtocol->orig_client->version_recs[i].minor_version);
    }

    IceFlush (iceConn);


    /*
     * Process messages until we get a Protocol Reply.
     */

    replyWait.sequence_of_request = setup_sequence;
    replyWait.major_opcode_of_request = 0;
    replyWait.minor_opcode_of_request = ICE_ProtocolSetup;
    replyWait.reply = (IcePointer) &reply;

    iceConn->protosetup_to_you = malloc (sizeof (_IceProtoSetupToYouInfo));
    iceConn->protosetup_to_you->my_opcode = myOpcode;
    iceConn->protosetup_to_you->my_auth_count = authCount;
    iceConn->protosetup_to_you->auth_active = 0;
    iceConn->protosetup_to_you->my_auth_indices = authIndices;

    gotReply = False;
    ioErrorOccured = False;
    accepted = 0;

    while (!gotReply && !ioErrorOccured)
    {
	ioErrorOccured = (IceProcessMessages (
	    iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError);

	if (ioErrorOccured)
	{
	    strncpy (errorStringRet,
		"IO error occured doing Protocol Setup on connection",
		errorLength);
	    return (IceProtocolSetupIOError);
	}
	else if (gotReply)
	{
	    if (reply.type == ICE_PROTOCOL_REPLY)
	    {
		if (reply.protocol_reply.version_index >=
		    myProtocol->orig_client->version_count)
		{
		    strncpy (errorStringRet,
	                "Got a bad version index in the Protocol Reply",
		        errorLength);

		    free (reply.protocol_reply.vendor);
		    free (reply.protocol_reply.release);
		}
		else
		{
		    versionRec = &(myProtocol->orig_client->version_recs[
		        reply.protocol_reply.version_index]);

		    accepted = 1;
		}
	    }
	    else /* reply.type == ICE_PROTOCOL_ERROR */
	    {
		/* Protocol Setup failed */

		strncpy (errorStringRet, reply.protocol_error.error_message,
		    errorLength);

		free (reply.protocol_error.error_message);
	    }

	    if (iceConn->protosetup_to_you->my_auth_indices)
		free (iceConn->protosetup_to_you->my_auth_indices);
	    free (iceConn->protosetup_to_you);
	    iceConn->protosetup_to_you = NULL;
	}
    }

    if (accepted)
    {
	_IceProcessMsgInfo *process_msg_info;

	*majorVersionRet = versionRec->major_version;
	*minorVersionRet = versionRec->minor_version;
	*vendorRet = reply.protocol_reply.vendor;
	*releaseRet = reply.protocol_reply.release;


	/*
	 * Increase the reference count for the number of active protocols.
	 */

	iceConn->proto_ref_count++;


	/*
	 * We may be using a different major opcode for this protocol
	 * than the other client.  Whenever we get a message, we must
	 * map to our own major opcode.
	 */

	hisOpcode = reply.protocol_reply.major_opcode;

	_IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode);

	process_msg_info = &iceConn->process_msg_info[hisOpcode -
	    iceConn->his_min_opcode];

	process_msg_info->client_data = clientData;
	process_msg_info->accept_flag = 0;

	process_msg_info->process_msg_proc.orig_client =
		versionRec->process_msg_proc;

	return (IceProtocolSetupSuccess);
    }
    else
    {
	return (IceProtocolSetupFailure);
    }
}
Exemplo n.º 17
0
  Bool
dcop_call(
  const char  * appId,
  const char  * remApp,
  const char  * remObjId,
  const char  * remFun,
  const char  * data,
  int           dataLength,
  char       ** replyType,
  char       ** replyData,
  int         * replyDataLength
)
{
  IceReplyWaitInfo          waitInfo;
  IceProcessMessagesStatus  status;
  struct dcop_reply_struct  replyStruct;

  char  * pos               = 0L;
  char  * outputData        = 0L;
  int     outputDataLength  = 0;
  int     temp              = 0;
  Bool    success           = False;
  Bool    readyRet          = False;

  struct DCOPMsg * pMsg;


  fprintf(stderr, "dcop_call() ...\n");

  if (0 == dcop_ice_conn) {
    fprintf(stderr, "Try running dcop_register(), moron\n");
    return False;
  }


  temp += strlen(appId);
  temp += strlen(remApp);
  temp += strlen(remObjId);
  temp += strlen(remFun);
  temp += dataLength;
  temp += 1024; /* Extra space for marshalling overhead */

  outputData = (char *)malloc(temp);

  temp = 0;

  pos = outputData;
  pos = dcop_write_string(pos, appId);
  pos = dcop_write_string(pos, remApp);
  pos = dcop_write_string(pos, remObjId);
  pos = dcop_write_string(pos, remFun);
  pos = dcop_write_int(pos, dataLength);

  outputDataLength = pos - outputData;

  IceGetHeader(
	       dcop_ice_conn,
	       dcop_major_opcode,
	       DCOPCall,
	       sizeof(struct DCOPMsg),
	       struct DCOPMsg,
	       pMsg
	       );

  pMsg->length += outputDataLength + dataLength;

  IceSendData(dcop_ice_conn, outputDataLength, outputData);
  IceSendData(dcop_ice_conn, dataLength, (char *)data);

  IceFlush(dcop_ice_conn);

  free(outputData);
  outputData = NULL;

  if (IceConnectionStatus(dcop_ice_conn) != IceConnectAccepted) {
      fprintf(stderr, "dcop_call(): Connection not accepted\n");
      return False;
  }

  waitInfo.sequence_of_request = IceLastSentSequenceNumber(dcop_ice_conn);
  waitInfo.major_opcode_of_request = dcop_major_opcode;
  waitInfo.minor_opcode_of_request = DCOPCall;

  replyStruct.status = DCOP_REPLY_PENDING;
  replyStruct.replyId = dcop_reply_id++;
  replyStruct.replyType = replyType;
  replyStruct.replyData = replyData;
  replyStruct.replyDataLength = replyDataLength;

  waitInfo.reply = (IcePointer)(&replyStruct);

  readyRet = False;

  do {
      fprintf(stderr, "dcop_call(): Doing IceProcessMessages\n");
      status = IceProcessMessages(dcop_ice_conn, &waitInfo, &readyRet);

      if (status == IceProcessMessagesIOError) {
        fprintf(stderr, "dcop_call(): IceProcessMessagesIOError\n");
        IceCloseConnection(dcop_ice_conn);
        return False;
      }

      fprintf(stderr, "dcop_call(): readyRet == %s\n", readyRet ? "True" : "False");
  } while (!readyRet);

  fprintf(stderr, "dcop_call(): Finished\n");
  return (replyStruct.status == DCOP_REPLY_OK) ? True : False;
}
Exemplo n.º 18
0
  Bool
dcop_send_signal(
  const char  * receiving_app,
  const char  * object,
  const char  * function,
  char        * data,
  int           dataLength
)
{
  char        * pos           = 0L;
  char        * header        = 0L;
  unsigned int  headerLength  = 0;

  struct DCOPMsg * pMsgPtr = 0;

  static const char* sAnonymous = "anonymous";

  if (0 == dcop_ice_conn) {
    fprintf(stderr, "Try running dcop_attach(), moron\n");
    return False;
  }

  /*
   * First let ICE initialize the ICE Message Header and give us a pointer to
   * it (ICE manages that buffer internally)
   */
  IceGetHeader(
    dcop_ice_conn,
    dcop_major_opcode,
    DCOPSend,
    sizeof(struct DCOPMsg),
    struct DCOPMsg,
    pMsgPtr
  );

  /*
   * Marshall the arguments for the DCOP message header (callerApp, destApp,
   * destObj, destFunc. The last argument is actually part of the data part of
   * the call, but we add it to the header. It's the size of the marshalled
   * argument data. In Qt it would look like TQDataStream str( ... ) str <<
   * callerApp << destApp << destObj << destFun <<
   * argumentQByteArrayDataStuff; (where as str is the complete data stream
   * sent do the dcopserver, excluding the ICE header) As the TQByteArray is
   * marshalled as [size][data] and as we (below) send the data in two chunks,
   * first the dcop msg header and the the data, we just put the [size] field
   * as last field into the dcop msg header ;-)
   */

  headerLength = strlen(sAnonymous) + 1 +
                 strlen(receiving_app) + 1 +
                 strlen(object) + 1 +
                 strlen(function) + 1 +
                 4*5;  /* 4 string lengths + 1 int */

  header = (char *)malloc(headerLength);

  pos = header;

  pos = dcop_write_string(pos, sAnonymous);
  pos = dcop_write_string(pos, receiving_app);
  pos = dcop_write_string(pos, object);
  pos = dcop_write_string(pos, function);
  pos = dcop_write_int(pos, dataLength);

  headerLength = pos - header;

  pMsgPtr->key = dcop_key;
  /*
   * The length field tells the dcopserver how much bytes the dcop message
   * takes up. We add that size to the already by IceGetHeader initialized
   * length value, as it seems that under some circumstances (depending on the
   * DCOPMsg structure size) the length field is aligned/padded.
   */
  pMsgPtr->length += headerLength + dataLength;

  /* First let's send the dcop message header.
   * IceSendData automatically takes care of first sending the Ice Message
   * Header (outbufptr > outbuf -> flush the connection buffer)
   */
  IceSendData(dcop_ice_conn, headerLength, header);

  /* Now the function argument data */
  IceSendData(dcop_ice_conn, dataLength, data);

  /* Send it all ;-) */
  IceFlush(dcop_ice_conn);

  free(header);

  if (IceConnectionStatus(dcop_ice_conn) != IceConnectAccepted)
    return False;
	
  return True;
}
Exemplo n.º 19
0
SmcCloseStatus
SmcCloseConnection(SmcConn smcConn, int count, char **reasonMsgs)
{
    IceConn			iceConn = smcConn->iceConn;
    smCloseConnectionMsg 	*pMsg;
    char 			*pData;
    int				extra, i;
    IceCloseStatus	        closeStatus;
    SmcCloseStatus		statusRet;

    extra = 8;

    for (i = 0; i < count; i++)
	extra += ARRAY8_BYTES (strlen (reasonMsgs[i]));

    IceGetHeaderExtra (iceConn, _SmcOpcode, SM_CloseConnection,
	SIZEOF (smCloseConnectionMsg), WORD64COUNT (extra),
	smCloseConnectionMsg, pMsg, pData);

    STORE_CARD32 (pData, count);
    pData += 4;

    for (i = 0; i < count; i++)
	STORE_ARRAY8 (pData, strlen (reasonMsgs[i]), reasonMsgs[i]); 

    IceFlush (iceConn);

    IceProtocolShutdown (iceConn, _SmcOpcode);
    IceSetShutdownNegotiation (iceConn, False);
    closeStatus = IceCloseConnection (iceConn);

    if (smcConn->vendor)
	free (smcConn->vendor);

    if (smcConn->release)
	free (smcConn->release);

    if (smcConn->client_id)
	free (smcConn->client_id);

    if (smcConn->prop_reply_waits)
    {
	_SmcPropReplyWait *ptr = smcConn->prop_reply_waits;
	_SmcPropReplyWait *next;

	while (ptr)
	{
	    next = ptr->next;
	    free ((char *) ptr);
	    ptr = next;
	}
	
    }

    free ((char *) smcConn);

    if (closeStatus == IceClosedNow)
	statusRet = SmcClosedNow;
    else if (closeStatus == IceClosedASAP)
	statusRet = SmcClosedASAP;
    else
	statusRet = SmcConnectionInUse;

    return (statusRet);
}
Exemplo n.º 20
0
IceCloseStatus
IceCloseConnection (
	IceConn     iceConn
)
{
    int refCountReachedZero;
    IceCloseStatus status;

    /*
     * If this connection object was never valid, we can close
     * it right now.  This happens if IceAcceptConnection was
     * called, but after calling IceProcessMessages several times
     * the connection was rejected (because of authentication or
     * some other reason).
     */

    if (iceConn->listen_obj &&
	iceConn->connection_status != IceConnectAccepted)
    {
	_IceConnectionClosed (iceConn);		/* invoke watch procs */
	_IceFreeConnection (iceConn);
	return (IceClosedNow);
    }


    /*---------------------------------------------------------------

    ACTIONS:

    A = Invoke Watch Procedures
    B = Set free-asap bit
    C = Free connection
    D = Initialize shutdown negotiation
    N = do nothing


    ACTION TABLE:

    IO	       free-      dispatch   protocol   shutdown
    error      asap bit   level      refcount   negotiation     ACTION
    occured    set        reached 0  reached 0
    
        0          0          0          0          0		N
        0          0          0          0          1		N
        0          0          0          1          0		AB
        0          0          0          1          1		N
        0          0          1          0          0		N
        0          0          1          0          1		N
        0          0          1          1          0		AC
        0          0          1          1          1		D
        0          1          0          0          0		N
        0          1          0          0          1		N
        0          1          0          1          0		N
        0          1          0          1          1		N
        0          1          1          0          0		C
        0          1          1          0          1		D
        0          1          1          1          0		C
        0          1          1          1          1		D
        1          0          0          0          0		AB
        1          0          0          0          1		AB
        1          0          0          1          0		AB
        1          0          0          1          1		AB
        1          0          1          0          0		AC
        1          0          1          0          1		AC
        1          0          1          1          0		AC
        1          0          1          1          1		AC
        1          1          0          0          0		N
        1          1          0          0          1		N
        1          1          0          1          0		N
        1          1          0          1          1		N
        1          1          1          0          0		C
        1          1          1          0          1		C
        1          1          1          1          0		C
        1          1          1          1          1		C

    ---------------------------------------------------------------*/

    if (iceConn->open_ref_count > 0)
	iceConn->open_ref_count--;

    refCountReachedZero = iceConn->open_ref_count == 0 &&
	iceConn->proto_ref_count == 0;

    status = IceConnectionInUse;

    if (!iceConn->free_asap && (!iceConn->io_ok ||
	(iceConn->io_ok && refCountReachedZero &&
	iceConn->skip_want_to_close)))
    {
	/*
	 * Invoke the watch procedures now.
	 */

	_IceConnectionClosed (iceConn);
	status = IceClosedNow;	     /* may be overwritten by IceClosedASAP */
    }

    if (!iceConn->free_asap && iceConn->dispatch_level != 0 &&
	(!iceConn->io_ok ||
	(iceConn->io_ok && refCountReachedZero &&
	iceConn->skip_want_to_close)))
    {
	/*
	 * Set flag so we free the connection as soon as possible.
	 */

	iceConn->free_asap = True;
	status = IceClosedASAP;
    }

    if (iceConn->io_ok && iceConn->dispatch_level == 0 &&
	!iceConn->skip_want_to_close && refCountReachedZero)
    {
	/*
	 * Initiate shutdown negotiation.
	 */

	IceSimpleMessage (iceConn, 0, ICE_WantToClose);
	IceFlush (iceConn);

	iceConn->want_to_close = 1;

	status = IceStartedShutdownNegotiation;
    }
    else if (iceConn->dispatch_level == 0 &&
	(!iceConn->io_ok || (iceConn->io_ok && iceConn->skip_want_to_close &&
	(iceConn->free_asap || (!iceConn->free_asap && refCountReachedZero)))))
    {
	/*
	 * Free the connection.
	 */

	_IceFreeConnection (iceConn);

	status = IceClosedNow;
    }

    return (status);
}