Logo Search packages:      
Sourcecode: dapl version File versions  Download package

dapl_evd_connection_callb.c

/*
 * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
 *
 * This Software is licensed under one of the following licenses:
 *
 * 1) under the terms of the "Common Public License 1.0" a copy of which is
 *    available from the Open Source Initiative, see
 *    http://www.opensource.org/licenses/cpl.php.
 *
 * 2) under the terms of the "The BSD License" a copy of which is
 *    available from the Open Source Initiative, see
 *    http://www.opensource.org/licenses/bsd-license.php.
 *
 * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
 *    copy of which is available from the Open Source Initiative, see
 *    http://www.opensource.org/licenses/gpl-license.php.
 *
 * Licensee has the right to choose one of the above licenses.
 *
 * Redistributions of source code must retain the above copyright
 * notice and one of the license notices.
 *
 * Redistributions in binary form must reproduce both the above copyright
 * notice, one of the license notices in the documentation
 * and/or other materials provided with the distribution.
 */

/**********************************************************************
 *
 * MODULE: dapl_evd_connection_callback.c
 *
 * PURPOSE: implements connection callbacks
 *
 * Description: Accepts asynchronous callbacks from the Communications Manager
 *              for EVDs that have been specified as the connection_evd.
 *
 * $Id:$
 **********************************************************************/

#include "dapl.h"
#include "dapl_evd_util.h"
#include "dapl_ep_util.h"
#include "dapl_timer_util.h"

/*
 * dapl_evd_connection_callback
 *
 * Connection callback function for ACTIVE connection requests; callbacks
 * generated by the Connection Manager in response to issuing a
 * connect call.
 *
 * Input:
 *    ib_cm_handle,
 *    ib_cm_event
 *    private_data_ptr
 *    context (evd)
 *    cr_pp
 *
 * Output:
 *    None
 *
 */

void
dapl_evd_connection_callback(IN dp_ib_cm_handle_t ib_cm_handle,
                       IN const ib_cm_events_t ib_cm_event,
                       IN const void *private_data_ptr,
                       IN const void *context)
{
      DAPL_EP *ep_ptr;
      DAPL_EVD *evd_ptr;
      DAPL_PRIVATE *prd_ptr;
      DAT_EVENT_NUMBER dat_event_num;
      DAT_RETURN dat_status;
      int private_data_size;

      dapl_dbg_log(DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
                 "--> dapl_evd_connection_callback: ctxt: %p event: %x cm_handle %p\n",
                 context, ib_cm_event, (void *)ib_cm_handle);

      /*
       * Determine the type of handle passed back to us in the context
       * and sort out key parameters.
       */
      if (context == NULL
          || ((DAPL_HEADER *) context)->magic != DAPL_MAGIC_EP) {
            return;
      }

      /*
       * Active side of the connection, context is an EP and
       * PSP is irrelevant.
       */
      ep_ptr = (DAPL_EP *) context;
      evd_ptr = (DAPL_EVD *) ep_ptr->param.connect_evd_handle;
      DAPL_CNTR(evd_ptr, DCNT_EVD_CONN_CALLBACK);

      prd_ptr = (DAPL_PRIVATE *) private_data_ptr;
      private_data_size = 0;
      /*
       * All operations effect the EP, so lock it once and unlock
       * when necessary
       */
      dapl_os_lock(&ep_ptr->header.lock);

      /*
       * If a connection timer has been set up on this EP, cancel it now
       */
      if (ep_ptr->cxn_timer != NULL) {
            dapls_timer_cancel(ep_ptr->cxn_timer);
            dapl_os_free(ep_ptr->cxn_timer, sizeof(DAPL_OS_TIMER));
            ep_ptr->cxn_timer = NULL;
      }

      /* Obtain the event number from the provider layer */
      dat_event_num = dapls_ib_get_dat_event(ib_cm_event, DAT_FALSE);

      switch (dat_event_num) {
      case DAT_CONNECTION_EVENT_ESTABLISHED:
            {
                  /* If we don't have an EP at this point we are very screwed
                   * up
                   */
                  if (ep_ptr->param.ep_state !=
                      DAT_EP_STATE_ACTIVE_CONNECTION_PENDING) {
                        /* If someone pulled the plug on the connection, just
                         * exit
                         */
                        dapl_os_unlock(&ep_ptr->header.lock);
                        dat_status = DAT_SUCCESS;
                        break;
                  }
                  ep_ptr->param.ep_state = DAT_EP_STATE_CONNECTED;
                  ep_ptr->cm_handle = ib_cm_handle;
                  if (prd_ptr == NULL) {
                        private_data_size = 0;
                  } else {
                        private_data_size =
                            dapls_ib_private_data_size(prd_ptr,
                                                 DAPL_PDATA_CONN_REP,
                                                 ep_ptr->header.
                                                 owner_ia->
                                                 hca_ptr);
                  }

                  if (private_data_size > 0) {
                        /* copy in the private data */
                        dapl_os_memcpy(ep_ptr->private.private_data,
                                     prd_ptr->private_data,
                                     DAPL_MIN(private_data_size,
                                          DAPL_MAX_PRIVATE_DATA_SIZE));
                  }
                  dapl_os_unlock(&ep_ptr->header.lock);

                  break;
            }
      case DAT_CONNECTION_EVENT_PEER_REJECTED:
            {
                  /* peer reject may include private data */
                  if (prd_ptr != NULL)
                        private_data_size =
                            dapls_ib_private_data_size(prd_ptr,
                                                 DAPL_PDATA_CONN_REJ,
                                                 ep_ptr->header.
                                                 owner_ia->
                                                 hca_ptr);

                  if (private_data_size > 0)
                        dapl_os_memcpy(ep_ptr->private.private_data,
                                     prd_ptr->private_data,
                                     DAPL_MIN(private_data_size,
                                          DAPL_MAX_PRIVATE_DATA_SIZE));

                  dapl_dbg_log(DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
                             "dapl_evd_connection_callback PEER REJ pd=%p sz=%d\n",
                             prd_ptr, private_data_size);
            }
      case DAT_CONNECTION_EVENT_DISCONNECTED:
      case DAT_CONNECTION_EVENT_UNREACHABLE:
      case DAT_CONNECTION_EVENT_NON_PEER_REJECTED:
            {
                  ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
                  dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE,
                                      ib_cm_event);
                  dapl_os_unlock(&ep_ptr->header.lock);

                  break;
            }
      case DAT_CONNECTION_EVENT_BROKEN:
      case DAT_CONNECTION_EVENT_TIMED_OUT:
            {
                  ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
                  dapls_ib_disconnect_clean(ep_ptr, DAT_FALSE,
                                      ib_cm_event);
                  dapl_os_unlock(&ep_ptr->header.lock);

                  break;
            }
      case DAT_CONNECTION_REQUEST_EVENT:
      default:
            {
                  dapl_os_unlock(&ep_ptr->header.lock);
                  evd_ptr = NULL;

                  dapl_os_assert(0);      /* shouldn't happen */
                  break;
            }
      }

      /*
       * Post the event
       * If the EP has been freed, the evd_ptr will be NULL
       */
      if (evd_ptr != NULL) {
            dat_status = dapls_evd_post_connection_event(evd_ptr, dat_event_num, (DAT_HANDLE) ep_ptr, private_data_size,      /* CONNECTED or REJECT */
                                               ep_ptr->private.
                                               private_data);

            if (dat_status != DAT_SUCCESS &&
                dat_event_num == DAT_CONNECTION_EVENT_ESTABLISHED) {
                  /* We can't tell the user we are connected, something
                   * is wrong locally. Just kill the connection and
                   * reset the state to DISCONNECTED as we don't
                   * expect a callback on an ABRUPT disconnect.
                   */
                  dapls_ib_disconnect(ep_ptr, DAT_CLOSE_ABRUPT_FLAG);
                  dapl_os_lock(&ep_ptr->header.lock);
                  ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
                  dapl_os_unlock(&ep_ptr->header.lock);
            }
      }

      dapl_dbg_log(DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
                 "dapl_evd_connection_callback () returns\n");

}

/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 *  tab-width: 8
 * End:
 */

Generated by  Doxygen 1.6.0   Back to index