/************************************************************************/ /* 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); }