/************************************************************************/ /* SISCO SOFTWARE MODULE HEADER *****************************************/ /************************************************************************/ /* (c) Copyright Systems Integration Specialists Company, Inc., */ /* 1994 - 2002, All Rights Reserved */ /* */ /* MODULE NAME : c_write.c */ /* PRODUCT(S) : MMSEASE-LITE */ /* */ /* MODULE DESCRIPTION : */ /* */ /* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ /* mvl_write_variables */ /* mvla_write_variables */ /* _mvl_process_write_conf */ /* */ /* MODIFICATION LOG : */ /* Date Who Rev Comments */ /* -------- --- ------ ------------------------------------------- */ /* 04/09/07 MDE 24 Enhanced filtered logging */ /* 01/30/06 GLB 23 Integrated porting changes for VMS */ /* 07/16/02 JRB 22 Skip memmove to front of asn1_buf. */ /* Make sure num vars matches num data. */ /* _mvla_send..: Del unused args, make static. */ /* 03/06/02 JRB 21 Add S_UNLOCK.. before ALL returns. */ /* 02/25/02 MDE 20 Now get max PDU size from mvl_cfg_info */ /* 01/02/02 JRB 19 Converted to use ASN1R (re-entrant ASN1) */ /* 11/01/01 JRB 18 mvl_wait_req_done now returns ST_RET. */ /* 09/21/01 JRB 17 Alloc global bufs only once at startup. */ /* 03/07/01 JRB 16 Del LOCK on sync functs: caused deadlocks. */ /* 03/08/00 JRB 15 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ /* Del mvl_free_req_ctrl call. User must call. */ /* Del invoke_id, numpend_req: see mvl_send_req.*/ /* 01/21/00 MDE 14 Now use MEM_SMEM for dynamic memory */ /* 01/21/00 MDE 13 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ /* 11/19/99 NAV 12 Add #ifdef MVL_REQ_BUF_ENABLED */ /* 10/20/99 NAV 11 Add maxpend_req support to aynsc functions */ /* 09/13/99 MDE 10 Added SD_CONST modifiers */ /* 03/05/99 MDE 09 Fixed NVL write pointer arithmatic problem */ /* 12/08/98 MDE 08 Added client alternate access support */ /* 11/17/98 MDE 07 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ /* Use MVL_SYNC_REQ_INTERFACE */ /* 11/16/98 MDE 06 Renamed internal functions (prefix '_') */ /* 06/15/98 MDE 05 Changes to allow compile under C++ */ /* 05/22/98 JRB 04 Pass (MVL_REQ_PEND**) to sync function also. */ /* 04/16/98 JRB 03 Conf func: Let caller do "common" stuff. */ /* Always set (*req_out) so user can always free*/ /* 02/10/98 MDE 02 Removed NEST_RT_TYPES support */ /* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ /************************************************************************/ #include "glbtypes.h" #include "sysincs.h" #include "glbsem.h" #include "mmsdefs.h" #include "mms_pvar.h" #include "mms_vvar.h" #include "mvl_acse.h" #include "mvl_log.h" static ST_RET _mvla_send_write_variables (MVL_NET_INFO *net_info, WRITE_REQ_INFO *write_info, MVL_REQ_PEND *req_pend); static ST_RET w_get_asn1_data (MVL_WRITE_REQ_INFO *w_info, ST_UCHAR *asn1_dest_buffer, ST_INT asn1_buffer_len, ST_INT *asn1_len_out); /************************************************************************/ /* 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 /************************************************************************/ /************************************************************************/ /* mvl_write_variables */ /************************************************************************/ #if defined(MVL_SYNC_REQ_INTERFACE) ST_RET mvl_write_variables (MVL_NET_INFO *net_info, WRITE_REQ_INFO *write_info, ST_INT num_data, MVL_WRITE_REQ_INFO *w_info, MVL_REQ_PEND **req_out) { ST_RET rc; if (_mvl_comm_serve_active == SD_TRUE) { MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); return (MVL_ERR_COMM_SERVE_ACTIVE); } rc = mvla_write_variables (net_info, write_info, num_data, w_info, req_out); if (rc == SD_SUCCESS) rc = mvl_wait_req_done (*req_out); return (rc); } #endif /************************************************************************/ /* mvla_write_variables */ /************************************************************************/ ST_RET mvla_write_variables (MVL_NET_INFO *net_info, WRITE_REQ_INFO *write_info, ST_INT num_data, MVL_WRITE_REQ_INFO *w_info, MVL_REQ_PEND **req_out) { ST_RET rc; MVL_REQ_PEND *req_pend; VARIABLE_LIST *vl_ptr; VAR_ACC_DATA *va_ptr; ST_UCHAR *asn1_buf; ST_INT asn1_len; ST_INT asn1_buf_left; ST_INT i; *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_WRITE); if (!req_pend) return (MVL_ERR_REQ_CONTROL); req_pend->u.wr.w_info = w_info; req_pend->u.wr.num_data = num_data; S_LOCK_COMMON_RESOURCES (); /* Make the write request operation specific data structure */ /* NOTE: Number of vars MUST match number of data. To be sure, */ /* overwrite values user entered. */ write_info->num_of_data = num_data; write_info->va_spec.num_of_variables = num_data; /* only used if VARLIST*/ vl_ptr = (VARIABLE_LIST *) (write_info+1); if (write_info->va_spec.var_acc_tag == VAR_ACC_NAMEDLIST) write_info->va_data = (VAR_ACC_DATA *) (write_info + 1); else write_info->va_data = (VAR_ACC_DATA *) (vl_ptr + write_info->va_spec.num_of_variables); va_ptr = write_info->va_data; /* encode the data */ asn1_buf = (ST_UCHAR *) M_MALLOC (MSMEM_ASN1_DATA_ENC, mvl_cfg_info->max_msg_size); asn1_buf_left = mvl_cfg_info->max_msg_size; for (i = 0; i < num_data; ++i, vl_ptr++, va_ptr++, w_info++) { rc = w_get_asn1_data(w_info,asn1_buf,asn1_buf_left,&asn1_len); if (rc != SD_SUCCESS) { MVL_LOG_NERR1 ("Write : w_get_asn1_data failed, ret = %x", rc); S_UNLOCK_COMMON_RESOURCES (); return(rc); } else { /* Data encoded at end of asn1_buf. Adjust len so next data */ /* encodes before this data. Save ptr and len. */ asn1_buf_left -= asn1_len; /* adjust buffer control vars */ va_ptr->len = asn1_len; va_ptr->data = asn1_buf + asn1_buf_left; #if defined(MVL_AA_SUPP) if (w_info->alt_acc_pres) { rc = _mvl_get_asn1_aa (w_info[i].alt_acc, vl_ptr); if (rc != SD_SUCCESS) { MVL_LOG_NERR0 ("Error creating ASN.1 encoded Alternate Access"); S_UNLOCK_COMMON_RESOURCES (); return (SD_FAILURE); } } #endif } } rc = _mvla_send_write_variables (net_info, write_info, req_pend); M_FREE (MSMEM_ASN1_DATA_ENC, asn1_buf); S_UNLOCK_COMMON_RESOURCES (); return (rc); } /************************************************************************/ /* _mvla_send_write_variables */ /************************************************************************/ static ST_RET _mvla_send_write_variables (MVL_NET_INFO *net_info, WRITE_REQ_INFO *write_info, MVL_REQ_PEND *req_pend) { ST_RET rc; /* Build a write request */ rc = mpl_write (write_info); if (rc == SD_SUCCESS) mpl_req_log (req_pend, write_info); #if defined(MVL_AA_SUPP) _m_free_aa_asn1_buf (); #endif rc = _mvl_send_req (net_info, req_pend, rc); return (rc); } /************************************************************************/ /* w_get_asn1_data */ /************************************************************************/ /* This function is to provide ASN.1 encoded data, given the variable */ /* list element. */ static ST_RET w_get_asn1_data (MVL_WRITE_REQ_INFO *wr_info, ST_UCHAR *asn1_dest_buffer, ST_INT asn1_buffer_len, ST_INT *asn1_len_out) { RUNTIME_TYPE *rt; ST_INT num_rt; ST_RET rc; ST_UCHAR *asn1_start; ST_INT asn1_len; ST_BOOLEAN packed_save; ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ ASN1_ENC_CTXT *aCtx = &localEncCtx; rc = mvl_get_runtime (wr_info->type_id,&rt, &num_rt); if (rc != SD_SUCCESS) { MVL_LOG_NERR1 ("Get ASN1 Data : mvl_get_runtime failed, rc = %x", rc); return (rc); /* bad type id */ } /* Check to see if this is an array with variable number of elements */ /* and modify the size if necessary - */ if (wr_info->arr) mvl_mod_arr_size (rt, wr_info->num_el); /* First we need to initialize the ASN.1 encode tools, then do the */ /* encode */ asn1r_strt_asn1_bld (aCtx, asn1_dest_buffer, asn1_buffer_len); #if defined(MVL_AA_SUPP) if (wr_info->alt_acc_pres && wr_info->alt_acc_type_aa == SD_FALSE) { packed_save = m_alt_acc_packed; m_alt_acc_packed = wr_info->alt_acc_data_packed; rc = ms_local_to_asn1_aa (aCtx, rt, num_rt, wr_info->alt_acc, (ST_CHAR *) wr_info->local_data); m_alt_acc_packed = packed_save; } else rc = ms_local_to_asn1 (aCtx, rt, num_rt, (ST_CHAR *) wr_info->local_data); #else rc = ms_local_to_asn1 (aCtx, rt, num_rt, (ST_CHAR *) wr_info->local_data); #endif /* #if defined(MVL_AA_SUPP) */ if (rc != SD_SUCCESS) { MVL_LOG_NERR1 ("Get ASN1 Data : ms_local_to_asn1 failed, rc = %x", rc); return (rc); /* bad type id */ } /* When the ASN.1 encode is complete, 'asn1_field_ptr' points 1 byte ahead */ /* of the start of the message. The ASN.1 message is build from back to */ /* front, so that is now we calculate the length of the PDU */ asn1_start = aCtx->asn1r_field_ptr+1; asn1_len = (asn1_dest_buffer + asn1_buffer_len) - asn1_start; *asn1_len_out = asn1_len; return (rc); } /************************************************************************/ /* _mvl_process_write_conf */ /************************************************************************/ ST_VOID _mvl_process_write_conf (MVL_REQ_PEND *req) { ST_INT i; WRITE_RESP_INFO *write_info; WRITE_RESULT *wr_rslt; ST_INT num_variables; MVL_WRITE_REQ_INFO *w_info; write_info = (WRITE_RESP_INFO *) req->event->u.mms.dec_rslt.data_ptr; wr_rslt = (WRITE_RESULT *) (write_info+1); /* retrieve output information */ w_info = req->u.wr.w_info; num_variables = req->u.wr.num_data; /* just a sanity check */ if (num_variables != write_info->num_of_result) { req->result = SD_FAILURE; return; } /* For each variable returned in the write response ... */ for (i=0; i < num_variables; i++, wr_rslt++, w_info++) { /* check for successful write of this variable */ if (wr_rslt->resp_tag == WR_RSLT_SUCCESS) w_info->result = SD_SUCCESS; else /* bad type ID */ w_info->result = SD_FAILURE; } /* for each variable */ }