⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssliop_connector.cpp

📁 这是广泛使用的通信开源项目,对于大容量,高并发的通讯要求完全能够胜任,他广泛可用于网络游戏医学图像网关的高qos要求.更详细的内容可阅读相应的材料
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    {
      if (TAO_debug_level > 0)
        {
          ACE_DEBUG ((LM_DEBUG,
                      ACE_TEXT ("TAO (%P|%t) SSLIOP connection failed.\n")
                      ACE_TEXT ("TAO (%P|%t) This is most likely ")
                      ACE_TEXT ("due to a hostname lookup ")
                      ACE_TEXT ("failure.\n")));
        }

      return 0;
    }

  int result = 0;
  TAO_SSLIOP_Connection_Handler *svc_handler = 0;
  TAO_Transport *transport = 0;

  // Check the Cache first for connections
  if (this->orb_core ()->lane_resources ().transport_cache ().find_transport (
        desc,
        transport) == 0)
    {
      if (TAO_debug_level > 2)
        ACE_DEBUG ((LM_DEBUG,
                    ACE_TEXT ("(%P|%t) SSLIOP_Connector::connect ")
                    ACE_TEXT ("got existing transport[%d]\n"),
                    transport->id ()));
    }
  else
    {
      if (TAO_debug_level > 4)
        ACE_DEBUG ((LM_DEBUG,
                    ACE_TEXT ("(%P|%t) SSLIOP_Connector::connect ")
                    ACE_TEXT ("making a new connection \n")));

      // Purge connections (if necessary)
      this->orb_core ()->lane_resources ().transport_cache ().purge ();

      // The svc_handler is created beforehand so that we can get
      // access to the underlying ACE_SSL_SOCK_Stream (the peer) and
      // its SSL pointer member prior to descending into the
      // ACE_Strategy_Connector (the "base_connector_").  This is
      // thread-safe and reentrant, hence no synchronization is
      // necessary.
      //
      // The make_svc_handler() method creates the service handler and
      // bumps the #REFCOUNT# up one extra.  The extra reference count
      // in TAO_Connect_Creation_Strategy::make_svc_handler() is
      // needed in the case when connection completion is pending and
      // we are going to wait on a variable in the handler to changes,
      // signifying success or failure.  Note, that this increment
      // cannot be done once the connect() returns since this might be
      // too late if another thread pick up the completion and
      // potentially deletes the handler before we get a chance to
      // increment the reference count.
      if (this->base_connector_.creation_strategy ()->make_svc_handler (
               svc_handler) != 0)
        {
          if (TAO_debug_level > 0)
            ACE_DEBUG ((LM_ERROR,
                        ACE_TEXT ("(%P|%t) Unable to create SSLIOP ")
                        ACE_TEXT ("service handler.\n")));

          return 0;
        }

      ACE_Auto_Basic_Ptr<TAO_SSLIOP_Connection_Handler>
        safe_handler (svc_handler);

      // Setup the establishment of trust connection properties, if
      // any.
      int verify_mode = 0;

      // On the server side, "trust_in_client" requires that a peer
      // (client) certificate exist.  Fail if one doesn't exist.
      //
      // In SSLIOP's case, trust_in_client also implies
      // trust_in_target.
      if (trust.trust_in_client)
        verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;

      // Require verification of the target's certificate.
      else if (trust.trust_in_target)
        verify_mode = SSL_VERIFY_PEER;

      // Trust in neither the client nor the target is explicitly
      // specified.  Use the default setting.
      else
        verify_mode =
          ACE_SSL_Context::instance ()->default_verify_mode ();

      ::SSL_set_verify (svc_handler->peer ().ssl (),
                        verify_mode,
                        0);

      // The "eNULL" cipher disables encryption but still uses a
      // secure hash (e.g. SHA1 or MD5) to ensure integrity.  (Try the
      // command "openssl ciphers -v eNULL".)
      //
      // Note that it is not possible to completely disable protection
      // here.
      if ((qop == Security::SecQOPNoProtection
          || qop == Security::SecQOPIntegrity)
          && ::SSL_set_cipher_list (svc_handler->peer ().ssl (),
                                    "eNULL") == 0)
        {
          if (TAO_debug_level > 0)
            ACE_DEBUG ((LM_ERROR,
                        ACE_TEXT ("(%P|%t) Unable to set eNULL ")
                        ACE_TEXT ("SSL cipher.\n")));

          ACE_THROW_RETURN (CORBA::INV_POLICY (), 0);
        }

      TAO_SSLIOP_Credentials_var credentials =
        this->retrieve_credentials (resolver->stub (),
                                    svc_handler->peer ().ssl ()
                                    ACE_ENV_ARG_PARAMETER);
      ACE_CHECK_RETURN (0);

      svc_handler = safe_handler.release ();

      // Get the right synch options
      ACE_Synch_Options synch_options;

      this->active_connect_strategy_->synch_options (max_wait_time,
                                                     synch_options);

      // We obtain the transport in the <svc_handler> variable.  As we
      // know now that the connection is not available in Cache we can
      // make a new connection
      result = this->base_connector_.connect (svc_handler,
                                              remote_address,
                                              synch_options);

      // There are three possibilities from calling connect(): (a)
      // connection succeeds immediately - in this case, the
      // #REFCOUNT# on the handler is two; (b) connection completion
      // is pending - in this case, the #REFCOUNT# on the handler is
      // also two; (c) connection fails immediately - in this case,
      // the #REFCOUNT# on the handler is one since close() gets
      // called on the handler.

      // No immediate result.  Wait for completion.
      if (result == -1 && errno == EWOULDBLOCK)
        {
          if (TAO_debug_level > 2)
            ACE_DEBUG ((LM_DEBUG,
                        "TAO (%P|%t) - SSLIOP_Connector::ssliop_connect(), "
                        "going to wait for connection completion on local"
                        "handle [%d]\n",
                        svc_handler->get_handle ()));

          // Wait for connection completion.  No need to specify timeout
          // to wait() since the correct timeout was passed to the
          // Connector. The Connector will close the handler in the case
          // of timeouts, so the event will complete (either success or
          // failure) within timeout.
          result =
            this->active_connect_strategy_->wait (svc_handler,
                                                  0);

          if (TAO_debug_level > 2)
            {
              ACE_DEBUG ((LM_DEBUG,
                          "TAO (%P|%t) - IIOP_Connector::make_connection"
                          "wait done for handle[%d], result = %d\n",
                          svc_handler->get_handle (), result));
            }

          // There are three possibilities when wait() returns: (a)
          // connection succeeded; (b) connection failed; (c) wait()
          // failed because of some other error.  It is easy to deal with
          // (a) and (b).  (c) is tricky since the connection is still
          // pending and may get completed by some other thread.  The
          // following code deals with (c).

          // Check if the handler has been closed.
          int closed =
            svc_handler->is_closed ();

          // In case of failures and close() has not be called.
          if (result == -1 &&
              !closed)
            {
              // First, cancel from connector.
              this->base_connector_.cancel (svc_handler);

              // Double check to make sure the handler has not been closed
              // yet.  This double check is required to ensure that the
              // connection handler was not closed yet by some other
              // thread since it was still registered with the connector.
              // Once connector.cancel() has been processed, we are
              // assured that the connector will no longer open/close this
              // handler.
              closed =
                svc_handler->is_closed ();

              // If closed, there is nothing to do here.  If not closed,
              // it was either opened or is still pending.
              if (!closed)
                {
                  // Check if the handler has been opened.
                  int open =
                    svc_handler->is_open ();

                  // Some other thread was able to open the handler even
                  // though wait failed for this thread.
                  if (open)
                    // Overwrite <result>.
                    result = 0;
                  else
                    {
                      // Assert that it is still connecting.
                      ACE_ASSERT (svc_handler->is_connecting ());

                      // Force close the handler now.
                      svc_handler->close ();
                    }
                }
            }
        }

      // Irrespective of success or failure, remove the extra #REFCOUNT#.
      svc_handler->remove_reference ();

      // In case of errors.
      if (result == -1)
        {
          // Give users a clue to the problem.
          if (TAO_debug_level)
            {
              char buffer [MAXHOSTNAMELEN + 6 + 1];
              ssl_endpoint->addr_to_string (buffer,
                                            sizeof (buffer) - 1);
              ACE_DEBUG ((LM_ERROR,
                          ACE_TEXT ("TAO (%P|%t) %N:%l, SSL connection to ")
                          ACE_TEXT ("<%s:%d> failed (%p)\n"),
                          buffer,
                          remote_address.get_port_number (),
                          ACE_TEXT ("errno")));
            }

          return 0;
        }

      // At this point, the connection has be successfully connected.
      // #REFCOUNT# is one.
      if (TAO_debug_level > 2)
        ACE_DEBUG ((LM_DEBUG,
                    "TAO (%P|%t) - SSLIOP_Connector::ssliop_connect(): "
                    "new SSL connection to port %d on transport[%d]\n",
                    remote_address.get_port_number (),
                    svc_handler->peer ().get_handle ()));

      transport =
        svc_handler->transport ();

      ssl_endpoint->qop (qop);
      ssl_endpoint->trust (trust);
      ssl_endpoint->credentials (credentials.in ());

      // Add the handler to Cache
      int retval =
        this->orb_core ()->lane_resources ().transport_cache ().cache_transport (desc,
                                                                                 transport);

      // Failure in adding to cache.
      if (retval != 0)
        {
          // Close the handler.
          svc_handler->close ();

          if (TAO_debug_level > 0)
            {
              ACE_ERROR ((LM_ERROR,
                          "TAO (%P|%t) - IIOP_Connector::make_connection, "
                          "could not add the new connection to cache\n"));
            }

          return 0;
        }

      // If the wait strategy wants us to be registered with the reactor
      // then we do so. If registeration is required and it succeeds,
      // #REFCOUNT# becomes two.
      retval =  transport->wait_strategy ()->register_handler ();

      // Registration failures.
      if (retval != 0)
        {
          // Purge from the connection cache.
          transport->purge_entry ();

          // Close the handler.
          svc_handler->close ();

          if (TAO_debug_level > 0)
            {
              ACE_ERROR ((LM_ERROR,
                          "TAO (%P|%t) - IIOP_Connector::make_connection, "
                          "could not register the new connection in the reactor\n"));
            }

          return 0;
        }
    }

  return transport;
}

TAO_SSLIOP_Credentials *
TAO_SSLIOP_Connector::retrieve_credentials (TAO_Stub *stub,
                                            SSL *ssl
                                            ACE_ENV_ARG_DECL)
{
  // Check if the user overrode the default invocation credentials.
  CORBA::Policy_var policy =
    stub->get_policy (Security::SecInvocationCredentialsPolicy
                      ACE_ENV_ARG_PARAMETER);
  ACE_CHECK_RETURN (TAO_SSLIOP_Credentials::_nil ());

  SecurityLevel2::InvocationCredentialsPolicy_var creds_policy =
    SecurityLevel2::InvocationCredentialsPolicy::_narrow (
      policy.in ()
      ACE_ENV_ARG_PARAMETER);
  ACE_CHECK_RETURN (TAO_SSLIOP_Credentials::_nil ());

  TAO_SSLIOP_Credentials_var ssliop_credentials;

  // Set the Credentials (X.509 certificates and corresponding private
  // keys) to be used for this invocation.
  if (!CORBA::is_nil (creds_policy.in ()))
    {
      SecurityLevel2::CredentialsList_var creds_list =
        creds_policy->creds (ACE_ENV_SINGLE_ARG_PARAMETER);
      ACE_CHECK_RETURN (TAO_SSLIOP_Credentials::_nil ());

      if (creds_list->length () > 0)
        {
          // Only use the first credential.  All others are supposed
          // to be used for delegation but SSLIOP in CSIv1 does not
          // support delegation.  (Compare to CSIv2.)
          SecurityLevel2::Credentials_ptr credentials =
            creds_list[(CORBA::ULong) 0];

          ssliop_credentials =
            TAO_SSLIOP_Credentials::_narrow (credentials
                                             ACE_ENV_ARG_PARAMETER);
          ACE_CHECK_RETURN (TAO_SSLIOP_Credentials::_nil ());

          if (!CORBA::is_nil (ssliop_credentials.in ()))
            {
              TAO_SSLIOP_X509_var x509 = ssliop_credentials->x509 ();
              if (::SSL_use_certificate (ssl, x509.in ()) != 1)
                return TAO_SSLIOP_Credentials::_nil ();

              TAO_SSLIOP_EVP_PKEY_var evp = ssliop_credentials->evp ();
              if (evp.in () != 0
                  && ::SSL_use_PrivateKey (ssl, evp.in ()) != 1)
                {
                  // Invalidate the certificate we just set.
                  (void) ::SSL_use_certificate (ssl, 0);
                  return TAO_SSLIOP_Credentials::_nil ();
                }
            }
        }
    }
  else
    {
      // Use the default certificate and private key, i.e. the one set
      // in the SSL_CTX that was used when creating the SSL data
      // structure.
      TAO_SSLIOP_Credentials_ptr & c = ssliop_credentials.out ();
      ACE_NEW_THROW_EX (c,
                        TAO_SSLIOP_Credentials (::SSL_get_certificate (ssl),
                                                ::SSL_get_privatekey (ssl)),
                        CORBA::NO_MEMORY ());
      ACE_CHECK_RETURN (TAO_SSLIOP_Credentials::_nil ());
    }

  return ssliop_credentials._retn ();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -