dghnd.c   [plain text]


/*
 * Copyright (c) 2010 Apple Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Portions of this software have been released under the following terms:
 *
 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
 *
 * To anyone who acknowledges that this file is provided "AS IS"
 * without any express or implied warranty:
 * permission to use, copy, modify, and distribute this file for any
 * purpose is hereby granted without fee, provided that the above
 * copyright notices and this notice appears in all source code copies,
 * and that none of the names of Open Software Foundation, Inc., Hewlett-
 * Packard Company or Digital Equipment Corporation be used
 * in advertising or publicity pertaining to distribution of the software
 * without specific, written prior permission.  Neither Open Software
 * Foundation, Inc., Hewlett-Packard Company nor Digital
 * Equipment Corporation makes any representations about the suitability
 * of this software for any purpose.
 *
 * Copyright (c) 2007, Novell, Inc. All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Novell Inc. nor the names of its contributors
 *     may be used to endorse or promote products derived from this
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @APPLE_LICENSE_HEADER_END@
 */

/*
**
**  NAME:
**
**      dghnd.c
**
**  FACILITY:
**
**      Remote Procedure Call (RPC)
**
**  ABSTRACT:
**
**  Routines for manipulating Datagram Specific RPC bindings.
**
**
*/

#include <dg.h>
#include <dghnd.h>
#include <dgcall.h>
#include <dgccall.h>

/* ======================================================================== */

/*
 * R E L E A S E _ C A C H E D _ C C A L L
 *
 * Release any client call binding we might have in the binding binding.
 */

INTERNAL void release_cached_ccall (
        rpc_dg_binding_client_p_t /*h*/
    );

INTERNAL void release_cached_ccall
(
    rpc_dg_binding_client_p_t h
)
{
    if (h->ccall == NULL)
        return;

    RPC_DG_CALL_LOCK(&h->ccall->c);
    rpc__dg_ccall_free_prep(h->ccall);
    RPC_DG_CCALL_RELEASE(&h->ccall);
    /* unlocks as a side effect */
}

/*
 * R P C _ _ D G _ B I N D I N G _ A L L O C
 *
 * Allocate a DG-specific binding rep.
 */

PRIVATE rpc_binding_rep_p_t rpc__dg_binding_alloc
(
    boolean32 is_server,
    unsigned32 *st
)
{
    rpc_binding_rep_p_t h;

    *st = rpc_s_ok;

    if (is_server)
    {
        RPC_MEM_ALLOC(h, rpc_binding_rep_p_t, sizeof(rpc_dg_binding_server_t),
                        RPC_C_MEM_DG_SHAND, RPC_C_MEM_NOWAIT);
    }
    else
    {
        RPC_MEM_ALLOC(h, rpc_binding_rep_p_t, sizeof(rpc_dg_binding_client_t),
                        RPC_C_MEM_DG_CHAND, RPC_C_MEM_NOWAIT);
    }

    return(h);
}

/*
 * R P C _ _ D G _ B I N D I N G _ I N I T
 *
 * Initialize the DG-specific part of a client binding binding.
 */

PRIVATE void rpc__dg_binding_init
(
    rpc_binding_rep_p_t h_,
    unsigned32 *st
)
{
    *st = rpc_s_ok;

    if (RPC_BINDING_IS_SERVER(h_))
    {
        rpc_dg_binding_server_p_t h = (rpc_dg_binding_server_p_t) h_;

        h->chand        = NULL;
        h->scall        = NULL;
    }
    else
    {
        rpc_dg_binding_client_p_t h = (rpc_dg_binding_client_p_t) h_;

        h->ccall          = NULL;
        h->server_boot    = 0;
        h->shand          = NULL;
        h->maint_binding  = NULL;
        h->is_WAY_binding = 0;
    }
}

/*
 * R P C _ _ D G _ B I N D I N G _ F R E E
 *
 * Free a DG-specific, client-side binding binding.
 */

PRIVATE void rpc__dg_binding_free
(
    rpc_binding_rep_p_t *h_,
    unsigned32 *st
)
{
    /*
     * The binding and the call binding are public at this point (remember
     * the call monitor) hence we need to ensure that things remain
     * orderly.
     */
    RPC_LOCK_ASSERT(0);

    if ((*h_)->is_server == 0)
    {
        release_cached_ccall((rpc_dg_binding_client_p_t) *h_);
        RPC_MEM_FREE(*h_, RPC_C_MEM_DG_CHAND);
    }
    else
    {
        RPC_MEM_FREE(*h_, RPC_C_MEM_DG_SHAND);
    }

    *h_ = NULL;

    *st = rpc_s_ok;
}

/*
 * R P C _ _ D G _ B I N D I N G _ C H A N G E D
 *
 *
 */

PRIVATE void rpc__dg_binding_changed
(
    rpc_binding_rep_p_t h,
    unsigned32 *st
)
{
    RPC_LOCK(0);    /* !!! this should really be done in common code */

    release_cached_ccall((rpc_dg_binding_client_p_t) h);    /* !!! Crude but effective.  Sufficient? */
    *st = rpc_s_ok;

    RPC_UNLOCK(0);
}

/*
 * R P C _ _ D G _ B I N D I N G _ I N Q _ A D D R
 *
 *
 */

PRIVATE void rpc__dg_binding_inq_addr
(
    rpc_binding_rep_p_t h ATTRIBUTE_UNUSED,
    rpc_addr_p_t *addr ATTRIBUTE_UNUSED,
    unsigned32 *st ATTRIBUTE_UNUSED
)
{
    /*
     * rpc_m_unimp_call
     * "(%s) Call not implemented"
     */
    rpc_dce_svc_printf (
        __FILE__, __LINE__,
        "%s",
        rpc_svc_general,
        svc_c_sev_fatal | svc_c_action_abort,
        rpc_m_unimp_call,
        "rpc__dg_binding_inq_addr" );
}

/*
 * R P C _ _ D G _ B I N D I N G _ R E S E T
 *
 * Dissociate the binding from a bound server instance.
 */

PRIVATE void rpc__dg_binding_reset
(
    rpc_binding_rep_p_t h_,
    unsigned32 *st
)
{
    rpc_dg_binding_client_p_t h = (rpc_dg_binding_client_p_t) h_;

    RPC_LOCK(0);    /* !!! this should really be done in common code */

    h->server_boot   = 0;
    release_cached_ccall(h);    /* Crude but effective */
    *st = rpc_s_ok;

    RPC_UNLOCK(0);
}

/*
 * R P C _ _ D G _ B I N D I N G _ C O P Y
 *
 * Copy DG private part of a binding.
 */

PRIVATE void rpc__dg_binding_copy
(
    rpc_binding_rep_p_t src_h_,
    rpc_binding_rep_p_t dst_h_,
    unsigned32 *st
)
{
    rpc_dg_binding_client_p_t src_h = (rpc_dg_binding_client_p_t) src_h_;
    rpc_dg_binding_client_p_t dst_h = (rpc_dg_binding_client_p_t) dst_h_;

    RPC_LOCK(0);    /* !!! this should really be done in common code */

    dst_h->server_boot = src_h->server_boot;
    dst_h->host_bound  = src_h->host_bound;

    *st = rpc_s_ok;

    RPC_UNLOCK(0);
}

/*
 * R P C _ _ D G _ B I N D I N G _ S E R V E R _ T O _ C L I E N T
 *
 * Create a client binding binding suitable for doing callbacks from a
 * server to a client.  The server binding binding of the current call
 * is used as a template for the new client binding.
 */

PRIVATE rpc_dg_binding_client_p_t rpc__dg_binding_srvr_to_client
(
    rpc_dg_binding_server_p_t shand,
    unsigned32 *st
)
{
    rpc_dg_binding_client_p_t chand;
    rpc_addr_p_t   client_addr;

    *st = rpc_s_ok;

    /*
     * If we've already made a callback on this binding binding,
     * then use the client binding binding that was previously
     * created.
     */

    if (shand->chand != NULL)
        return(shand->chand);

    /*
     * Otherwise, allocate a client binding binding and bind it to the
     * address associated with the server binding binding.
     */

    rpc__naf_addr_copy(shand->c.c.rpc_addr, &client_addr, st);
    chand = (rpc_dg_binding_client_p_t)
        rpc__binding_alloc(false, &UUID_NIL, RPC_C_PROTOCOL_ID_NCADG,
                                   client_addr, st);
    if (*st != rpc_s_ok)
        return(NULL);

    /*
     * Link the binding bindings.
     */

    chand->shand = shand;
    shand->chand = chand;

    return(chand);
}

/*
 * R P C _ _ D G _ B I N D I N G _ C R O S S _ F O R K
 *
 * This routine makes it possible for children of forks to use
 * binding handles inherited from their parents.  It does this
 * by vaporizing any state associated with the handle, so that
 * the child is forced to rebuild its own state from scratch.
 */

PRIVATE void rpc__dg_binding_cross_fork
(
    rpc_binding_rep_p_t h_,
    unsigned32 *st
)
{
    rpc_dg_binding_client_p_t h = (rpc_dg_binding_client_p_t) h_;

    *st = rpc_s_ok;

    /*
     * Drop any state associated with this handle.  This state
     * survives in the parent of the fork, and will be processed
     * correctly there.
     */
    h->ccall = NULL;
    h->shand = NULL;
    h->maint_binding = NULL;
}

#if 0

/*
**++
**
**  ROUTINE NAME:       rpc__cn_binding_cross_fork
**
**  SCOPE:              PRIVATE - declared in cnbind.h
**
**  DESCRIPTION:
**
**      This routine makes it possible for children of forks to use
**      binding handles inherited from their parents.
**
**  INPUTS:
**
**      binding_r       The binding rep to be inherited
**
**  INPUTS/OUTPUTS:     none
**
**  OUTPUTS:
**
**      st              The return status of this routine.
**
**  IMPLICIT INPUTS:    none
**
**  IMPLICIT OUTPUTS:   none
**
**  FUNCTION VALUE:
**
**      rpc_s_coding_error
**      rpc_s_ok
**
**  SIDE EFFECTS:       none
**
**--
**/

PRIVATE void rpc__cn_binding_cross_fork
(
  rpc_binding_rep_p_t     binding_r ATTRIBUTE_UNUSED,
  unsigned32              *st
)
{
    CODING_ERROR (st);

    /*
     * This is a dummy function to avoid the null reference
     * causing a core dump.
     */

    *st = rpc_s_ok;
}
#endif