Files
microser/mmslib/mvlu/mvl_serv.c

1070 lines
37 KiB
C
Raw Normal View History

2026-06-15 15:48:16 +08:00
/************************************************************************/
/* SISCO SOFTWARE MODULE HEADER *****************************************/
/************************************************************************/
/* (c) Copyright Systems Integration Specialists Company, Inc., */
/* 1994 - 2005, All Rights Reserved */
/* */
/* MODULE NAME : mvl_serv.c */
/* PRODUCT(S) : MMSEASE-LITE */
/* */
/* MODULE DESCRIPTION : */
/* */
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
/* NONE */
/* */
/* MODIFICATION LOG : */
/* Date Who Rev Comments */
/* -------- --- ------ ------------------------------------------- */
/* 06/24/08 MDE 63 Added _mvl_persist_aa_objs */
/* 05/20/08 JRB 62 Fix handling of MMSCNCLERR (Conclude ERROR). */
/* 04/22/08 JRB 61 Move "active" chk inside semaphore lock. */
/* Del unused MVLULOG_TIMING. */
/* 03/05/08 JRB 60 Call _mvl_clear_aa_objs in ..net_req_done */
/* 10/04/07 MDE 59 Tweaked LOGCFG_VALUE_GROUP/LOGCFGX_VALUE_MAP */
/* 04/09/07 MDE 58 Enhanced filtered logging */
/* 10/30/06 JRB 57 Del _mvl_curr_net_info, _mvl_curr_usr_ind_ctrl.*/
/* 08/03/07 NAV 56 mvl_msg_rcvd - return after sending reject */
/* 01/30/06 GLB 55 Integrated porting changes for VMS */
/* 09/08/05 JRB 54 _mvl_send_reject: set rej_info->pdu_type, */
/* send right class/code on request decode err. */
/* Remove duplicate log msg. */
/* 07/13/05 MDE 52 Improved reject handlng, add u_mvl_reject_ind*/
/* 08/08/05 JRB 52 Init mvl_debug_sel = MVLLOG_ERR. */
/* 06/02/05 JRB 51 Fix _mvl_send_reject for INVALID-PDU. */
/* 05/24/05 EJV 50 Add mvlLogMaskMapCtrl for parsing logcfg.xml */
/* 09/07/04 JRB 49 _mvl_get_req_ctrl: ret NULL if net_info==NULL*/
/* 07/28/03 MDE 48 Yet another tweak to mvl_ureq_bufs_avail */
/* 05/05/03 MDE 47 Yet another tweak to mvl_ureq_bufs_avail */
/* 05/01/03 MDE 46 Added high water logging to (u)req_bufs_avail*/
/* 04/28/03 JRB 45 Fix computations in mvl_(u)req_bufs_avail. */
/* 07/09/02 JRB 44 Add mvl_(u)req_bufs_avail functions. */
/* 07/09/02 MDE 43 Add maxpend_ind support */
/* 05/21/02 MDE 42 Check PDU len before decoding */
/* 05/13/02 MDE 41 Added 'skip' arg to _mvl_set_net_req_done */
/* 05/01/02 MDE 40 Fixed conclude logging */
/* 04/05/02 MDE 39 Added MLOG logging */
/* 03/25/02 MDE 38 Moved error/reject elements outside union */
/* 11/07/01 JRB 37 mvl_wait_req_done return "req->result". */
/* 09/21/01 JRB 36 Alloc global bufs only once at startup. */
/* 07/31/01 MDE 35 Added mvl_conn_filtered_logging */
/* 02/22/01 GLB 34 Added: MVLULOG_DEBUG, MVLULOG_TIMING */
/* 11/20/00 MDE 33 Fixed lockup - abort with requests out */
/* 10/25/00 JRB 32 Del global link list of MVL_REQ_PEND. Add one*/
/* for each conn. Save list ptr in MVL_NET_INFO.*/
/* Del _mvl_free_req_pend function. */
/* 10/25/00 JRB 31 Del ind & conf funct ptrs. Call directly. */
/* Mv mvl_ind_rcvd, mvl_conf_rcvd to mvlop_en.c */
/* so "conditional compilation" can be used. */
/* 05/15/00 MDE 30 Added statistics */
/* 05/12/00 RKR 29 Worked on mvl_send_reject */
/* 04/14/00 JRB 28 Lint cleanup. */
/* 03/08/00 JRB 27 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */
/* mvl_free_req_ctrl chk result before freeing. */
/* 01/21/00 MDE 26 Now use MEM_SMEM for dynamic memory */
/* 11/24/99 MDE 25 Del indCtrl from link list for info reports */
/* 11/19/99 NAV 24 Add #ifdef MVL_REQ_BUF_ENABLED */
/* 10/20/99 NAV 23 Additions for maxpend_req support */
/* 11/03/99 RKR 22 Changed reject and error confirm results */
/* 11/02/99 RKR 21 Fixed a leak when a reject is received */
/* 10/28/99 RKR 20 Added mvl_clr_ind_que */
/* 10/06/99 GLB 19 Added changes to accomodate file rename */
/* 09/13/99 MDE 18 Added SD_CONST modifiers */
/* 04/01/99 MDE 17 Changes to decode buffer allocation scheme */
/* 03/03/99 MDE 16 Changed 'mvl_max_req_pend' to 10000 */
/* 12/08/98 MDE 15 Cleanup on request control handling */
/* 11/16/98 MDE 14 Renamed internal functions (prefix '_') */
/* 11/16/98 MDE 13 Cleanup, conclude changes, removed simple */
/* request control, renamed concat_filename */
/* 10/08/98 MDE 12 Migrated to updated SLOG interface */
/* 10/01/98 DWL 11 Added get domain attributes client */
/* Added get name list client */
/* Added get status client */
/* 09/21/98 MDE 10 Minor lint cleanup */
/* 06/15/98 MDE 09 Changes to allow compile under C++ */
/* 05/13/98 JRB 08 Set req->result=CNF_REJ_ERR in mvl_reject_rcvd*/
/* Add _mplas_err_resp & _mvl_concat_filename. */
/* 04/21/98 MDE 07 Added service logging */
/* 04/15/98 JRB 06 mvl_conf_rcvd: do all common processing, */
/* pass req_pend to all "ml_*_conf_proc". */
/* Add client support for more services. */
/* Free comm_event, etc. from mvl_free_req_ctrl */
/* Init "result" in _mvl_get_req_ctrl. */
/* Add _mvl_conf_reject, _mvl_ind_reject. */
/* 02/10/98 MDE 05 Added get domain attributes server */
/* 12/22/97 MDE 04 Changed 'mvl_comm_serve' to report activity */
/* 12/12/97 MDE 03 _mvl_send_reject now returns ST_VOID */
/* 12/10/97 MDE 02 Added JREAD/JINIT */
/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */
/************************************************************************/
#include "glbtypes.h"
#include "sysincs.h"
#include "glbsem.h"
#include "mmsdefs.h"
#include "mms_err.h"
#include "mvl_defs.h"
#include "mvl_log.h"
#include "mloguser.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_UINT mvl_debug_sel = MVLLOG_ERR;
#ifdef DEBUG_SISCO
SD_CONST ST_CHAR *SD_CONST _mvllog_err_logstr = "MVLLOG_ERR";
SD_CONST ST_CHAR *SD_CONST _mvllog_nerr_logstr = "MVLLOG_NERR";
SD_CONST ST_CHAR *SD_CONST _mvllog_acse_logstr = "MVLLOG_ACSE";
SD_CONST ST_CHAR *SD_CONST _mvllog_acsedata_logstr = "MVLLOG_ACSEDATA";
SD_CONST ST_CHAR *SD_CONST _mvlulog_flow_logstr = "MVLULOG_FLOW";
SD_CONST ST_CHAR *SD_CONST _mvlulog_debug_logstr = "MVLULOG_DEBUG";
LOGCFGX_VALUE_MAP mvlLogMaskMaps[] =
{
{"MVLLOG_ERR", MVLLOG_ERR, &mvl_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Error"},
{"MVLLOG_NERR", MVLLOG_NERR, &mvl_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Notice"},
{"MVLLOG_ACSE", MVLLOG_ACSE, &mvl_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "ACSE"},
{"MVLLOG_ACSEDATA", MVLLOG_ACSEDATA, &mvl_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "ACSEData"},
{"MVLULOG_FLOW", MVLULOG_FLOW, &mvl_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Flow"},
{"MVLULOG_DEBUG", MVLULOG_DEBUG, &mvl_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Debug"}
};
LOGCFG_VALUE_GROUP mvlLogMaskMapCtrl =
{
{NULL,NULL},
"MvlLogMasks", /* Parent Tag */
sizeof(mvlLogMaskMaps)/sizeof(LOGCFGX_VALUE_MAP),
mvlLogMaskMaps
};
#endif /* DEBUG_SISCO */
ST_BOOLEAN mvl_conn_filtered_logging;
ST_BOOLEAN _mvl_persist_aa_objs;
/************************************************************************/
/* User defined function, called repetitively by MVL client functions */
/* while waiting for confirm. If this function returns SD_TRUE, the */
/* request will timeout and return SD_FAILURE. */
ST_BOOLEAN (*u_mvl_check_timeout)(ST_VOID);
/************************************************************************/
/* These functions are used internally by mvl_comm_serve () */
static ST_VOID mvl_msg_rcvd (MVL_COMM_EVENT *event);
static ST_VOID mvl_error_rcvd (MVL_COMM_EVENT *event);
static ST_VOID mvl_reject_rcvd (MVL_COMM_EVENT *event);
static ST_VOID _mvl_send_reject_net_info (MVL_NET_INFO *net_info,
REJECT_RESP_INFO *rej_info);
/************************************************************************/
/************************************************************************/
/* mvl_comm_serve */
/* General MMS communication service */
/************************************************************************/
ST_BOOLEAN _mvl_comm_serve_active;
ST_BOOLEAN mvl_comm_serve ()
{
MVL_COMM_EVENT *event;
ST_BOOLEAN activityFlag;
S_LOCK_COMMON_RESOURCES ();
/* Check for re-entrancy. This must be inside the lock so only one */
/* thread is accessing the global "_mvl_comm_serve_active". */
if (_mvl_comm_serve_active)
{
MVL_LOG_ERR0 ("Error: mvl_comm_serve re-entered");
S_UNLOCK_COMMON_RESOURCES (); /* unlock sem before return */
return (SD_FALSE);
}
_mvl_comm_serve_active = SD_TRUE;
/* Call the network service routine, see if it has anything for us */
/* to deal with */
activityFlag = _mvl_net_service (&event);
if (event)
{
switch (event->event_type)
{
case MMS_MSG_RCVD :
mvl_msg_rcvd (event);
break;
default :
_mvl_free_comm_event (event); /* All done with this event */
break;
}
}
_mvl_comm_serve_active = SD_FALSE;
S_UNLOCK_COMMON_RESOURCES ();
return (activityFlag);
}
/************************************************************************/
/* mvl_msg_rcvd */
/* This function is called by mvl_comm_serve when a MMS message */
/* has been received. */
/************************************************************************/
static ST_VOID mvl_msg_rcvd (MVL_COMM_EVENT *event)
{
MMSDEC_INFO *rslt;
MVL_REQ_PEND *req_pend;
ST_INT pdu_len;
rslt = &event->u.mms.dec_rslt;
pdu_len = event->u.mms.pdu_len;
/* Verify that the message is less than or equal to negiotiated */
if (pdu_len > event->net_info->max_pdu_size)
{
MVL_LOG_NERR2 ("MMS PDU too long: %d rxd, %d max",
pdu_len, event->net_info->max_pdu_size);
printf("MMS PDU too long: %d rxd, %d max",
pdu_len, event->net_info->max_pdu_size);
_mvl_send_reject (event);
return;
}
/* some kind of message was received, need to decode and act on it */
_ms_mms_decode (event->u.mms.pdu, pdu_len, rslt);
rslt->data_ptr = _mms_dec_info;
if (rslt->err_code == NO_DECODE_ERR)
{
switch (rslt->type)
{
case MMSREQ :
/* We can log here if so desired */
if ((mms_debug_sel & MMS_LOG_IND) && ml_log_ind_info_fun != NULL)
{
if (mvl_conn_filtered_logging == SD_FALSE || event->net_info->log_enable)
(*ml_log_ind_info_fun) (rslt->id, rslt->op, rslt->data_ptr);
}
mvl_ind_rcvd (event);
break;
case MMSUNREQ :
/* We can log here if so desired */
if ((mms_debug_sel & MMS_LOG_IND) && ml_log_unsol_ind_info_fun != NULL)
{
if (mvl_conn_filtered_logging == SD_FALSE || event->net_info->log_enable)
(*ml_log_unsol_ind_info_fun) (rslt->op, rslt->data_ptr);
}
mvl_ind_rcvd (event);
break;
case MMSRESP :
/* We can log here if so desired */
if ((mms_debug_sel & MMS_LOG_CONF) && ml_log_conf_info_fun != NULL)
{
if (mvl_conn_filtered_logging == SD_FALSE || event->net_info->log_enable)
(*ml_log_conf_info_fun) (rslt->id, rslt->op, rslt->data_ptr);
}
mvl_conf_rcvd (event);
break;
case MMSREJECT :
/* We can log here if so desired */
if ((mms_debug_sel & MMS_LOG_CONF) && ml_log_reject_recv_fun != NULL)
{
if (mvl_conn_filtered_logging == SD_FALSE || event->net_info->log_enable)
(*ml_log_reject_recv_fun) (rslt->data_ptr);
}
mvl_reject_rcvd (event);
break;
case MMSERROR :
if ((mms_debug_sel & MMS_LOG_CONF) && ml_log_error_conf_fun != NULL)
{
if (mvl_conn_filtered_logging == SD_FALSE || event->net_info->log_enable)
(*ml_log_error_conf_fun) (rslt->id, rslt->data_ptr);
}
mvl_error_rcvd (event);
break;
case MMSCNCLERR :
if ((mms_debug_sel & MMS_LOG_CONF) && ml_log_error_conf_fun != NULL)
{
if (mvl_conn_filtered_logging == SD_FALSE || event->net_info->log_enable)
(*ml_log_error_conf_fun) (rslt->id, rslt->data_ptr);
}
/* Find Conclude request sent on this connection & mark it as failed.*/
req_pend = _mvl_find_req_ctrl (event->net_info,
MMSOP_CONCLUDE, (ST_UINT32) -1);
if (!req_pend)
{ /* this should almost never fail. */
MVL_LOG_ERR0 ("Negative Conclude Confirm received: Error finding request control");
_mvl_free_comm_event (event); /* All done with this event */
return;
}
req_pend->done = SD_TRUE;
req_pend->result = SD_FAILURE;
break;
case MMSCNCLRESP :
/* We can log here if so desired */
if ((mms_debug_sel & MMS_LOG_CONF) && ml_log_conf_info_fun != NULL)
{
if (mvl_conn_filtered_logging == SD_FALSE || event->net_info->log_enable)
(*ml_log_conf_info_fun) (rslt->id, MMSOP_CONCLUDE, NULL);
}
req_pend = _mvl_find_req_ctrl (event->net_info,
MMSOP_CONCLUDE, (ST_UINT32) -1);
if (!req_pend)
{
MVL_LOG_NERR1 ("%s Confirmation : mvl_find_req_ctrl failed",
mms_op_string [event->u.mms.dec_rslt.op]);
_mvl_free_comm_event (event); /* All done with this event */
return;
}
req_pend->event = event;
mvl_concl_conf_rcvd (req_pend);
break;
case MMSCNCLREQ :
/* We can log here if so desired */
if ((mms_debug_sel & MMS_LOG_IND) && ml_log_ind_info_fun != NULL)
{
if (mvl_conn_filtered_logging == SD_FALSE || event->net_info->log_enable)
(*ml_log_ind_info_fun) (rslt->id, MMSOP_CONCLUDE, NULL);
}
mvl_concl_ind_rcvd (event);
break;
/* Unexpected PDU types */
case MMSCANREQ :
/* We can log here if so desired */
if ((mms_debug_sel & MMS_LOG_IND) && ml_log_ind_info_fun != NULL)
(*ml_log_ind_info_fun) (rslt->id, rslt->op, rslt->data_ptr);
mvl_cancel_ind_rcvd (event);
break;
case MMSCANRESP :
MVL_LOG_NERR0 ("Unexpected MMS PDU type received: Cancel Response");
_mvl_send_reject (event);
break;
case MMSCANERR :
MVL_LOG_NERR0 ("Unexpected MMS PDU type received: Cancel Error");
_mvl_send_reject (event);
break;
case MMSINITREQ :
MVL_LOG_NERR0 ("Unexpected MMS PDU type received: Initiate Request");
_mvl_send_reject (event);
break;
case MMSINITRESP :
MVL_LOG_NERR0 ("Unexpected MMS PDU type received: Initiate Response");
_mvl_send_reject (event);
break;
case MMSINITERR :
MVL_LOG_NERR0 ("Unexpected MMS PDU type received: Initiate Error");
_mvl_send_reject (event);
break;
case UNKNOWNTYPE :
MVL_LOG_NERR0 ("Unexpected MMS PDU type received: Unknown");
_mvl_send_reject (event);
break;
default :
MVL_LOG_NERR1 ("Unexpected MMS PDU type received: %d", rslt->type);
_mvl_send_reject (event);
break;
}
}
else /* Error in decoding, need to reject the message */
{
MVL_LOG_NERR0 ("MMS PDU decode error, sending reject");
/* If this was a confirmed response, try to match the request */
req_pend = NULL;
if (rslt->dec_level >= 2 && rslt->type == MMSRESP)
{
req_pend = _mvl_find_req_ctrl (event->net_info, -1, rslt->id);
if (req_pend != NULL)
{
req_pend->event = event;
req_pend->reject_info = event->u.mms.dec_rslt.data_ptr =
(REJECT_RESP_INFO *) chk_calloc (1, sizeof (REJECT_RESP_INFO));
event->u.mms.dec_rslt.data_pres = SD_TRUE;
req_pend->reject_info->detected_here = SD_TRUE;
req_pend->reject_info->invoke_known = SD_TRUE;
req_pend->reject_info->invoke = rslt->id;
req_pend->reject_info->pdu_type = MMSRESP;
req_pend->reject_info->rej_class = MMS_REJ_CLASS_CONFIRMED_RESPONSE_PDU;
req_pend->reject_info->rej_code = MMS_REJ_CODE_CONFIRMED_RESPONSE_PDU_OTHER;
_mvl_send_reject_net_info (event->net_info, req_pend->reject_info);
_mvl_set_req_done (req_pend, MVL_ERR_CNF_REJ_ERR);
}
else
{
MVL_LOG_CNERR0 ("Could not match confirmed request");
}
}
if (req_pend == NULL)
_mvl_send_reject (event);
}
}
/************************************************************************/
ST_VOID mvl_clr_ind_que (MVL_NET_INFO *net_info)
{
MVL_IND_PEND *pend_ind;
MVL_IND_PEND *next_ind;
/* look at all the pending indications attached to this MVL_NET_INFO */
/* unlink them, and deallocate them. */
pend_ind = net_info->pend_ind;
while(pend_ind!=NULL)
{
next_ind = (MVL_IND_PEND *) list_get_next(net_info->pend_ind,pend_ind);
list_unlink(&(net_info->pend_ind),pend_ind);
--net_info->numpend_ind;
_mvl_free_comm_event (pend_ind->event);
M_FREE (MSMEM_IND_CTRL, pend_ind);
pend_ind = next_ind;
}
}
/************************************************************************/
/* mvl_error_rcvd */
/************************************************************************/
static ST_VOID mvl_error_rcvd (MVL_COMM_EVENT *event)
{
MVL_REQ_PEND *req;
ST_UINT32 id;
ST_INT op;
++mvl_mms_statistics.clientReqErr;
event->net_info->numpend_req--;
id = event->u.mms.dec_rslt.id;
op = event->u.mms.dec_rslt.op;
req = _mvl_find_req_ctrl (event->net_info, -1, id);
if (!req)
{
MVL_LOG_NERR0 ("Error Received : mvl_find_req_ctrl failed");
_mvl_free_comm_event (event); /* All done with this event */
return;
}
req->event = event;
req->error_info = (ERR_INFO *) req->event->u.mms.dec_rslt.data_ptr;
_mvl_set_req_done (req, MVL_ERR_CNF_ERR_OK);
}
/************************************************************************/
/* mvl_reject_rcvd */
/************************************************************************/
static ST_VOID mvl_reject_rcvd (MVL_COMM_EVENT *event)
{
REJECT_RESP_INFO *info;
MVL_REQ_PEND *req;
ST_BOOLEAN freeCommEvent;
MVL_NET_INFO *netInfo;
++mvl_mms_statistics.rejectsRcvd;
netInfo = event->net_info;
netInfo->numpend_req--;
freeCommEvent = SD_TRUE;
info = (REJECT_RESP_INFO *) event->u.mms.dec_rslt.data_ptr;
MVL_LOG_NERR2 ("Reject Received: class %d, code %d",
info->rej_class, info->rej_code);
/* If the other node rejected our confirmed request, need to match it */
if (info->rej_class == MMS_REJ_CLASS_CONFIRMED_REQUEST_PDU)
{
if (info->invoke_known)
{
req = _mvl_find_req_ctrl (netInfo, -1, info->invoke);
if (!req)
{
MVL_LOG_CNERR0 ("Could not match confirmed request");
return;
}
req->event = event;
req->reject_info =
(REJECT_RESP_INFO *) req->event->u.mms.dec_rslt.data_ptr;
_mvl_set_req_done (req, MVL_ERR_CNF_REJ_ERR);
freeCommEvent = SD_FALSE;
}
}
/* Let the user know about this */
u_mvl_reject_ind (netInfo, info);
if (freeCommEvent)
_mvl_free_comm_event (event); /* All done with this event */
}
/************************************************************************/
/************************************************************************/
/* This table is used to select reject class given MMS pdu type */
/* PDU type is the index into this table */
/************************************************************************/
SD_CONST ST_INT16 pdutype_to_reject_class[14] =
{
1, /* confirmed request */
2, /* confirmed response */
3, /* confirmed error */
4, /* unconfirmed */
5, /* reject */
6, /* cancel request */
7, /* cancel response */
8, /* cancel error */
0, /* initiate req - not used */
0, /* initiate resp - not used */
0, /* initiate error - not used */
9, /* conclude request */
10, /* conclude response */
11 /* conclude error */
};
/************************************************************************/
/* _mvl_ind_reject */
/* Send reject for Indication. */
/************************************************************************/
ST_VOID _mvl_ind_reject (MVL_IND_PEND *ind_pend)
{
MVL_NET_INFO *net_info;
net_info = ind_pend->event->net_info;
_mvl_send_reject (ind_pend->event);
list_unlink(&(net_info->pend_ind),ind_pend);
--net_info->numpend_ind;
M_FREE (MSMEM_IND_CTRL, ind_pend);
}
/************************************************************************/
/* _mvl_conf_reject */
/* Send reject for Confirmation. */
/************************************************************************/
ST_VOID _mvl_conf_reject (MVL_REQ_PEND *req_pend)
{
_mvl_send_reject (req_pend->event);
req_pend->event = NULL; /* so mvl_free_req_ctrl doesn't try to */
/* free it again. */
req_pend->result = SD_FAILURE;/* Let user know it failed. */
}
/************************************************************************/
/* _mvl_send_reject */
/* This is a simple minded reject send function. If the PDU type isd */
/* known, send a reject of the appropriate class with code == OTHER. */
/* This is not always exactly right per the MMS service document, but */
/* will be OK for now. */
/************************************************************************/
ST_VOID _mvl_send_reject (MVL_COMM_EVENT *event)
{
ST_RET rc;
REJECT_RESP_INFO rej_info;
MMSDEC_INFO *rslt;
S_LOCK_COMMON_RESOURCES ();
rej_info.detected_here = SD_TRUE;
rej_info.invoke_known = SD_FALSE;
rslt = &event->u.mms.dec_rslt;
if (rslt->dec_level > 0) /* If we at least know the type of PDU */
{
rej_info.pdu_type = rslt->type;
/* If this was unrecognized confirmed request, set appropriate reject class/code. */
if (rslt->dec_level >= 2 && rslt->type == MMSREQ && rslt->err_code==REQ_UNREC_SERV)
{
rej_info.rej_class = MMS_REJ_CLASS_CONFIRMED_REQUEST_PDU;
rej_info.rej_code = MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_UNRECOGNIZED_SERVICE;
}
else
{ /* set correct class, but just set code to "OTHER" (0). */
rej_info.rej_class = pdutype_to_reject_class[rslt->type];
rej_info.rej_code = 0;
}
if ((rslt->dec_level >= 2) && /* if invoke ID known, use it */
(rslt->type == MMSREQ || rslt->type == MMSRESP))
{
rej_info.invoke_known = SD_TRUE;
rej_info.invoke = rslt->id;
}
}
else
{
rej_info.pdu_type = UNKNOWNTYPE;
rej_info.rej_class = MMS_REJ_CLASS_PDU_ERROR;
rej_info.rej_code = MMS_REJ_CODE_PDU_ERROR_INVALID_PDU;
}
rc = mpl_reject_resp (&rej_info);
if (rc != SD_SUCCESS)
{
MVL_LOG_NERR1 ("Sending Reject : mpl_reject_resp failed, ret = %x", rc);
}
else
{ /* build was OK, send it */
rc = _mvl_send_msg (mmsl_msg_start,mmsl_msg_len, event->net_info);
if (rc != SD_SUCCESS)
{
MVL_LOG_NERR1 ("Sending Reject : _mvl_send_msg failed, ret = %x", rc);
}
else
++mvl_mms_statistics.rejectsSent;
}
/* Tell the user all about it ... */
u_mvl_reject_ind (event->net_info, &rej_info);
_mvl_free_comm_event (event); /* All done with this event */
S_UNLOCK_COMMON_RESOURCES ();
}
/************************************************************************/
/* _mvl_send_reject_net_info */
/************************************************************************/
static ST_VOID _mvl_send_reject_net_info (MVL_NET_INFO *net_info,
REJECT_RESP_INFO *rej_info)
{
ST_RET rc;
S_LOCK_COMMON_RESOURCES ();
rc = mpl_reject_resp (rej_info);
if (rc != SD_SUCCESS)
{
MVL_LOG_NERR1 ("Sending Reject : mpl_reject_resp failed, ret = %x", rc);
}
else
{ /* build was OK, send it */
rc = _mvl_send_msg (mmsl_msg_start,mmsl_msg_len, net_info);
if (rc != SD_SUCCESS)
{
MVL_LOG_NERR1 ("Sending Reject : _mvl_send_msg failed, ret = %x", rc);
}
else
++mvl_mms_statistics.rejectsSent;
}
/* Tell the user all about it ... */
u_mvl_reject_ind (net_info, rej_info);
S_UNLOCK_COMMON_RESOURCES ();
}
/************************************************************************/
/* _mplas_err_resp */
/* This function sends an error response and frees the MVL_IND_PEND */
/* and the MVL_COMM_EVENT. */
/************************************************************************/
ST_RET _mplas_err_resp (MVL_IND_PEND *indCtrl, ST_INT16 eClass, ST_INT16 code)
{
ST_RET rc;
MVL_NET_INFO *net_info;
net_info = indCtrl->event->net_info;
rc = _mvl_send_err_f (indCtrl->event, eClass, code);
list_unlink(&(net_info->pend_ind),indCtrl);
--net_info->numpend_ind;
M_FREE (MSMEM_IND_CTRL, indCtrl);
++mvl_mms_statistics.serverRespErr;
return (rc);
}
/************************************************************************/
/* _mvl_send_err_f */
/* This function sends an error response and frees the MVL_COMM_EVENT. */
/************************************************************************/
ST_RET _mvl_send_err_f (MVL_COMM_EVENT *event, ST_INT16 eClass, ST_INT16 code)
{
ST_RET rc;
rc = _mvl_send_error (event, eClass, code);
_mvl_free_comm_event (event); /* All done with this event */
return (rc);
}
/************************************************************************/
/* _mvl_send_error */
/* This function is used to send an error response to a confirmed */
/* request PDU. */
/************************************************************************/
ST_RET _mvl_send_error (MVL_COMM_EVENT *event, ST_INT16 eClass, ST_INT16 code)
{
ST_RET rc;
S_LOCK_COMMON_RESOURCES ();
rc = mpl_err_resp (event->u.mms.dec_rslt.op,
event->u.mms.dec_rslt.id,
eClass,code);
if (rc != SD_SUCCESS)
{
MVL_LOG_NERR1 ("Sending Error : mpl_err_resp failed, ret = %x", rc);
}
else
{ /* build was OK, send it */
rc = _mvl_send_msg (mmsl_msg_start,mmsl_msg_len,event->net_info);
if (rc != SD_SUCCESS)
{
MVL_LOG_NERR1 ("Sending Error : _mvl_send_msg failed, ret = %x", rc);
}
else
++mvl_mms_statistics.serverRespErr;
}
S_UNLOCK_COMMON_RESOURCES ();
return (rc);
}
/************************************************************************/
/* mvl_wait_req_done */
/* RETURNS: SD_SUCCESS or MVL error code */
/************************************************************************/
ST_RET mvl_wait_req_done (MVL_REQ_PEND *req)
{
while (req->done == SD_FALSE) /* wait forever until done */
{
if (u_mvl_check_timeout)
{
if ((*u_mvl_check_timeout)())
{
req->result = MVL_ERR_USR_TIMEOUT;
MVL_LOG_NERR0 ("Wait Request Done : u_mvl_check_timeout timed out");
break;
}
}
mvl_comm_serve (); /* service communications */
}
return (req->result);
}
/************************************************************************/
/************************************************************************/
/* Outstanding MMS request control handling functions */
/************************************************************************/
/************************************************************************/
/* _mvl_get_req_ctrl */
/************************************************************************/
MVL_REQ_PEND *_mvl_get_req_ctrl (MVL_NET_INFO *net_info, ST_INT16 op)
{
MVL_REQ_PEND *req;
if (net_info == NULL)
{
MVL_LOG_NERR0 ("_mvl_get_req_ctrl error: connection invalid");
return (NULL);
}
req = (MVL_REQ_PEND *) M_CALLOC (MSMEM_REQ_CTRL, 1, sizeof (MVL_REQ_PEND));
S_LOCK_COMMON_RESOURCES ();
list_add_last(&net_info->req_pend_list, req);
req->invoke_id = mmsl_invoke_id;
req->op = op;
req->done = SD_FALSE;
req->result = SD_SUCCESS;
req->net_info = net_info;
req->u_req_done = NULL;
req->event = NULL;
S_UNLOCK_COMMON_RESOURCES ();
return (req);
}
/************************************************************************/
/* _mvl_find_req_ctrl */
/************************************************************************/
MVL_REQ_PEND *_mvl_find_req_ctrl (MVL_NET_INFO *net_info,
ST_INT op, ST_UINT32 id)
{
MVL_REQ_PEND *req;
S_LOCK_COMMON_RESOURCES ();
req = net_info->req_pend_list; /* start at head of linked list */
while (req != NULL) /* look through whole list */
{
if (req->net_info == net_info &&
req->invoke_id == id)
{
if (req->op == op || op == -1)
break; /* return a pointer to it */
}
req = (MVL_REQ_PEND *) list_get_next (net_info->req_pend_list, req);
}
S_UNLOCK_COMMON_RESOURCES ();
return (req);
}
/************************************************************************/
/* _mvl_set_net_req_done */
/************************************************************************/
ST_VOID _mvl_set_net_req_done (MVL_REQ_PEND *skip,
MVL_NET_INFO *net_info, ST_RET result)
{
MVL_REQ_PEND *req;
MVL_REQ_PEND *next;
req = net_info->req_pend_list; /* start at head of linked list */
while (req != NULL) /* look through whole list */
{
/* CRITICAL: get NEXT entry BEFORE calling _mvl_set_req_done */
/* because it may remove THIS entry from the linked list. */
next = (MVL_REQ_PEND *) list_get_next (net_info->req_pend_list, req);
if (req->done != SD_TRUE)
{
if (req != skip)
_mvl_set_req_done (req, result);
}
req = next;
}
/* CRITICAL: Destroy all AA_SPEC objects on this connection. */
/* This is a good place to do this because this function is */
/* called on Abort.req, Abort.ind, Release.ind, or Release.cnf */
if (!_mvl_persist_aa_objs)
_mvl_clear_aa_objs (net_info->aa_objs);
}
/************************************************************************/
/* _mvl_set_req_done */
/************************************************************************/
ST_VOID _mvl_set_req_done (MVL_REQ_PEND *req, ST_RET result)
{
req->result = result;
req->done = SD_TRUE;
if (req->u_req_done) /* Call the user done function */
(*req->u_req_done)(req);
}
/************************************************************************/
/* mvl_free_req_ctrl */
/************************************************************************/
ST_VOID mvl_free_req_ctrl (MVL_REQ_PEND *pend_req)
{
if (pend_req)
{
S_LOCK_COMMON_RESOURCES ();
if (pend_req->event)
_mvl_free_comm_event (pend_req->event);
/* Free up extra stuff for some services. */
/* NOTE: on error or reject the union (pend_req->u) is overwritten */
/* so "normal" resp_info is not valid. DON'T try to free it. */
if (pend_req->op == MMSOP_FILE_DIR &&
pend_req->result != MVL_ERR_CNF_REJ_ERR && /* !reject */
pend_req->result != MVL_ERR_CNF_ERR_OK && /* !error */
pend_req->u.fdir.resp_info != NULL)
{ /* Only do this if it was allocated (see confirm function) */
M_FREE (MSMEM_GEN, pend_req->u.fdir.resp_info);
}
if (pend_req->op == MMSOP_READ_JOURNAL &&
pend_req->result != MVL_ERR_CNF_REJ_ERR && /* !reject */
pend_req->result != MVL_ERR_CNF_ERR_OK && /* !error */
pend_req->u.jread.resp_info != NULL)
{ /* Only do this if it was allocated (see confirm function) */
M_FREE (MSMEM_GEN, pend_req->u.jread.resp_info);
}
list_unlink (&pend_req->net_info->req_pend_list, pend_req);
M_FREE (MSMEM_REQ_CTRL, pend_req);
S_UNLOCK_COMMON_RESOURCES ();
}
}
/************************************************************************/
/************************************************************************/
/* mvl_init_glb_vars */
/************************************************************************/
/* For use when global variables cannot be initialized at compile time */
#if defined(NO_GLB_VAR_INIT)
ST_VOID mvl_init_glb_vars (ST_VOID)
{
m_init_glb_vars ();
_mvlop_en_init ()
}
#endif
/************************************************************************/
/* _mvl_concat_filename */
/************************************************************************/
ST_RET _mvl_concat_filename (ST_CHAR *good_name,
ST_INT num_of_fname,
FILE_NAME *fname_arr,
ST_INT max_len) /* size of array to fill in (i.e. good_name) */
{
ST_INT j;
ST_INT total_len;
for (j = 0, total_len = 0; j < num_of_fname; j++)
total_len += fname_arr[j].fn_len;
if (total_len + 1 > max_len) /* Must leave room for NULL */
return (SD_FAILURE);
for (j = 0, total_len = 0; j < num_of_fname; j++)
{
memcpy (&good_name [total_len], fname_arr[j].fname, fname_arr[j].fn_len);
total_len += fname_arr[j].fn_len;
}
good_name [total_len] = '\x00'; /* add NULL terminator */
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
/************************************************************************/
/* _mvl_calloc_os */
/************************************************************************/
ST_VOID *_mvl_calloc_os (ST_UINT num, ST_UINT size)
{
return (M_CALLOC (MSMEM_DEC_OS_INFO, 1, size));
}
/************************************************************************/
/* _mvl_realloc_os */
/************************************************************************/
ST_VOID *_mvl_realloc_os (ST_VOID *old, ST_UINT new_size)
{
return (M_REALLOC (MSMEM_DEC_OS_INFO, old,new_size));
}
/************************************************************************/
/* _mvl_free_os */
/************************************************************************/
ST_VOID _mvl_free_os (ST_VOID *buf)
{
M_FREE (MSMEM_DEC_OS_INFO, buf);
}
/************************************************************************/
/* mvl_req_bufs_avail */
/* Return number of buffers available for sending "confirmed" requests. */
/************************************************************************/
ST_INT mvlLowWaterAvail = 50;
ST_INT mvlLowWaterReqAvail = 50;
ST_INT mvlLowWaterUReqAvail = 50;
ST_INT mvl_req_bufs_avail (MVL_NET_INFO *net_info)
{
ST_INT avail;
avail = a_buffers_avail (net_info->acse_conn_id);
if (avail < mvlLowWaterAvail)
{
mvlLowWaterAvail = avail;
MVLU_LOG_DEBUG1 ("Low water 'buffers available': %d", mvlLowWaterAvail);
}
/* Must have enough buffers avail to respond to max num of indications.*/
/* Doesn't matter how many indications are currently pending because */
/* at any momemt could get a bunch of indications and must ALWAYS */
/* have buffers available to respond to the maximum. */
avail -= net_info->maxpend_ind;
if (avail < mvlLowWaterReqAvail)
{
mvlLowWaterReqAvail = avail;
MVLU_LOG_DEBUG1 ("Low water 'Req buffers available': %d", mvlLowWaterReqAvail);
}
return (avail);
}
/************************************************************************/
/* mvl_ureq_bufs_avail */
/* Return number of buffers available for sending "unconfirmed" reqs */
/************************************************************************/
ST_INT mvl_ureq_bufs_avail (MVL_NET_INFO *net_info)
{
ST_INT avail;
avail = a_buffers_avail (net_info->acse_conn_id);
if (avail < mvlLowWaterAvail)
{
mvlLowWaterAvail = avail;
MVLU_LOG_DEBUG1 ("Low water 'buffers available': %d", mvlLowWaterAvail);
}
/* Must have enough buffers avail to respond to max num of indications.*/
/* Doesn't matter how many indications are currently pending because */
/* at any momemt could get a bunch of indications and must ALWAYS */
/* have buffers available to respond to the maximum. */
/* Because we don't know when response buffers are release by SUIC, */
/* we always assume that we must be able to send the max resp at any */
/* time. This means that when there really ARE max resp pend in SUIC */
/* we reserve twice as many as we need ... */
avail -= (net_info->maxpend_ind * 2); /* reserve maximum */
/* Must have enough buffers avail to send max num of "confirmed" reqs.*/
/* Doesn't matter how many requests are currently pending because */
/* at any momemt could get a bunch of confirms and may want to send */
/* new requests. So, we need to have buffers reserved for the max. */
avail -= (net_info->maxpend_req);
if (avail < mvlLowWaterUReqAvail)
{
mvlLowWaterUReqAvail = avail;
MVLU_LOG_DEBUG1 ("Low water 'UReq buffers' available': %d", mvlLowWaterUReqAvail);
}
return (avail);
}