PRIVATE rpc_binding_rep_t *rpc__cn_binding_alloc ( boolean32 is_server, unsigned32 *st ) { rpc_cn_binding_rep_p_t brp; CODING_ERROR (st); /* * A server binding is allocated from the receiver thread which * has already acquired the CN global mutex. */ if (!is_server) { RPC_CN_LOCK (); } else { RPC_CN_LOCK_ASSERT (); } /* * Allocate a binding rep off the lookaside list. */ brp = (rpc_cn_binding_rep_p_t) rpc__list_element_alloc (&rpc_g_cn_binding_lookaside_list, true); if (brp == NULL) { *st = rpc_s_no_memory; RPC_CN_UNLOCK (); return NULL; } if (!is_server) { ((rpc_cn_binding_rep_t *)brp)->being_resolved = false; RPC_CN_UNLOCK (); } brp->common.rpc_addr = NULL; brp->common.auth_info = NULL; brp->common.transport_info = NULL; *st = rpc_s_ok; return ((rpc_binding_rep_p_t) brp); }
PRIVATE void rpc__cn_binding_init ( rpc_binding_rep_p_t binding_r, unsigned32 *st ) { unsigned32 type; rpc_cn_local_id_t grp_id; CODING_ERROR (st); /* * Determine the type of association group we are looking for. */ if (RPC_BINDING_IS_SERVER (binding_r)) { type = RPC_C_CN_ASSOC_GRP_SERVER; } else { type = RPC_C_CN_ASSOC_GRP_CLIENT; /* * Use the RPC address contained in the binding rep to find an * association group. */ RPC_CN_LOCK (); grp_id = rpc__cn_assoc_grp_lkup_by_addr (binding_r->rpc_addr, binding_r->transport_info, type, st); /* * Record its the association group id returned into the * binding rep. Note that the group id returned may be invalid. */ ((rpc_cn_binding_rep_t *)binding_r)->grp_id = grp_id; RPC_CN_UNLOCK (); } /* * Return a good status code no matter what happened. */ *st = rpc_s_ok; }
PRIVATE void rpc__cn_call_executor (pointer_t arg, boolean32 call_was_queued ATTRIBUTE_UNUSED) { rpc_binding_rep_t *binding_r; rpc_cn_call_rep_t *call_r; rpc_iovector_t iovector; dce_uuid_t type_uuid; rpc_mgr_epv_t manager_epv; rpc_v2_server_stub_epv_t server_stub_epv; rpc_if_rep_p_t if_spec_rep; unsigned32 flags; unsigned32 max_calls; unsigned32 max_rpc_size; rpc_if_callback_fn_t if_callback; unsigned32 status; RPC_LOG_CN_CTHD_NTR; RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL, ("CN: call_rep->%x call executor running ... %s queued\n", arg, (call_was_queued ? "WAS" : "WAS NOT"))); /* * The arg passed in is really a call rep. */ call_r = (rpc_cn_call_rep_t *) arg; /* * Release the call rep lock which was acquired for us in the * common code. */ RPC_CALL_UNLOCK ((rpc_call_rep_t *) call_r); /* * If there is an object uuid, see if there's a type uuid * associated with it. */ rpc_object_inq_type (&call_r->binding_rep->obj, &type_uuid, &status); if ((status != rpc_s_object_not_found) && (status != rpc_s_ok)) { RPC_CALL_LOCK ((rpc_call_rep_t *) call_r); rpc__cthread_cancel_caf ((rpc_call_rep_t *) call_r); RPC_CALL_UNLOCK ((rpc_call_rep_t *) call_r); RPC_CN_LOCK (); rpc__cn_call_reject ((rpc_call_rep_p_t) call_r, status); RPC_CN_UNLOCK (); goto CLEANUP; } /* * Get the if rep and the server stub and manager EPV. */ rpc__if_lookup2 (call_r->u.server.if_id, call_r->u.server.if_vers, &type_uuid, &call_r->u.server.ihint, &if_spec_rep, &server_stub_epv, &manager_epv, &flags, &max_calls, &max_rpc_size, &if_callback, &status); if (status != rpc_s_ok) { RPC_CALL_LOCK ((rpc_call_rep_t *) call_r); rpc__cthread_cancel_caf ((rpc_call_rep_t *) call_r); RPC_CALL_UNLOCK ((rpc_call_rep_t *) call_r); RPC_CN_LOCK (); rpc__cn_call_reject ((rpc_call_rep_p_t) call_r, status); RPC_CN_UNLOCK (); goto CLEANUP; } /* * If the operation number is out of range, indicate a fault to * the protocol service, otherwise process the incoming packet(s). */ if (call_r->opnum >= if_spec_rep->opcnt) { RPC_CALL_LOCK ((rpc_call_rep_t *) call_r); rpc__cthread_cancel_caf ((rpc_call_rep_t *) call_r); RPC_CALL_UNLOCK ((rpc_call_rep_t *) call_r); RPC_CN_LOCK (); rpc__cn_call_reject ((rpc_call_rep_p_t) call_r, rpc_s_op_rng_error); RPC_CN_UNLOCK (); goto CLEANUP; } /* * Receive the first packet. */ rpc__cn_call_receive ((rpc_call_rep_t *) call_r, &iovector.elt[0], &status); if (status != rpc_s_ok) { RPC_CALL_LOCK ((rpc_call_rep_t *) call_r); rpc__cthread_cancel_caf ((rpc_call_rep_t *) call_r); RPC_CALL_UNLOCK ((rpc_call_rep_t *) call_r); RPC_CN_LOCK (); rpc__cn_call_reject ((rpc_call_rep_p_t) call_r, rpc_s_op_rng_error); RPC_CN_UNLOCK (); goto CLEANUP; } /* * Mark the call as having executed. */ call_r->call_executed = true; /* * Enable posting of cancels to this call executor thread. * This will also post any queued cancels. */ RPC_DBG_PRINTF (rpc_e_dbg_cancel, RPC_C_CN_DBG_CANCEL, ("(rpc__cn_call_executor) call_rep->%x enabling posting of cancels and posting any queued cancels\n", call_r)); RPC_CALL_LOCK ((rpc_call_rep_t *) call_r); rpc__cthread_cancel_enable_post ((rpc_call_rep_p_t) call_r); RPC_CALL_UNLOCK ((rpc_call_rep_t *) call_r); /* * Dispatch appropriately depending on the stub version. */ switch (if_spec_rep->stub_rtl_if_vers) { /* * If this is an old v0 or v1 stub runtime interface * then do the dirty work out of line. */ case 0: case 1: /* * rpc_m_pre_v2_ifspec * "(%s) Pre-v2 interface spec" */ RPC_DCE_SVC_PRINTF (( DCE_SVC(RPC__SVC_HANDLE, "%s"), rpc_svc_server_call, svc_c_sev_fatal | svc_c_action_abort, rpc_m_pre_v2_ifspec, "rpc__cn_call_executor" )); break; /* * This is the v2 (new) stub runtime interface. */ case 2: RPC_LOG_SERVER_STUB_PRE; ((*server_stub_epv[call_r->opnum])) ((handle_t) call_r->binding_rep, (rpc_call_handle_t) call_r, &iovector.elt[0], &(RPC_CN_ASSOC_NDR_FORMAT (call_r->assoc)), &call_r->transfer_syntax, manager_epv, &status); RPC_LOG_SERVER_STUB_POST; break; /* * Unknown version */ default: /* * rpc_m_unk_ifspec * "(%s) Unknown interface spec version" */ RPC_DCE_SVC_PRINTF (( DCE_SVC(RPC__SVC_HANDLE, "%s"), rpc_svc_server_call, svc_c_sev_fatal | svc_c_action_abort, rpc_m_pre_v2_ifspec, "rpc__cn_call_executor" )); break; } /* * Check for an error while in the server stub but before the * manager routine was entered. */ if (status != rpc_s_ok) { RPC_CALL_LOCK ((rpc_call_rep_t *) call_r); rpc__cthread_cancel_caf ((rpc_call_rep_t *) call_r); RPC_CALL_UNLOCK ((rpc_call_rep_t *) call_r); RPC_CN_LOCK (); rpc__cn_call_reject ((rpc_call_rep_p_t) call_r, status); RPC_CN_UNLOCK (); goto CLEANUP; } /* * If the stub returned successfully, end the call and free the binding handle. */ binding_r = (rpc_binding_rep_t *) call_r->binding_rep; RPC_CALL_LOCK ((rpc_call_rep_t *) call_r); rpc__cthread_cancel_caf ((rpc_call_rep_t *) call_r); RPC_CALL_UNLOCK ((rpc_call_rep_t *) call_r); CLEANUP: binding_r = (rpc_binding_rep_t *) call_r->binding_rep; rpc__cn_call_end ((rpc_call_rep_p_t *) &call_r, &status); RPC_LOCK (0); RPC_BINDING_RELEASE (&binding_r, &status); RPC_UNLOCK (0); RPC_LOG_CN_CTHD_XIT; }
PRIVATE void rpc__cn_binding_inq_addr ( rpc_binding_rep_p_t binding_r, rpc_addr_p_t *rpc_addr, unsigned32 *st ) { unsigned32 type; rpc_cn_local_id_t grp_id; rpc_cn_assoc_grp_t *assoc_grp; rpc_protseq_id_t protseq_id; CODING_ERROR (st); /* * Determine the type of association group we are looking for. */ if (RPC_BINDING_IS_SERVER (binding_r)) { type = RPC_C_CN_ASSOC_GRP_SERVER; } else { type = RPC_C_CN_ASSOC_GRP_CLIENT; } /* * Use the group id contained in the binding rep to find an * association group. */ RPC_CN_LOCK (); grp_id = rpc__cn_assoc_grp_lkup_by_id ( ((rpc_cn_binding_rep_t *)binding_r)->grp_id, type, binding_r->transport_info, st); /* * Check whether an association group was found or not. */ if (RPC_CN_LOCAL_ID_VALID (grp_id)) { /* * An association group was found. Check whether it * contains an RPC address. */ assoc_grp = RPC_CN_ASSOC_GRP (grp_id); if (assoc_grp->grp_address != NULL) { /* * The association group contains an RPC address. * Copy it into the binding. */ rpc__naf_addr_copy (assoc_grp->grp_address, rpc_addr, st); } else { /* * The association doesn't have an RPC address. Find * it out using one of the connections attached to the * association group. */ rpc__naf_desc_inq_protseq_id (((rpc_cn_assoc_t *)assoc_grp->grp_assoc_list.next)->cn_ctlblk.cn_sock, RPC_C_PROTOCOL_ID_NCACN, &protseq_id, st); if (*st == rpc_s_ok) { rpc__naf_desc_inq_peer_addr (((rpc_cn_assoc_t *)assoc_grp->grp_assoc_list.next)->cn_ctlblk.cn_sock, protseq_id, rpc_addr, st); if (*st == rpc_s_ok) { rpc__naf_addr_copy (*rpc_addr, &assoc_grp->grp_address, st); } } } binding_r->rpc_addr = *rpc_addr; } else { *st = rpc_s_connection_closed; } RPC_CN_UNLOCK (); }