/* * * (c) Copyright 1989 OPEN SOFTWARE FOUNDATION, INC. * (c) Copyright 1989 HEWLETT-PACKARD COMPANY * (c) Copyright 1989 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. * */ /* */ /* ** ** NAME: ** ** dghnd.c ** ** FACILITY: ** ** Remote Procedure Call (RPC) ** ** ABSTRACT: ** ** Routines for manipulating Datagram Specific RPC bindings. ** ** */ #include #include #include #include /* ======================================================================== */ /* * 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 _DCE_PROTOTYPE_(( rpc_dg_binding_client_p_t /*h*/ )); INTERNAL void release_cached_ccall #ifdef _DCE_PROTO_ ( rpc_dg_binding_client_p_t h ) #else (h) rpc_dg_binding_client_p_t h; #endif { 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 #ifdef _DCE_PROTO_ ( boolean32 is_server, unsigned32 *st ) #else (is_server, st) boolean32 is_server; unsigned32 *st; #endif { 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 #ifdef _DCE_PROTO_ ( rpc_binding_rep_p_t h_, unsigned32 *st ) #else (h_, st) rpc_binding_rep_p_t h_; unsigned32 *st; #endif { *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 #ifdef _DCE_PROTO_ ( rpc_binding_rep_p_t *h_, unsigned32 *st ) #else (h_, st) rpc_binding_rep_p_t *h_; unsigned32 *st; #endif { /* * 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 #ifdef _DCE_PROTO_ ( rpc_binding_rep_p_t h, unsigned32 *st ) #else (h, st) rpc_binding_rep_p_t h; unsigned32 *st; #endif { 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 #ifdef _DCE_PROTO_ ( rpc_binding_rep_p_t h ATTRIBUTE_UNUSED, rpc_addr_p_t *addr ATTRIBUTE_UNUSED, unsigned32 *st ATTRIBUTE_UNUSED ) #else (h, addr, st) rpc_binding_rep_p_t h; rpc_addr_p_t *addr; unsigned32 *st; #endif { /* * rpc_m_unimp_call * "(%s) Call not implemented" */ RPC_DCE_SVC_PRINTF (( DCE_SVC(RPC__SVC_HANDLE, "%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 #ifdef _DCE_PROTO_ ( rpc_binding_rep_p_t h_, unsigned32 *st ) #else (h_, st) rpc_binding_rep_p_t h_; unsigned32 *st; #endif { 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 #ifdef _DCE_PROTO_ ( rpc_binding_rep_p_t src_h_, rpc_binding_rep_p_t dst_h_, unsigned32 *st ) #else (src_h_, dst_h_, st) rpc_binding_rep_p_t src_h_; rpc_binding_rep_p_t dst_h_; unsigned32 *st; #endif { 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 #ifdef _DCE_PROTO_ ( rpc_dg_binding_server_p_t shand, unsigned32 *st ) #else (shand, st) rpc_dg_binding_server_p_t shand; unsigned32 *st; #endif { 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 #ifdef _DCE_PROTO_ ( rpc_binding_rep_p_t h_, unsigned32 *st ) #else (h_, st) rpc_binding_rep_p_t h_; unsigned32 *st; #endif { 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 #ifdef _DCE_PROTO_ ( rpc_binding_rep_p_t binding_r ATTRIBUTE_UNUSED, unsigned32 *st ) #else (binding_r, st) rpc_binding_rep_p_t binding_r; unsigned32 *st; #endif { CODING_ERROR (st); /* * This is a dummy function to avoid the null reference * causing a core dump. */ *st = rpc_s_ok; } #endif