Files
microser/mmslib/mvlu/s_read.c
2026-06-15 15:48:16 +08:00

450 lines
16 KiB
C

/*******************************************************************/
/* SISCO SOFTWARE MODULE HEADER *****************************************/
/************************************************************************/
/* (c) Copyright Systems Integration Specialists Company, Inc., */
/* 1994 - 2005, All Rights Reserved */
/* */
/* MODULE NAME : s_read.c */
/* PRODUCT(S) : MMSEASE-LITE */
/* */
/* MODULE DESCRIPTION : */
/* */
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
/* NONE */
/* */
/* MODIFICATION LOG : */
/* Date Who Rev Comments */
/* -------- --- ------ ------------------------------------------- */
/* 01/23/09 JRB 30 Deal with non-named variables better */
/* 04/09/07 MDE 29 Enhanced filtered logging */
/* 10/30/06 JRB 28 Use new mvl_vmd_* object handling functions. */
/* Add args on call to _mvl_objname_to_va. */
/* Elim use of global "_mvl_curr_usr_ind_ctrl". */
/* 08/09/06 JRB 27 For MVL_UCA, call mvl_find_nvl */
/* (DO NOT call u_mvl_get_nvl, u_mvl_free_nvl). */
/* 01/30/06 GLB 26 Integrated porting changes for VMS */
/* 10/19/05 JRB 25 Fix spec_in_result handling (was ignored). */
/* 05/16/05 JRB 24 Send appropriate failure codes in read resp. */
/* 12/12/02 JRB 23 Add net_info arg to mvl_get_va_asn1_data & */
/* prep_.. functions to elim use of */
/* mvl_curr_net_info global var. */
/* 07/24/02 JRB 22 Use mvl_send_resp_i like ALL responses. */
/* 07/09/02 MDE 21 Add maxpend_ind support */
/* 02/25/02 MDE 20 Now get max PDU size from mvl_cfg_info */
/* 09/21/01 JRB 19 Alloc global bufs only once at startup. */
/* 03/30/01 MDE 18 Changed MSMEM_ENC_INFO to MSMEM_ENC_OS_INFO */
/* 10/25/00 JRB 17 Del u_mvl funct ptrs. Call functs directly. */
/* Control with #ifdefs. */
/* 06/19/00 JRB 16 Free rdCtrl->vaCtrlTbl on error. */
/* 05/15/00 MDE 15 Added MMS statistics */
/* 03/10/00 JRB 14 Copy va_scope to appropriate structures. */
/* 01/21/00 MDE 13 Now use MEM_SMEM for dynamic memory */
/* 11/22/99 JRB 12 mvlas_read_resp: del indCtrl from link list */
/* 09/13/99 MDE 11 Added SD_CONST modifiers */
/* 04/07/99 MDE 10 Logging improvements */
/* 01/15/99 JRB 09 IF (u_mvl_get_nvl_fun != NULL) call it, */
/* ELSE call "mvl_find_nvl". */
/* 12/11/98 MDE 08 Removed scope references from VA */
/* 11/16/98 MDE 07 Renamed internal functions (prefix '_') */
/* 11/10/98 MDE 06 Moved 'mvl_get_va_asn1_data' to mvl_var.c */
/* 06/15/98 MDE 05 Changes to allow compile under C++ */
/* 05/15/98 JRB 04 Chg mvl_process.. arg to (MVL_IND_PEND *). */
/* 05/15/98 JRB 03 Call u_mvl_read_ind direct (no funct ptr). */
/* 02/10/98 MDE 02 Removed NEST_RT_TYPES, always support AA, */
/* added 'u_mvl_rd_ind_start' and */
/* 'u_mvl_rd_resp_sent', other */
/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */
/************************************************************************/
#include "glbtypes.h"
#include "sysincs.h"
#include "mmsdefs.h"
#include "mms_pvar.h"
#include "mms_vvar.h"
#include "mvl_acse.h"
#include "mvl_log.h"
/************************************************************************/
/* For debug version, use a static pointer to avoid duplication of */
/* __FILE__ strings. */
/************************************************************************/
#ifdef DEBUG_SISCO
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
#endif
/************************************************************************/
/************************************************************************/
ST_RET (*u_mvl_rd_ind_start) (MVL_IND_PEND *indCtrl);
ST_VOID (*u_mvl_rd_resp_sent) (MVL_IND_PEND *indCtrl);
/************************************************************************/
/************************************************************************/
/* Internal functions */
static ST_RET prep_lov_rd_ctrl (MVL_IND_PEND *indCtrl, READ_REQ_INFO *read_info,
MVLAS_READ_CTRL *rdCtrlOut);
static ST_RET prep_nvl_rd_ctrl (MVL_IND_PEND *indCtrl, MVL_NET_INFO *net_info, READ_REQ_INFO *read_info,
MVLAS_READ_CTRL *rdCtrlOut);
static ST_RET prep_read_resp (MVL_NET_INFO *net_info, MVLAS_READ_CTRL *rdCtrl,
READ_REQ_INFO *req_info,
READ_RESP_INFO **resp_info_out,
ST_UCHAR *asn1_buf, ST_INT asn1_buf_size);
/************************************************************************/
/************************************************************************/
/* _mvl_process_read_ind */
/************************************************************************/
ST_VOID _mvl_process_read_ind (MVL_IND_PEND *indCtrl)
{
READ_REQ_INFO *read_info;
MVLAS_READ_CTRL *rdCtrl;
ST_RET rc;
rdCtrl = &indCtrl->u.rd;
read_info = (READ_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr;
rdCtrl->var_acc_tag = read_info->va_spec.var_acc_tag;
rc = SD_SUCCESS;
if (u_mvl_rd_ind_start)
{
/* This might set optional user pointer "indCtrl->usr_ind_ctrl". */
rc = (*u_mvl_rd_ind_start) (indCtrl);
}
if (rc == SD_SUCCESS)
{
if (rdCtrl->var_acc_tag == VAR_ACC_NAMEDLIST)
rc = prep_nvl_rd_ctrl (indCtrl, indCtrl->event->net_info, read_info, rdCtrl);
else
rc = prep_lov_rd_ctrl (indCtrl, read_info, rdCtrl);
}
if (rc == SD_SUCCESS)
{
u_mvl_read_ind (indCtrl);
}
else
{
_mplas_err_resp (indCtrl,7,2);
}
}
/************************************************************************/
/* prep_lov_rd_ctrl */
/************************************************************************/
static ST_RET prep_lov_rd_ctrl (MVL_IND_PEND *indCtrl, READ_REQ_INFO *read_info,
MVLAS_READ_CTRL *rdCtrl)
{
MVLAS_RD_VA_CTRL *vaCtrl;
VARIABLE_LIST *vl;
ST_INT num_var;
ST_INT i;
ST_BOOLEAN alt_access_pres;
/* This is a list of variables */
/* Allocate the read control data structures */
num_var = read_info->va_spec.num_of_variables;
rdCtrl->vaCtrlTbl = (MVLAS_RD_VA_CTRL *) M_CALLOC (MSMEM_GEN, num_var,
sizeof(MVLAS_RD_VA_CTRL));
vaCtrl = rdCtrl->vaCtrlTbl;
rdCtrl->numVar = num_var;
/* Prepare to process each variable in the list */
vl = (VARIABLE_LIST *) (read_info + 1);
for (i = 0; i < num_var; ++i, ++vl, ++vaCtrl)
{
ST_BOOLEAN alt_access_done = SD_FALSE; /* chg if AA processed */
/* These are done by the 'chk_calloc' call */
/* vaCtrl->va = NULL; */
/* vaCtrl->alt_access_pres = SD_FALSE; */
vaCtrl->acc_rslt_tag = ACC_RSLT_SUCCESS;
alt_access_pres = vl->alt_access_pres;
if (alt_access_pres) /* no alternate access support now */
{
#if !defined(MVL_AA_SUPP)
MVL_LOG_NERR0 ("Read Indication : Alternate Access not supported");
continue;
#else
/* now create the AA, given the ASN.1 spec */
if (ms_asn1_to_aa (vl->alt_access.data, vl->alt_access.len,
&vaCtrl->alt_acc))
{
MVL_LOG_NERR0 ("Read Indication : ASN.1 -> AA failure");
continue;
}
vaCtrl->alt_access_pres = SD_TRUE;
#endif
}
switch (vl->var_spec.var_spec_tag)
{
case VA_SPEC_NAMED :
vaCtrl->va = _mvl_objname_to_va (&mvl_vmd, indCtrl->event->net_info, MMSOP_READ, &vl->var_spec.vs.name,
&vaCtrl->va_scope,
alt_access_pres,
&vaCtrl->alt_acc,
&alt_access_done);
if (!vaCtrl->va)
{
MVL_LOG_NERR1 ("Read ind : Variable Association '%s' not found",
vl->var_spec.vs.name.obj_name.vmd_spec);
}
break;
case VA_SPEC_ADDRESSED:
case VA_SPEC_DESCRIBED:
case VA_SPEC_SCATTERED:
case VA_SPEC_INVALIDATED:
default :
MVL_LOG_NERR1 ("Read: Unsupported MMS VariableSpecification Tag %d", vl->var_spec.var_spec_tag);
/* NOTE: "vaCtrl->va = NULL" already. That's GOOD. */
break;
}
if (vaCtrl->va)
vaCtrl->va->usr_ind_ctrl = indCtrl->usr_ind_ctrl; /* save optional user pointer in va*/
/* If alt_acc allocated, free it now if done with it, or if va not found.*/
if (alt_access_pres && (alt_access_done || vaCtrl->va==NULL))
{
M_FREE (MSMEM_GEN, vaCtrl->alt_acc.aa);
vaCtrl->alt_access_pres = SD_FALSE;
}
}
return (SD_SUCCESS);
}
/************************************************************************/
/* prep_nvl_rd_ctrl */
/************************************************************************/
static ST_RET prep_nvl_rd_ctrl (MVL_IND_PEND *indCtrl, MVL_NET_INFO *net_info, READ_REQ_INFO *read_info,
MVLAS_READ_CTRL *rdCtrl)
{
MVL_NVLIST_CTRL *nvList;
MVLAS_RD_VA_CTRL *vaCtrl;
ST_INT i;
ST_INT num_var;
/* search for the NVL */
#if defined(USE_MANUFACTURED_OBJS)
nvList = u_mvl_get_nvl (MMSOP_READ, &read_info->va_spec.vl_name,
net_info);
#else /* default */
nvList = mvl_vmd_find_nvl (&mvl_vmd, &read_info->va_spec.vl_name, indCtrl->event->net_info);
#endif /* default */
if (!nvList)
{
MVL_LOG_NERR0 ("Read NVL : NamedVariableList not found");
return (MVL_ERR_NVL_NOT_FOUND);
}
rdCtrl->nvList = nvList;
/* Found the named variable list, create the response */
num_var = nvList->num_of_entries;
rdCtrl->vaCtrlTbl = (MVLAS_RD_VA_CTRL *) M_CALLOC (MSMEM_GEN, num_var,
sizeof(MVLAS_RD_VA_CTRL));
vaCtrl = rdCtrl->vaCtrlTbl;
rdCtrl->numVar = num_var;
for (i = 0; i < num_var; ++i, ++vaCtrl)
{
/* These are done by the 'chk_calloc' call */
/* vaCtrl->va = NULL; */
/* vaCtrl->alt_access_pres = NULL; */
vaCtrl->va = nvList->entries[i];
memcpy (&vaCtrl->va_scope, &nvList->va_scope[i], sizeof(MVL_SCOPE));
vaCtrl->acc_rslt_tag = ACC_RSLT_SUCCESS;
vaCtrl->va->usr_ind_ctrl = indCtrl->usr_ind_ctrl; /* save optional user pointer in va*/
}
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
/* mvlas_read_resp */
/************************************************************************/
ST_RET mvlas_read_resp (MVL_IND_PEND *indCtrl)
{
MVLAS_READ_CTRL *rdCtrl;
MVL_COMM_EVENT *event;
MVL_NET_INFO *net_info;
READ_RESP_INFO *resp_info;
ST_UCHAR *asn1_buf;
ST_RET rc;
READ_REQ_INFO *req_info = (READ_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr;
event = indCtrl->event;
net_info = indCtrl->event->net_info;
rdCtrl = &indCtrl->u.rd;
asn1_buf = (ST_UCHAR *) M_MALLOC (MSMEM_ASN1_DATA_ENC, mvl_cfg_info->max_msg_size);
rc = prep_read_resp (net_info, rdCtrl, req_info, &resp_info, asn1_buf, mvl_cfg_info->max_msg_size);
if (rc == SD_SUCCESS)
{
/* Build the read response */
rc = mpl_read_resp (event->u.mms.dec_rslt.id, resp_info);
if (rc == SD_SUCCESS)
mpl_resp_log (indCtrl, resp_info);
/* The process functions allocate the response buffer */
M_FREE (MSMEM_ENC_OS_INFO, resp_info);
}
#if defined(USE_MANUFACTURED_OBJS)
if (rdCtrl->nvList) /* For NVL, this was allocated by prep_nvl_... */
u_mvl_free_nvl (MMSOP_READ, rdCtrl->nvList, event->net_info);
#endif
if (u_mvl_rd_resp_sent)
(*u_mvl_rd_resp_sent) (indCtrl);
M_FREE (MSMEM_ASN1_DATA_ENC, asn1_buf);
M_FREE (MSMEM_GEN, rdCtrl->vaCtrlTbl);
/* NOTE: This funct frees indCtrl. DO NOT use after this. */
/* NOTE: if rc != SD_SUCCESS, this funct sends error resp. */
_mvl_send_resp_i (indCtrl, rc);
return (SD_SUCCESS);
}
/************************************************************************/
/* prep_read_resp */
/************************************************************************/
static ST_RET prep_read_resp (MVL_NET_INFO *net_info, MVLAS_READ_CTRL *rdCtrl,
READ_REQ_INFO *req_info,
READ_RESP_INFO **resp_info_out,
ST_UCHAR *asn1_buf, ST_INT asn1_buf_size)
{
MVLAS_RD_VA_CTRL *vaCtrl;
MVL_VAR_ASSOC *va;
READ_RESP_INFO *resp_info;
ACCESS_RESULT *ar_ptr;
ST_UCHAR *asn1_start;
ST_INT asn1_len;
ST_INT asn1_buf_left;
ST_INT num_var;
ST_INT i;
num_var = rdCtrl->numVar;
/* Allocate READ_RESP_INFO struct plus space for variableAccessSpec */
/* (only used if spec_in_result=TRUE) and accessResults. */
resp_info =
(READ_RESP_INFO *) M_CALLOC (MSMEM_ENC_OS_INFO, 1, sizeof (READ_RESP_INFO) +
(num_var * sizeof (VARIABLE_LIST)) + /* for variableAccessSpec*/
(num_var * sizeof (ACCESS_RESULT)));
*resp_info_out = resp_info;
if (req_info->spec_in_result)
{ /* Send variableAccessSpec in response */
resp_info->va_spec_pres = SD_TRUE;
resp_info->va_spec.var_acc_tag = req_info->va_spec.var_acc_tag;
if (resp_info->va_spec.var_acc_tag == VAR_ACC_VARLIST)
{ /* list of variables */
/* Copy variableAccessSpec (array of VARIABLE_LIST) from req to resp.*/
resp_info->va_spec.num_of_variables = num_var;
memcpy ((resp_info + 1), (req_info + 1), num_var * sizeof (VARIABLE_LIST));
}
else
{ /* variable list name : copy name from req to resp. */
memcpy (&resp_info->va_spec.vl_name, &req_info->va_spec.vl_name, sizeof (OBJECT_NAME));
}
}
else
{ /* Do NOT send variableAccessSpec in response. */
resp_info->va_spec_pres = SD_FALSE;
}
resp_info->num_of_acc_result = num_var;
/* Calculate pointer to start of accessResults (after variableAccessSpec)*/
resp_info->acc_rslt_list = (ACCESS_RESULT *)
((((VARIABLE_LIST *)(resp_info+1)) + num_var));
ar_ptr = resp_info->acc_rslt_list;
asn1_start = asn1_buf;
asn1_buf_left = asn1_buf_size;
vaCtrl = rdCtrl->vaCtrlTbl;
for (i = 0; i < num_var; ++i, ++ar_ptr, ++vaCtrl)
{
va = vaCtrl->va;
if (va == NULL)
{
ar_ptr->acc_rslt_tag = ACC_RSLT_FAILURE;
ar_ptr->failure = ARE_OBJ_NONEXISTENT;
}
else
{
/* Copy values from vaCtrl, but may change due to other errors. */
ar_ptr->acc_rslt_tag = vaCtrl->acc_rslt_tag;
ar_ptr->failure = vaCtrl->failure;
if (ar_ptr->acc_rslt_tag == ACC_RSLT_SUCCESS)
{ /* may still fail other checks */
/* Sanity check, because foundry can generate configured variables w/o */
/* the data pointer initialized. */
if (va->data == NULL)
{ /* Error. Override values set before */
MVL_LOG_NERR1 ("Read Indication : va '%s' data is NULL", va->name);
ar_ptr->acc_rslt_tag = ACC_RSLT_FAILURE;
ar_ptr->failure = ARE_OBJ_INVALIDATED;
}
else if (mvl_get_va_asn1_data (net_info,
va, vaCtrl->alt_access_pres, &vaCtrl->alt_acc,
asn1_start, asn1_buf_left, &asn1_len) != SD_SUCCESS)
{ /* Error. Override values set before */
ar_ptr->acc_rslt_tag = ACC_RSLT_FAILURE;
ar_ptr->failure = ARE_OBJ_ACC_UNSUPPORTED;
}
else
{ /* this is the only path to success */
ar_ptr->va_data.len = asn1_len;
ar_ptr->va_data.data = asn1_start;
asn1_buf_left -= asn1_len; /* adjust buffer control variables */
asn1_start += asn1_len;
}
}
}
/* IMPORTANT: Use ar_ptr->acc_rslt_tag here (not vaCtrl->acc_rslt_tag).*/
if (ar_ptr->acc_rslt_tag == ACC_RSLT_SUCCESS)
++mvl_mms_statistics.serverVarRdOk;
else
++mvl_mms_statistics.serverVarRdErr;
/* The user needs to free a manufactured NVL and the associated VA's */
/* in the 'u_mvl_free_va_fun'; here just free manufactured variables */
/* associated with a list of variables. */
#if defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS)
if (rdCtrl->var_acc_tag == VAR_ACC_VARLIST)
{
if (va && va->va_to_free != NULL)
u_mvl_free_va (MMSOP_READ, va, net_info);
}
#endif /* defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS) */
#if defined(MVL_AA_SUPP)
if (vaCtrl->alt_access_pres) /* if we calloc'd this AA, free it */
M_FREE (MSMEM_GEN, vaCtrl->alt_acc.aa);
#endif
} /* end loop */
return (SD_SUCCESS);
}