/** * @file: $RCSfile: mmsclient.c,v $ * @brief: $IEC 61850 Protocol * * @version: $Revision: 1.12 $ * @date: $Date: 2022/11/28 07:13:13 $ * @author: $Author: lizhongming $ * @state: $State: Exp $ * * @latest: $Id: mmsclient.c,v 1.12 2022/11/28 07:13:13 lizhongming Exp $ * */ //$Header: /JoyProject/jspqfe/src/pt61850netd_pqfe/source/mms/mmsclient.c,v 1.12 2022/11/28 07:13:13 lizhongming Exp $ /************************************************************************/ /* SISCO SOFTWARE MODULE HEADER *****************************************/ /************************************************************************/ /* (c) Copyright Systems Integration Specialists Company, Inc., */ /* 1986 - 2005, All Rights Reserved */ /* (c) Copyright GDNZ Company, Inc., */ /* 2006- 2006, All Rights Reserved */ /* */ /* MODULE NAME : mmsclient.c */ /* PRODUCT(S) : MMSEASE-LITE */ /* */ /* MODULE DESCRIPTION : */ /* */ /* This module include the functions would be use by others */ /* */ /* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ /* NONE */ /* */ /* MODIFICATION LOG : */ /* Date Who Rev Comments */ /* -------- --- ------ ------------------------------------------- */ /*2006-06-28 Lzm 101 Change the file to be functions used by others . */ /* 09/09/05 JRB 55 Don't print BUILD_NUM. */ /* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ /************************************************************************/ #define HARD_CODED_CFG #if 1 /* move outside #if to enable */ #define ACSE_AUTH_ENABLED /* for password authentication without */ /* security */ /* S_SEC_ENABLED for certificate based authentication & */ /* SSL encryption, put this define in */ /* application's DSP/MAK file */ #endif /************************************************************************/ #include "rdb_client.h" #include "glbtypes.h" #include "sysincs.h" #include "signal.h" #include "mmsdefs.h" #include "mms_pvmd.h" #include "mms_pvar.h" #include "mms_vvar.h" #include "mms_err.h" #include "mms_pcon.h" #include "asn1defs.h" #include "mmsop_en.h" #include "lean_a.h" //add by lzm #include "tp0_sock.h" #include "mvl_defs.h" #include "acse2.h" #include "mvl_acse.h" #include "mvl_log.h" #include "tp4api.h" #include "clntobj.h" #include "mmsclient.h" #include "tp4.h" #include "../mms/db_interface.h" #include //lnk20241119 extern uint32_t g_node_id; extern char subdir[128]; unsigned int g_no_auth = 0; DEV_TYPE_LIST gDev_rcb_list; //全局报告控制块链表 #if defined(MVL_GOOSE_SUPPORT) /* Need parts of "iecgoose" sample app */ #include "iec_demo.h" /* definitions from "iecgoose" sample app */ /* Prototype here because it needs struct def from "iec_demo.h". */ IEC_GOOSE_RX_USER_INFO *goose_init (ST_VOID); #endif /*----------------------------------------------------------------------*/ /* NOTE: The MMS-EASE Lite Secured applications (Client, Server) */ /* are designed to work with Security Toolkit for MMS-EASE Lite */ /* (LITESECURE-000-001). */ /* The S_SEC_ENABLED delimits the security related code. */ /*----------------------------------------------------------------------*/ #if defined(S_SEC_ENABLED) && defined(ACSE_AUTH_ENABLED) #error Only one S_SEC_ENABLED or ACSE_AUTH_ENABLED may be defined #endif #if defined(S_SEC_ENABLED) #include "mmslusec.h" #endif #include "fkeydefs.h" #ifdef kbhit /* CRITICAL: fkeydefs may redefine kbhit. DO NOT want that.*/ #undef kbhit #endif /************************************************************************/ /* 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 /************************************************************************/ /* Identify server information */ IDENT_RESP_INFO identify_response_info = { "Joyway JoyCom", /* Vendor */ MMSLITE_NAME, /* Model */ MMSLITE_VERSION, 0, /* Version */ }; /************************************************************************/ extern TP0_CONN *tp0_conn_arr; /* ptr to array of "max_num_conns" structs */ static ST_VOID disc_ind_fun (MVL_NET_INFO *cc, ST_INT discType); ST_VOID test_simple_requests (MVL_NET_INFO *clientNetInfo); ST_INT timeOut = 60; /* timeout (in seconds) passed to waitReqDone */ INIT_INFO callingInitInfo; INIT_INFO initRespInfo; MVL_CFG_INFO mvlCfg; RPT_TYPEIDS g_rpt_typeids; /************************************************************************/ #if defined(HARD_CODED_CFG) DIB_ENTRY localDibTable[] = { { 0, /* reserved */ "local1", /* name[65] */ SD_TRUE, /* local */ SD_TRUE, /* AP_title_pres */ { /* AP_title */ 4, /* num_comps */ 1, 3, 9999, 105 }, SD_FALSE, /* AP_inv_id_pres */ 0, /* AP_invoke_id */ SD_TRUE, /* AE_qual_pres */ 33, /* AE_qual */ SD_FALSE, /* AE_inv_id_pres */ 0, /* AE_invoke_id */ #if defined(REDUCED_STACK) 105 /* adlcAddr */ #else { /* PRES_ADDR */ 4, /* P-selector length */ {'\x00','\x00','\x00','\x01'}, /* P-selector */ 2, /* S-selector length */ "\x00\x01", /* S-selector */ TP_TYPE_TCP,// change by lzm /* Transport type */ 2, /* T-selector length */ "\x00\x01", /* T-selector */ 0, /* Network address length */ "" /* Network address (ignored on local) */ } #endif } }; #endif ST_VOID set_rem_dib_table_size (ST_INT size) { mvlCfg.num_calling = size; num_rem_dib_entries = size; rem_dib_table = malloc(sizeof(DIB_ENTRY)*size); } ST_VOID add_rem_dib_table (ST_INT pos,ST_CHAR *remAr,unsigned short port) { DIB_ENTRY *de; de = &rem_dib_table[pos]; de->reserved = 0; /*de->name = (ST_CHAR *)chk_malloc(strlen(remAr) + 1); strcpy(de->name, remAr);*/ de->name = (ST_CHAR *)chk_malloc(32); apr_snprintf(de->name,32,"%s:%d",remAr,port); de->local = SD_TRUE; de->AP_title.num_comps = 4; de->AP_title.comps[0] = 1; de->AP_title.comps[1] = 3; de->AP_title.comps[2] = 9999; de->AP_title.comps[3] = 106; de->AP_title_pres = SD_TRUE; /* defaults to FALSE */ de->AE_qual_pres = SD_TRUE; /* defaults to FALSE */ de->AE_qual = 33; de->AP_inv_id_pres = SD_FALSE; de->AP_invoke_id = 0; de->AE_inv_id_pres = SD_FALSE; de->AE_invoke_id = 0; de->pres_addr.psel[0] = 0; de->pres_addr.psel[1] = 0; de->pres_addr.psel[2] = 0; de->pres_addr.psel[3] = 1; de->pres_addr.psel_len = 4; de->pres_addr.ssel[0] = 0; de->pres_addr.ssel[1] = 1; de->pres_addr.ssel_len = 2; de->pres_addr.tp_type = TP_TYPE_TCP; de->pres_addr.tsel[0] = 0; de->pres_addr.tsel[1] = 1; de->pres_addr.tsel_len = 2; de->pres_addr.nsap_len = 4; de->pres_addr.netAddr.ip = tp0_convert_ip(remAr); // printf (" %x", de->pres_addr.netAddr.ip ); // de->pres_addr.netAddr.nsap[0] = '\xAC'; // de->pres_addr.netAddr.nsap[1] = '\x15'; // de->pres_addr.netAddr.nsap[2] = '\x64'; // de->pres_addr.netAddr.nsap[3] = '\x64'; de->pres_addr.port = port;//IPPORT_RFC1006; } static ST_VOID init_mem (ST_VOID); #if defined (DEBUG_SISCO) // ST_VOID init_log_cfg (ST_VOID); #endif /************************************************************************/ /* Global variables */ /************************************************************************/ typedef struct { ST_INT cmd_term_num_va; /* num of vars received in CommandTermination*/ ST_CHAR oper_name [MAX_IDENT_LEN +1]; } MY_CONTROL_INFO; /* NOTE: this global variable can be avoided if a (MVL_CONTROL_INFO *) */ /* is saved in the "user_info" member of MVL_NET_INFO, but to do so, */ /* you must make sure "user_info" is not used for something else. */ MY_CONTROL_INFO my_control_info; /************************************************************************/ /* mms_var_type_id_create */ /* Get the type for any domain-specific var and create a type_id. */ /************************************************************************/ ST_INT mms_var_type_id_create (MVL_NET_INFO *clientNetInfo, ST_INT scope, ST_CHAR *dom_name, ST_CHAR *var_name, int iTimeOut) { MVL_REQ_PEND *reqCtrl; GETVAR_REQ_INFO getvar_req; ST_INT type_id = -1; /* start with invalid type id */ ST_RET ret; /* Get the type of this "Oper" attribute & create type. */ /* Would be more efficient to do this just once before this function.*/ getvar_req.req_tag = GETVAR_NAME; getvar_req.name.object_tag = scope; /* set scope */ if (scope == DOM_SPEC) getvar_req.name.domain_id= dom_name; getvar_req.name.obj_name.vmd_spec = var_name; ret = mvla_getvar (clientNetInfo, &getvar_req, &reqCtrl); if (ret == SD_SUCCESS) ret = waitReqDone (reqCtrl, iTimeOut); if (ret != SD_SUCCESS) echo_warn2 ("Error getting type of variable '%s' in domain '%s'\n", var_name, dom_name); else { /* Don't care about name so pass NULL. */ type_id = mvl_type_id_create (NULL, reqCtrl->u.getvar.resp_info->type_spec.data, reqCtrl->u.getvar.resp_info->type_spec.len); } mvl_free_req_ctrl (reqCtrl); /* Done with request struct */ return (type_id); } /************************************************************************/ /* mms_var_type_id_create */ /* Get the type for any domain-specific var and create a type_id. */ /************************************************************************/ ST_INT mms_get_datatype_from_type_id (ST_INT type_id, ST_UCHAR* datatype,ST_INT *len) { ST_RET ret; RUNTIME_CTRL rt_ctrl; if(type_id < 0) return SD_FAILURE; ret = mvl_get_runtime (type_id, &rt_ctrl.rt_first,&rt_ctrl.rt_num); if (ret == SD_SUCCESS) {//只返回 rt_ctrl.rt_num 中第一个数据的类型和 长度 RUNTIME_TYPE *rt_type = &rt_ctrl.rt_first[0]; *datatype = rt_type->el_tag; *len = rt_type->u.p.el_len; } return ret; } ST_INT32 u_safe_chang_double_to_int32 (ST_DOUBLE value, ST_CHAR *FileName, ST_INT32 line) { ST_INT32 gInt32; if(value > LONG_MAX) { gInt32 = LONG_MAX; MVL_LOG_NERR2 ("%s:%d Change double to int32 max overflow", FileName, line); printf(" %s:%ld Change double to int32 max overflow!\n", FileName, line); } else if(value < LONG_MIN) { gInt32 = LONG_MIN; MVL_LOG_NERR2 ("%s:%d Change double to int32 min overflow", FileName, line); printf(" %s:%ld Change double to int32 mxin overflow!\n", FileName, line); } else { gInt32 = (ST_INT32)(value + 0.5); } return(gInt32); } void u_get_current_utc_time(MMS_UTC_TIME *utc_time) { ST_DOUBLE temp = 0.0; apr_time_t us; apr_time_t tm = apr_time_now(); us = tm%1000000LL; utc_time->secs = (ST_UINT32)(tm/1000000LL); temp = (ST_DOUBLE)us/1000000 * 0x00FFFFFF; utc_time->fraction = u_safe_chang_double_to_int32(temp, __FILE__, __LINE__); utc_time->qflags = 0x00; } void convert_apr_time_to_utc_time(apr_time_t tm,MMS_UTC_TIME *utc_time) { ST_DOUBLE temp = 0.0; apr_time_t us; us = tm%1000000LL; utc_time->secs = (ST_UINT32)(tm/1000000LL); temp = (ST_DOUBLE)us/1000000 * 0x00FFFFFF; utc_time->fraction = u_safe_chang_double_to_int32(temp, __FILE__, __LINE__); utc_time->qflags = 0x00; } void mms_waitEventForever() { while (1) { doCommService (); } } void exit_MMS() { dyn_mem_ptr_statistics (0); mvl_end_acse (); dyn_mem_ptr_status (); /* is everything freed up? */ } /************************************************************************/ /* init_MMS */ /************************************************************************/ void init_MMS() { ST_RET ret; setbuf (stdout, NULL); /* do not buffer the output to stdout */ setbuf (stderr, NULL); /* do not buffer the output to stderr */ printf ("%s Version %s\n", MMSLITE_NAME, MMSLITE_VERSION); #if defined(S_SEC_ENABLED) printf ("%s Version %s\n", S_SEC_LITESECURE_NAME, S_SEC_LITESECURE_VERSION_STR); #endif puts (MMSLITE_COPYRIGHT); #ifdef S_MT_SUPPORT /* init glbsem explicitly to avoid auto-initialization calls from multiple threads */ if ((ret = gs_init()) != SD_SUCCESS) { printf ("gs_init() failed"); exit (1); } #endif /* init stime explicitly to avoid auto-initialization calls from multiple threads */ if ((ret = stimeInit()) != SD_SUCCESS) { printf ("stimeInit() failed"); exit (1); } #if defined(NO_GLB_VAR_INIT) mvl_init_glb_vars (); #endif init_mem (); /* Set up memory allocation tools */ echo_msg2 ("%s Version %s \n", MMSLITE_NAME, MMSLITE_VERSION); /* We want to know about connection activity */ u_mvl_disc_ind_fun = disc_ind_fun; #if !defined(MAP30_ACSE) #if defined(HARD_CODED_CFG) num_loc_dib_entries = sizeof(localDibTable)/sizeof(DIB_ENTRY); loc_dib_table = localDibTable; // num_rem_dib_entries = sizeof(rem_dib_table)/sizeof(DIB_ENTRY); memset(&gDev_rcb_list, 0, sizeof(DEV_TYPE_LIST)); //WW 2023-08-29 全局装置报告指针初始化 // tp4_config(); /* see tp4_hc.c */ tp0_cfg.max_tpdu_len = 8192;//8192; tp0_cfg.max_num_conns = 8; /* see tp4_hc.c */ //printf("OLD tp0_cfg.keepalive = %i \n" ,tp0_cfg.keepalive ); tp0_cfg.keepalive = 1; //printf("OLD tp0_cfg.max_spdu_outst = %i \n" ,tp0_cfg.max_spdu_outst ); tp0_cfg.max_spdu_outst = 50; #if 0 /* Only call config functions necessary for stack being used. */ tp4_config(); /* see tp4_hc.c */ clnp_config(); /* see clnp_hc.c */ adlcConfigure(); /* see adlc_hc.c */ #endif /* Fill in mvlCfg. */ mvlCfg.num_called = 0; mvlCfg.max_msg_size = 320000; //to enlage to fit the 主设备保护 strcpy (mvlCfg.local_ar_name, "local1"); #else /* #if defined(HARD_CODED_CFG) */ /* Read the configuration from a file */ ret = osicfgx ("osicfg.xml", &mvlCfg); /* This fills in mvlCfg */ if (ret != SD_SUCCESS) { printf ("\n Stack configuration failed, err = 0x%X. Check configuration.\n", ret ); exit (1); } #endif /* HARD_CODED_CFG */ #else /* MAP30_ACSE */ mvlCfg.num_calling = 4; mvlCfg.num_called = 0; mvlCfg.max_msg_size = 8000; strcpy (mvlCfg.local_ar_name, "local1"); #endif /* MAP30_ACSE */ #if defined(S_SEC_ENABLED) /* set security configuration file name, MUST be before mvl_start_acse*/ secManCfgXmlFile = "secmancfg.xml"; #endif /* defined(S_SEC_ENABLED) */ ret = mvl_start_acse (&mvlCfg); /* MAKE SURE mvlCfg is filled in*/ if (ret != SD_SUCCESS) { printf ("\n mvl_start_acse () failed, err = 0x%X.\n", ret ); exit (1); } if ((ret = rpt_typeids_find (&g_rpt_typeids)) != SD_SUCCESS) { printf ("rpt_typeids_find () failed = 0x%X.\n", ret ); exit (1); } #if defined(MVL_GOOSE_SUPPORT) /* NOTE: this GOOSE initialization must be AFTER mvl_start_acse so */ /* that required types can be found. */ goosehandle = goose_init (); #endif chk_malloc(1); /* memory marker */ #if !defined(NO_KEYBOARD) && !defined(_WIN32) && !defined(__QNX__) //term_init (); /* makes getchar work right */ #endif } // ST_RET mms_mvla_identify (MVL_NET_INFO *net_info,char** ident,int iTimeout) { static char ident_str[256]; MVL_REQ_PEND *reqCtrl; IDENT_RESP_INFO *ident_resp; ST_RET ret = mvla_identify (net_info, &reqCtrl); memset(ident_str,0,sizeof(ident_str)); if (ret == SD_SUCCESS) ret = waitReqDone (reqCtrl, iTimeout); if (ret == SD_SUCCESS) { ident_resp = reqCtrl->u.ident.resp_info; apr_snprintf( ident_str, sizeof(ident_str), "Vendor = %s, Model = %s, Rev = %s", ident_resp->vend, ident_resp->model, ident_resp->rev); printf ("%s\n",ident_str); *ident = ident_str; } else printf ("\n mvl_identify () Error, ret = 0x%X.", ret); mvl_free_req_ctrl (reqCtrl); return ret; } #if (MMS_STATUS_EN & REQ_EN) ST_RET mms_mvla_status (MVL_NET_INFO *net_info,int iTimeout) { ST_RET ret; STATUS_REQ_INFO status_req; MVL_REQ_PEND *reqCtrl; status_req.extended = SD_FALSE; ret = mvla_status (net_info, &status_req, &reqCtrl); if (ret == SD_SUCCESS) ret = waitReqDone (reqCtrl, iTimeout); if (ret != SD_SUCCESS) printf ("\n mvl_status () Error, ret = 0x%x ", ret); else { // printf (" mvl_status OK \n"); // printf ("\n logical status = %d", reqCtrl->u.status.resp_info->logical_stat); // printf ("\n physical status = %d", reqCtrl->u.status.resp_info->physical_stat); // if (reqCtrl->u.status.resp_info->local_detail_pres == SD_FALSE) // printf ("\n No local detail"); // else // { // printf ("\n Local detail present"); // printf ("\n Local detail len = %d bits", // reqCtrl->u.status.resp_info->local_detail_len); // } } mvl_free_req_ctrl (reqCtrl); return ret; } #endif #if (MMS_OBTAINFILE_EN & REQ_EN) ST_RET mms_mvla_obtfile (MVL_NET_INFO *net_info,ST_CHAR *srcfilename, ST_CHAR *destfilename,int iTimeout) { MVL_REQ_PEND *reqCtrl; ST_RET ret = mvla_obtfile (net_info, srcfilename, destfilename, &reqCtrl); if (ret == SD_SUCCESS) ret = waitReqDone (reqCtrl, iTimeout); if (ret != SD_SUCCESS) printf ("\n mvl_obtfile () Error obtaining file '%s', ret = 0x%X.", srcfilename, ret); else printf ("\n mvl_obtfile () of '%s' OK.", srcfilename); mvl_free_req_ctrl (reqCtrl); return ret; } #endif #if (MMS_FDELETE_EN & REQ_EN) ST_RET mms_mvla_fdelete (MVL_NET_INFO *net_info,ST_CHAR *file_to_delete,int iTimeout) { MVL_REQ_PEND *reqCtrl; ST_RET ret = mvla_fdelete (net_info, file_to_delete, &reqCtrl); if (ret == SD_SUCCESS) ret = waitReqDone (reqCtrl, iTimeout); if (ret != SD_SUCCESS) printf ("\n mvl_fdelete () Error deleting file '%s', ret = 0x%X.", file_to_delete, ret); else printf ("\n mvl_fdelete () of '%s' OK.", file_to_delete); mvl_free_req_ctrl (reqCtrl); return ret; } #endif //用于发送文件目录请求,获取远程设备的文件列表,并返回符合条件的文件名。 #if (MMS_FDIR_EN & REQ_EN) ST_RET mms_mvla_fdir (MVL_NET_INFO *net_info,ST_CHAR *filespec,int iTimeout, char*** filenames ,int* filenum,apr_pool_t *pool) { MVL_REQ_PEND *reqCtrl; MVL_FDIR_RESP_INFO *fdir_resp; ST_RET ret; ST_CHAR ca_filename[255]; ST_BOOLEAN more_follows = SD_FALSE; ST_INT i; char** filenames2; *filenum = 0; // "*.*", /* fs_name */ do { if (more_follows) ret = mvla_fdir (net_info, filespec, ca_filename ,&reqCtrl); else ret = mvla_fdir (net_info, filespec, NULL ,&reqCtrl); if (ret == SD_SUCCESS) ret = waitReqDone (reqCtrl, iTimeout); if (ret != SD_SUCCESS) { printf ("\n mvl_fdir () Error, ret = 0x%X. \n", ret); mvl_free_req_ctrl (reqCtrl); /* CRITICAL: */ break; } else { fdir_resp = reqCtrl->u.fdir.resp_info; more_follows = fdir_resp->more_follows; printf ("\n mvl_fdir results: num=%i \n",fdir_resp->num_dir_ent); filenames2 = apr_pcalloc( pool,(*filenum+fdir_resp->num_dir_ent)*sizeof(char*) ); for ( i = 0; i < *filenum; ++i) filenames2[i] =(*filenames)[i]; (*filenames) = filenames2; for (i = 0; i < fdir_resp->num_dir_ent; i++) { //printf ("\n File #%d: %s", i, fdir_resp->dir_ent[i].filename); (*filenames)[*filenum+i] = apr_pstrdup(pool,fdir_resp->dir_ent[i].filename); } } if (fdir_resp->num_dir_ent >0 ) strcpy(ca_filename,fdir_resp->dir_ent[fdir_resp->num_dir_ent-1].filename); *filenum += fdir_resp->num_dir_ent; mvl_free_req_ctrl (reqCtrl); /* CRITICAL: */ } while (more_follows); return ret; } #endif #if (MMS_GETNAMES_EN & REQ_EN) //#define MMS_CLASS_VAR 0 //#define MMS_CLASS_SCAT_ACC 1 //#define MMS_CLASS_VARLIST 2 //#define MMS_CLASS_TYPE 3 //#define MMS_CLASS_SEM 4 //#define MMS_CLASS_EV_COND 5 //#define MMS_CLASS_EV_ACT 6 //#define MMS_CLASS_EV_ENROLL 7 //#define MMS_CLASS_JOU 8 //#define MMS_CLASS_DOM 9 //#define MMS_CLASS_PI 10 //#define MMS_CLASS_OPER_STA 11 ST_RET mms_mvla_getnam (MVL_NET_INFO *net_info,ST_INT scope, ST_CHAR *domName,ST_INT16 mms_class, int iTimeout, char*** varnames ,int* varnum,apr_pool_t *pool) { MVL_REQ_PEND *reqCtrl; NAMELIST_REQ_INFO getnam_req; NAMELIST_RESP_INFO *getnam_resp; ST_RET ret; ST_CHAR continue_after[255]; ST_BOOLEAN more_follows = SD_FALSE; ST_CHAR **nptr; ST_INT i; char** varnames2; *varnum=0; getnam_req.cs_objclass_pres = SD_FALSE; getnam_req.obj.mms_class = mms_class; getnam_req.objscope = scope; if (scope == DOM_SPEC) strcpy (getnam_req.dname, domName); //getnam_req.dname = domName; /* set domain name */ getnam_req.cont_after_pres = SD_FALSE; do { if (more_follows) { getnam_req.cont_after_pres = SD_TRUE; strcpy(getnam_req.continue_after,continue_after); } ret = mvla_getnam (net_info, &getnam_req, &reqCtrl); if (ret == SD_SUCCESS) ret = waitReqDone (reqCtrl, iTimeout); if (ret != SD_SUCCESS) { printf ("\n mvl_getnam () Error, ret = 0x%x.", ret); more_follows = SD_FALSE; } else { // printf ("\n mvl_getnam OK"); getnam_resp = (NAMELIST_RESP_INFO *) reqCtrl->u.ident.resp_info; more_follows = getnam_resp->more_follows; //if (more_follows) { // printf ("\n More Follows : TRUE"); //} //else { // printf ("\n More Follows : FALSE"); //} printf("★");// //printf ("mms_mvla_getname %d Names returned . \n",getnam_resp->num_names); varnames2 = apr_pcalloc( pool,(*varnum+getnam_resp->num_names)*sizeof(char*) ); for ( i = 0; i < *varnum; ++i) varnames2[i] =(*varnames)[i]; (*varnames) = varnames2; //printf ("\n Name List :"); nptr = (ST_CHAR **) (getnam_resp + 1); for ( i = 0; i < getnam_resp->num_names; ++i) (*varnames)[*varnum +i] = apr_pstrdup(pool, nptr[i] ); //printf ("\n%d %s ",total+i,nptr[i]); if (getnam_resp->num_names >0 ) strcpy(continue_after,nptr[getnam_resp->num_names-1]); *varnum += getnam_resp->num_names; } mvl_free_req_ctrl (reqCtrl); } while (more_follows); return ret; } #endif ST_RET mms_rcb_setEntryID(MVL_NET_INFO *netInfo, ST_CHAR *domName, ST_CHAR *rcbName, RPT_TYPEIDS *rpt_typeids, ST_INT timeOut, ST_UINT8* pEntryID) { ST_RET ret; ST_CHAR varName [MAX_IDENT_LEN + 1]; apr_snprintf (varName, sizeof(varName), "%s$EntryID", rcbName); ret = mms_named_var_write (netInfo, varName, DOM_SPEC, domName, rpt_typeids->ostring8, (ST_CHAR *)pEntryID, timeOut); if (ret == SD_SUCCESS) printf ("\n Report setEntryID successed,EntryID: %02x %02x %02x %02x %02x %02x %02x %02x \n", *pEntryID, *(pEntryID+1), *(pEntryID+2), *(pEntryID+3), *(pEntryID+4), *(pEntryID+5), *(pEntryID+6), *(pEntryID+7) ); else echo_warn8("\n Report setEntryID failed,EntryID: %02x %02x %02x %02x %02x %02x %02x %02x \n", *pEntryID, *(pEntryID+1), *(pEntryID+2), *(pEntryID+3), *(pEntryID+4), *(pEntryID+5), *(pEntryID+6), *(pEntryID+7) ); return ret; } /************************************************************************/ /* mms_register_iec_rpt */ /* This function sets up to receive IEC-61850 or UCA reports on this connection*/ // RCB (e.g. "LLN0$BR$PosReport") /************************************************************************/ RCB_INFO* mms_register_iec_rpt (MVL_NET_INFO *clientNetInfo, RPT_TYPEIDS *rpt_typeids, ST_CHAR *dom_name,ST_CHAR *rcb_name,ST_INT timeOut, ST_INT scanRate,ST_UCHAR trgops,ST_UINT8* pEntryID,ST_UINT8* OptFlds ) { ST_RET ret; RCB_INFO *rcb_info; /* UCA/IEC Report Control Block info */ //ST_UCHAR OptFlds [2]; /* 10 bit bitstring but only allow write of 9 bits*/ ST_UCHAR TrgOps [1]; /* 8 bit bitstring */ rcb_info = rcb_info_create (clientNetInfo, dom_name, rcb_name, rpt_typeids, timeOut); if (rcb_info) { //先注销报告先 ST_BOOLEAN RptDisEna = 0; /* 0 = disable the report */ ST_CHAR varName [MAX_IDENT_LEN + 1]; apr_snprintf (varName,sizeof(varName), "%s$RptEna", rcb_name); mms_named_var_write (clientNetInfo, varName, DOM_SPEC, dom_name, rpt_typeids->mmsbool, (ST_CHAR *) &RptDisEna, timeOut); printf ("rcb_info->numDsVar = %d\n", rcb_info->numDsVar); /* Enable options we want to see in report. */ //OptFlds [0] = 0; /* These options valid for IEC BRCB, IEC URCB, or UCA. */ //BSTR_BIT_SET_ON(OptFlds, OPTFLD_BITNUM_SQNUM); //BSTR_BIT_SET_ON(OptFlds, OPTFLD_BITNUM_TIMESTAMP); //BSTR_BIT_SET_ON(OptFlds, OPTFLD_BITNUM_REASON); //BSTR_BIT_SET_ON(OptFlds, OPTFLD_BITNUM_DATSETNAME); /* NOTE: these options ONLY available for IEC-61850 (not UCA) * SUBSEQNUM is only set by the server, so don't try to set it. */ if (rcb_info->rcb_type == RCB_TYPE_IEC_BRCB) { /* These only valid for IEC BRCB */ // BSTR_BIT_SET_ON(OptFlds, OPTFLD_BITNUM_BUFOVFL); BSTR_BIT_SET_ON(OptFlds, OPTFLD_BITNUM_ENTRYID); if ((pEntryID[0]!=0xff)||(pEntryID[1]!=0xff)||(pEntryID[2]!=0xff)||(pEntryID[3]!=0xff) ||(pEntryID[4]!=0xff)||(pEntryID[5]!=0xff)||(pEntryID[6]!=0xff)||(pEntryID[7]!=0xff) ) mms_rcb_setEntryID(clientNetInfo, dom_name, rcb_name, rpt_typeids, timeOut, pEntryID); } //if (rcb_info->rcb_type != RCB_TYPE_UCA) // { /* These only valid for IEC BRCB or IEC URCB */ // BSTR_BIT_SET_ON(OptFlds, OPTFLD_BITNUM_DATAREF); // BSTR_BIT_SET_ON(OptFlds, OPTFLD_BITNUM_CONFREV); // } TrgOps [0] = trgops; ret = rcb_enable (clientNetInfo, dom_name, rcb_name, OptFlds, TrgOps, scanRate*1000, /* Integrity Period (ms) */ rpt_typeids, timeOut); /* timeout (s) */ if(ret == SD_SUCCESS) { list_add_last(&((ALL_RCB_INFO *)clientNetInfo->user_info)->rcb_info_list, rcb_info); /* add RCB to list*/ } else{ rcb_info_destroy(rcb_info); rcb_info = NULL; echo_warn2 ("rcb_enable error for dom='%s', rcb='%s'\n", dom_name, rcb_name); } } else { printf ("rcb_info_create error for dom='%s', rcb='%s'\n", dom_name, rcb_name); rcb_info = NULL; } return (rcb_info); } /////////////////////////////////////////// //WW 2023-08-29 增加设备类型处理,优化报告触发速度 RCB_INFO* mms_register_iec_rpt_by_devtype(MVL_NET_INFO *clientNetInfo, RPT_TYPEIDS *rpt_typeids, ST_CHAR *dom_name, ST_CHAR *rcb_name, ST_INT timeOut, ST_CHAR *dev_type, ST_CHAR *ip, int port, ST_INT scanRate, ST_UCHAR trgops, ST_UINT8* pEntryID, ST_UINT8* OptFlds) { ST_RET ret; //ST_UCHAR OptFlds [2]; /* 10 bit bitstring but only allow write of 9 bits*/ ST_UCHAR TrgOps[1]; /* 8 bit bitstring */ //一、装置类型查找判断--------------------------------------------------------------------------------------------------------------------------- ST_BOOLEAN bFindDevType = 0; //是否在链表中查找到装置类型 Dev_RCB_INFO *dev_rcb = NULL;//装置报告结构指针 for (dev_rcb = gDev_rcb_list.dev_rcb_info_Head; dev_rcb != NULL; dev_rcb = (Dev_RCB_INFO *)list_get_next(gDev_rcb_list.dev_rcb_info_Head, dev_rcb)) //①遍历 全局装置报告控制块链表 { //LOG_INFO("(报告触发)遍历gDev_rcb_list链表, dev_type_name= %s", dev_rcb->dev_type_name); //仅调试使用! zl 2019-12-24 00:16:31 if ((strcmp(dev_rcb->dev_type_name, dev_type) == 0)) //匹配 装置类型 { bFindDevType = 1; //查找到装置类型 //LOG_INFO("(报告触发)匹配到装置类型,dev_type_name= %s", dev_rcb->dev_type_name); //仅调试使用! zl 2019-12-24 00:23:55 break; } } //遍历 装置类型链表 结束 if (!bFindDevType) //未查找到装置类型 { dev_rcb = (Dev_RCB_INFO *)chk_calloc(1, sizeof(Dev_RCB_INFO)); //调用 申请连续内存空间,并初始化为0,返回首地址指针,相当于New strcpy(dev_rcb->dev_type_name, dev_type); //装置类型 //LOG_INFO("(报告触发)新增装置类型,dev_type_name= %s", dev_rcb->dev_type_name); //仅调试使用! zl 2019-12-24 00:23:55 list_add_last(&gDev_rcb_list.dev_rcb_info_Head, dev_rcb); //添加 全局装置报告控制块链表 } //二、装置IP、端口号查找判断--------------------------------------------------------------------------------------------------------------------------------------------------- ST_BOOLEAN bFindIpPort = 0; //是否在链表中查找到装置IP、端口号 Dev_IP_Port_INFO *dev_info = NULL; //装置IP、端口号结构指针 for (dev_info = dev_rcb->dev_ip_port_list; dev_info != NULL; dev_info = (Dev_IP_Port_INFO *)list_get_next(dev_rcb->dev_ip_port_list, dev_info)) //②遍历 全局装置IP、端口链表 { //LOG_INFO("(报告触发)遍历dev_ip_port_list链表, dev_type_name= %s, ip= %s, port= %d", dev_rcb->dev_type_name, dev_info->IP, dev_info->Port); //仅调试使用! zl 2019-12-24 00:16:31 if ((strcmp(dev_info->IP, ip) == 0) && (dev_info->Port == port)) //匹配 装置IP && 端口号 { bFindIpPort = 1; //查找到装置IP && 端口号 //LOG_INFO("(报告触发)匹配到装置dev_type_name= %s, IP= %s, Port= %d", dev_rcb->dev_type_name, dev_info->IP, dev_info->Port); //仅调试使用! zl 2019-12-24 00:23:55 break; } }//遍历 装置IP、端口链表 结束 if (!bFindIpPort) //未查找到装置IP、端口 { dev_info = (Dev_IP_Port_INFO *)chk_calloc(1, sizeof(Dev_IP_Port_INFO)); //调用 申请连续内存空间,并初始化为0,返回首地址指针,相当于New strcpy(dev_info->IP, ip); //装置IP dev_info->Port = port; //端口号 //LOG_INFO("(报告触发)新增装置dev_type_name= %s, IP= %s, Port= %d", dev_rcb->dev_type_name, dev_info->IP, dev_info->Port); //仅调试使用! zl 2019-12-24 00:23:55 list_add_last(&dev_rcb->dev_ip_port_list, dev_info); //添加 全局装置报告控制块链表->装置IP、端口链表 } //三、装置报告控制块查找判断---------------------------------------------------------------------------------------------------------------------------------------------------------------------- RCB_INFO *rcb_info = NULL; //报告控制块指针 ST_BOOLEAN bFindRCB = 0; //是否在装置报告控制块链表中查找到 for (rcb_info = dev_rcb->rcb_info_list; rcb_info != NULL; rcb_info = (RCB_INFO *)list_get_next(dev_rcb->rcb_info_list, rcb_info)) //③遍历 全局装置报告控制块链表->报告控制块信息链表 { //LOG_INFO("(报告触发)遍历rcb_info_list链表, RptID= %s,dom_Name= %s,dom= %s,rcb_name= %s,rpt= %s", rcb_info->RptID, rcb_info->dom_Name, dom, rcb_info->rcb_name, rpt); //仅调试使用! zl 2018-10-17 21:19:36 if ((strcmp(rcb_info->rcb_name, rcb_name) == 0) && (strcmp(rcb_info->dom_Name, dom_name) == 0)) //匹配 装置报告控制块 { bFindRCB = 1; //查找到装置报告控制块 //LOG_INFO("(报告触发)匹配到报告控制块dev_type_name= %s, dom= %s,rcb= %s,已触发过!", dev_rcb->dev_type_name, dom, rpt); //仅调试使用! zl 2019-3-13 14:24:43 break; /* rcb_info now points to right structure */ } } if (!bFindRCB) //未查找到装置报告控制块 { rcb_info = rcb_info_create(clientNetInfo, dom_name, rcb_name, rpt_typeids, timeOut); //调用 创建装置报告控制块 —>> 注:该函数较为耗时,若本装置类型的报告控制块已创建过,则不需再进行创建! if (rcb_info == NULL) { //LOG_INFO("(报告触发)创建报告控制块失败!dev_type_name= %s, dom= %s,rcb= %s", dev_rcb->dev_type_name, dom, rpt); //仅调试使用! zl 2019-3-13 14:24:43 return SD_FAILURE; } else { //LOG_INFO("(报告触发)创建报告控制块成功,新增全局报告控制块链表!dev_type_name= %s, dom= %s,rcb= %s", dev_rcb->dev_type_name, dom, rpt); //仅调试使用! zl 2019-3-13 14:24:43 list_add_last(&dev_rcb->rcb_info_list, rcb_info); //添加 全局报告控制块链表->报告控制块信息链表 } //TRACE("(报告触发)创建报告控制块!dom= %s rcb= %s,耗时:%0.6f,报告大小:%d", dom, rpt, dwEnd - dwStart, sizeof(RCB_INFO)); } if (rcb_info) { //先注销报告先 WW 2023-08-29注释先注销报告的代码 //ST_BOOLEAN RptDisEna = 0; /* 0 = disable the report */ //ST_CHAR varName[MAX_IDENT_LEN + 1]; //apr_snprintf(varName, sizeof(varName), "%s$RptEna", rcb_name); //mms_named_var_write(clientNetInfo, varName, DOM_SPEC, dom_name, rpt_typeids->mmsbool, (ST_CHAR *)&RptDisEna, timeOut); //WW 2023-08-29 end printf("rcb_info->numDsVar = %d\n", rcb_info->numDsVar); /* Enable options we want to see in report. */ //OptFlds [0] = 0; /* These options valid for IEC BRCB, IEC URCB, or UCA. */ //BSTR_BIT_SET_ON(OptFlds, OPTFLD_BITNUM_SQNUM); //BSTR_BIT_SET_ON(OptFlds, OPTFLD_BITNUM_TIMESTAMP); //BSTR_BIT_SET_ON(OptFlds, OPTFLD_BITNUM_REASON); //BSTR_BIT_SET_ON(OptFlds, OPTFLD_BITNUM_DATSETNAME); /* NOTE: these options ONLY available for IEC-61850 (not UCA) * SUBSEQNUM is only set by the server, so don't try to set it. */ if (rcb_info->rcb_type == RCB_TYPE_IEC_BRCB) { /* These only valid for IEC BRCB */ // BSTR_BIT_SET_ON(OptFlds, OPTFLD_BITNUM_BUFOVFL); BSTR_BIT_SET_ON(OptFlds, OPTFLD_BITNUM_ENTRYID); if ((pEntryID[0] != 0xff) || (pEntryID[1] != 0xff) || (pEntryID[2] != 0xff) || (pEntryID[3] != 0xff) || (pEntryID[4] != 0xff) || (pEntryID[5] != 0xff) || (pEntryID[6] != 0xff) || (pEntryID[7] != 0xff)) mms_rcb_setEntryID(clientNetInfo, dom_name, rcb_name, rpt_typeids, timeOut, pEntryID); } //if (rcb_info->rcb_type != RCB_TYPE_UCA) // { /* These only valid for IEC BRCB or IEC URCB */ // BSTR_BIT_SET_ON(OptFlds, OPTFLD_BITNUM_DATAREF); // BSTR_BIT_SET_ON(OptFlds, OPTFLD_BITNUM_CONFREV); // } TrgOps[0] = trgops; ret = rcb_enable(clientNetInfo, dom_name, rcb_name, OptFlds, TrgOps, scanRate * 1000, /* Integrity Period (ms) */ rpt_typeids, timeOut); /* timeout (s) */ if (ret == SD_SUCCESS) { list_add_last(&((ALL_RCB_INFO *)clientNetInfo->user_info)->rcb_info_list, rcb_info); /* add RCB to list*/ } else { rcb_info_destroy(rcb_info); rcb_info = NULL; echo_warn2("rcb_enable error for dom='%s', rcb='%s'\n", dom_name, rcb_name); } } else { printf("rcb_info_create error for dom='%s', rcb='%s'\n", dom_name, rcb_name); rcb_info = NULL; } return (rcb_info); } ST_RET mms_unregister_iec_rpt_by_devtype(MVL_NET_INFO *clientNetInfo, RPT_TYPEIDS *rpt_typeids, ST_CHAR *dev_type, ST_CHAR *ip, int port, ST_CHAR *dom_name, ST_CHAR *rcb_name, ST_INT timeOut) { ST_BOOLEAN RptEna = 0; ST_CHAR varName[MAX_IDENT_LEN + 1]; ST_RET ret; //函数执行返回值 //一、装置类型查找判断--------------------------------------------------------------------------------------------------------------------------- ST_BOOLEAN bFindDevType = 0; //是否在链表中查找到装置类型 Dev_RCB_INFO *dev_rcb = NULL;//装置报告结构指针 for (dev_rcb = gDev_rcb_list.dev_rcb_info_Head; dev_rcb != NULL; dev_rcb = (Dev_RCB_INFO *)list_get_next(gDev_rcb_list.dev_rcb_info_Head, dev_rcb)) //①遍历 全局装置报告控制块链表 { //LOG_INFO("(报告停止)遍历gDev_rcb_list链表, dev_type_name= %s", dev_rcb->dev_type_name); //仅调试使用! zl 2019-12-24 00:16:31 if ((strcmp(dev_rcb->dev_type_name, dev_type) == 0)) //匹配 装置类型 { bFindDevType = 1; //查找到装置类型 //LOG_INFO("(报告停止)匹配到装置类型,dev_type_name= %s", dev_rcb->dev_type_name); //仅调试使用! zl 2019-12-24 00:23:55 break; } } //遍历 装置类型链表 结束 if (!bFindDevType) //未查找到装置类型 { dev_rcb = (Dev_RCB_INFO *)chk_calloc(1, sizeof(Dev_RCB_INFO)); //调用 申请连续内存空间,并初始化为0,返回首地址指针,相当于New //memset(dev_rcb, 0, sizeof(Dev_RCB_INFO)); //指针 清0 strcpy(dev_rcb->dev_type_name, dev_type); //装置类型 list_add_last(&gDev_rcb_list.dev_rcb_info_Head, dev_rcb); //添加 全局装置报告控制块链表 } //二、装置IP、端口号查找判断--------------------------------------------------------------------------------------------------------------------------------------------------- ST_BOOLEAN bFindIpPort = 0; //是否在链表中查找到装置IP、端口号 Dev_IP_Port_INFO *dev_info = NULL; //装置IP、端口号结构指针 for (dev_info = dev_rcb->dev_ip_port_list; dev_info != NULL; dev_info = (Dev_IP_Port_INFO *)list_get_next(dev_rcb->dev_ip_port_list, dev_info)) //②遍历 全局装置IP、端口链表 { //LOG_INFO("(报告停止)遍历dev_ip_port_list链表, dev_type_name= %s, ip= %s, port= %d", dev_rcb->dev_type_name, dev_info->IP, dev_info->Port); //仅调试使用! zl 2019-12-24 00:16:31 if ((strcmp(dev_info->IP, ip) == 0) && (dev_info->Port == port)) //匹配 装置IP && 端口号 { bFindIpPort = 1; //查找到装置IP && 端口号 //LOG_INFO("(报告停止)匹配到装置dev_type_name= %s, IP= %s, Port= %d", dev_rcb->dev_type_name, dev_info->IP, dev_info->Port); //仅调试使用! zl 2019-12-24 00:23:55 break; } } //遍历 装置IP、端口链表 结束 if (!bFindIpPort) //未查找到装置IP、端口 { dev_info = (Dev_IP_Port_INFO *)chk_calloc(1, sizeof(Dev_IP_Port_INFO)); //调用 申请连续内存空间,并初始化为0,返回首地址指针,相当于New //memset(dev_info, 0, sizeof(Dev_IP_Port_INFO)); //指针 清0 strcpy(dev_info->IP, ip); //装置IP dev_info->Port = port; //端口号 list_add_last(&dev_rcb->dev_ip_port_list, dev_info); //添加 全局装置报告控制块链表->装置IP、端口链表 } //三、装置报告控制块查找判断---------------------------------------------------------------------------------------------------------------------------------------------------------------------- RCB_INFO *rcb_info = NULL; //报告控制块指针 ST_BOOLEAN bFindRCB = 0; //是否在装置报告控制块链表中查找到 for (rcb_info = dev_rcb->rcb_info_list; rcb_info != NULL; rcb_info = (RCB_INFO *)list_get_next(dev_rcb->rcb_info_list, rcb_info)) //③遍历 全局装置报告控制块链表->报告控制块信息链表 { //LOG_INFO("(报告停止)遍历rcb_info_list链表, RptID= %s,dom_Name= %s,dom= %s,rcb_name= %s,rpt= %s", rcb_info->RptID, rcb_info->dom_Name, dom, rcb_info->rcb_name, rpt); //仅调试使用! zl 2018-10-17 21:19:36 //if ((strcmp (rcb_info->rcb_name, rpt) == 0) && (strcmp(rcb_info->dom_Name, dom) == 0)) //匹配 装置报告控制块 —— 废弃! zl 2019-12-26 17:27:29 if ((strcmp(rcb_info->rcb_name, rcb_name) == 0)) //匹配 装置报告控制块 { bFindRCB = 1; //查找到装置报告控制块 //LOG_INFO("(报告停止)匹配到报告控制块dom= %s,rcb= %s,已触发过!", dom, rpt); //仅调试使用! zl 2019-3-13 14:24:43 break; /* rcb_info now points to right structure */ } } if (!bFindRCB) //未查找到装置报告控制块 { rcb_info = rcb_info_create(clientNetInfo, dom_name, rcb_name, rpt_typeids, timeOut); //调用 创建装置报告控制块 —>> 注:该函数较为耗时,若本装置类型的报告控制块已创建过,则不需再进行创建! if (rcb_info == NULL) { //LOG_INFO("(报告停止)创建报告控制块失败!dom= %s,rcb= %s", dom, rpt); //仅调试使用! zl 2019-3-13 14:24:43 return SD_FAILURE; } else { //LOG_INFO("(报告停止)创建报告控制块成功,新增全局报告控制块链表!dom= %s,rcb= %s", dom, rpt); //仅调试使用! zl 2019-3-13 14:24:43 list_add_last(&dev_rcb->rcb_info_list, rcb_info); //添加 全局报告控制块链表->报告控制块信息链表 } } sprintf(varName, "%s$RptEna", rcb_name); //报告停止 例:LLN0$BR$brcbStatisticData03$RptEna ret = mms_named_var_write(clientNetInfo, varName, DOM_SPEC, dom_name, rpt_typeids->mmsbool, (ST_CHAR *)&RptEna, timeOut); //调用 写入装置报告控制块(报告停止) return ret; } //WW 2023-08-29 end //////////////////////////////////// ST_RET mms_unregister_iec_rpt (MVL_NET_INFO *clientNetInfo, RPT_TYPEIDS *rpt_typeids, ST_CHAR *dom_name, ST_CHAR *rcb_name, ST_INT timeOut ) { ST_RET ret; RCB_INFO *rcb_info; RCB_INFO* this_rcb_info; this_rcb_info = FindRcbInfo(clientNetInfo,dom_name,rcb_name ); ret = rcb_disable(clientNetInfo, dom_name, rcb_name,rpt_typeids,timeOut); // remove the if condition ALL_RCB_INFO *all_rcb_info = (ALL_RCB_INFO *)clientNetInfo->user_info ; for (rcb_info = all_rcb_info->rcb_info_list; rcb_info != NULL; rcb_info = (RCB_INFO *) list_get_next (all_rcb_info->rcb_info_list, rcb_info)) { if( rcb_info == this_rcb_info ) { ret = list_unlink(&all_rcb_info->rcb_info_list, rcb_info); if(ret == SD_SUCCESS) { rcb_info_destroy(rcb_info); return ret; } } } return SD_FAILURE; } /************************************************************************/ /* doCommService */ /************************************************************************/ ST_VOID doCommService () { #if defined (MOSI) /* If stack is MOSI, use events */ wait_any_event (50); /* Wait 50 milliseconds */ while (mvl_comm_serve ()) /* Perform communications service */ { /* Loop until "mvl_comm_serve" returns 0*/ } #else mvl_comm_serve (); /* Perform communications service */ #endif } /************************************************************************/ /* connectToServer */ /************************************************************************/ // 检查字符串是否为空、仅空格或不可见字符lnk20241119 int is_empty_or_whitespace(const char* str) { if (str == NULL) { return 1; // NULL 情况,视为"空" } while (*str) { if (!isspace((unsigned char)*str)) { return 0; // 有非空格字符,非"空" } str++; } return 1; // 全是空格或不可见字符,视为"空" } ST_RET mms_connectToServer (ST_CHAR * dev_key,ST_CHAR *dev_series, ST_CHAR *serverARName, MVL_NET_INFO **clientNetInfo, MVL_REQ_PEND **reqCtrl) { ST_RET ret; #if defined(S_SEC_ENABLED) || defined(ACSE_AUTH_ENABLED) ST_CHAR ied_password[256]; ACSE_AUTH_INFO authInfoStr = {0}; #endif #if defined(S_SEC_ENABLED) S_SEC_ENCRYPT_CTRL encryptCtrlStr = {0}; S_SEC_LOC_AR *loc_ar_sec = NULL; S_SEC_REM_AR *rem_ar_sec = NULL; #endif ACSE_AUTH_INFO *authInfo = NULL; /* conn authentication info */ S_SEC_ENCRYPT_CTRL *encryptCtrl = NULL; /* conn enctryption info */ callingInitInfo.mms_p_context_pres = SD_TRUE; callingInitInfo.max_segsize_pres = SD_TRUE; callingInitInfo.max_segsize = mvl_cfg_info->max_msg_size; callingInitInfo.maxreq_calling = 1; callingInitInfo.maxreq_called = 1; callingInitInfo.max_nest_pres = SD_TRUE; callingInitInfo.max_nest = 5; callingInitInfo.mms_detail_pres = SD_TRUE; callingInitInfo.version = 1; callingInitInfo.num_cs_init = 0; callingInitInfo.core_position = 0; callingInitInfo.param_supp[0] = m_param[0]; callingInitInfo.param_supp[1] = m_param[1]; memcpy (callingInitInfo.serv_supp, m_service_resp,11); #if defined(S_SEC_ENABLED) authInfo = &authInfoStr; encryptCtrl = &encryptCtrlStr; /* set authentication and encryption infor for this connection */ ret = ulSetSecurityCalling (clientARName, serverARName, &loc_ar_sec, &rem_ar_sec, authInfo, encryptCtrl); if (ret != SD_SUCCESS)9 { printf ("\n Initialization of security info failed"); return (NULL); /* error */ } #elif defined(ACSE_AUTH_ENABLED) if (g_no_auth==0) { /* Fill out an authentication structure */ //authInfo = &authInfoStr; //authInfo->auth_pres = SD_TRUE; //authInfo->mech_type = ACSE_AUTH_MECH_PASSWORD; //memset(ied_password,0,sizeof(ied_password)); //lnk20241119添加判断和打印,确保识别码秘钥为空时不调用加密 if (!is_empty_or_whitespace(dev_series) || !is_empty_or_whitespace(dev_key)) { printf("dev_series= %s\n", dev_series); printf("dev_key= %s\n", dev_key); /* Fill out an authentication structure */ authInfo = &authInfoStr; authInfo->auth_pres = SD_TRUE; authInfo->mech_type = ACSE_AUTH_MECH_PASSWORD; memset(ied_password,0,sizeof(ied_password)); GetSM4Code((unsigned char*)dev_series,dev_key,ied_password); strcpy (authInfo->u.pw_auth.password, ied_password); } else { printf("dev_series or dev_key is null or space!\n"); } //GetSM4Code((unsigned char*)dev_series,dev_key,ied_password); //strcpy (authInfo->u.pw_auth.password, ied_password); //cout<<"old password:"<< ied_password <u.pw_auth.password, "7a88179802378762611182956231b315"); /* this is the password */ } #endif /* defined(ACSE_AUTH_ENABLED) */ // *reqCtrl = NULL; *clientNetInfo = NULL; ret = mvla_initiate_req_ex (serverARName, &callingInitInfo, &initRespInfo, clientNetInfo, reqCtrl, authInfo, encryptCtrl); if (ret == SD_SUCCESS) { #if defined(S_SEC_ENABLED) /* Save the AR Security pointers, for convenience when the confirm is rxd */ clientNetInfo->loc_ar_sec = loc_ar_sec; clientNetInfo->rem_ar_sec = rem_ar_sec; #endif // ret = waitReqDone (reqCtrl, 60); /* need to wait longer on connect */ } if (ret != SD_SUCCESS) *clientNetInfo = NULL; //printf ("\n %s clientNetInfo = 0x%x ,ret =0x%X ",serverARName,*clientNetInfo,ret); #if defined(S_SEC_ENABLED) ulFreeAssocSecurity (authInfo); /* free local auth info, not needed anymore */ #endif // mvl_free_req_ctrl (reqCtrl); return ret; } /************************************************************************/ /* disconnectFromServer */ /************************************************************************/ ST_RET mms_disconnectFromServer (MVL_NET_INFO *clientNetInfo,MVL_REQ_PEND **reqCtrl) { ST_RET ret; echo_warn1( "mms_disconnectFromServer clientNetInfo= %x \n",clientNetInfo); ret = mvla_concl (clientNetInfo, reqCtrl); //waitReqDone (*reqCtrl, 0); //mvl_free_req_ctrl (*reqCtrl); return ret; } ST_RET mms_release_connection (MVL_NET_INFO *clientNetInfo) { echo_warn1( "mms_release_connection NetInfo= %x \n",clientNetInfo); mvl_abort_req(clientNetInfo); return SD_SUCCESS; } /************************************************************************/ /* u_mvl_info_rpt_ind */ /************************************************************************/ ST_VOID u_mvl_info_rpt_ind (MVL_COMM_EVENT *event) { //printf(" ST_VOID u_mvl_info_rpt_ind (MVL_COMM_EVENT *event) \n"); //printf(" %d \n",event->net_info);//->rem_ar_sec->arName); INFO_REQ_INFO *info_ptr; ST_INT j; OBJECT_NAME *vobj; VARIABLE_LIST *vl; VAR_ACC_SPEC *va_spec; //MVL_VAR_ASSOC *va; ST_INT num_va; ST_CHAR *name; /* Assume this is an IEC-61850/UCA report, and try to process it. * If processing successful, then skip other processing. */ //WW 2023-08-30 if (u_iec_rpt_ind (event) == SD_SUCCESS) // if (u_iec_rpt_ind_by_devtype(event) == SD_SUCCESS) return; /* this funct processed it. Skip other processing. */ //WW 2023-08-30 end /* We want to get a table of pointers to VARIABLE_ASSOCIATIONS so we */ /* can convert the received data to local format. */ info_ptr = (INFO_REQ_INFO *) event->u.mms.dec_rslt.data_ptr; va_spec = &info_ptr->va_spec; num_va = info_ptr->num_of_acc_result; if (va_spec->var_acc_tag == VAR_ACC_NAMEDLIST) { printf ("Unrecognized Report received with NamedVariableList='%s'. Ignored.\n", va_spec->vl_name.obj_name.vmd_spec); } else if (va_spec->var_acc_tag == VAR_ACC_VARLIST) { vl = (VARIABLE_LIST *) (info_ptr + 1); for (j = 0; j < num_va; ++j, ++vl) { printf (" Recognized Report received with NamedVariable "); if (vl->var_spec.var_spec_tag == VA_SPEC_NAMED) { vobj = &vl->var_spec.vs.name; name = vobj->obj_name.vmd_spec; printf (" var name= %s \n ",name); if (!strcmp (name, my_control_info.oper_name) && vobj->object_tag == DOM_SPEC) { /* This is IEC 61850 CommandTermination. Save num of vars. */ my_control_info.cmd_term_num_va = num_va; } } else { printf ("InfoRpt Ind : VA Spec not named \n"); } } } /* end if VAR_ACC_VARLIST */ } /************************************************************************/ /* u_mvl_connect_ind_ex */ /*----------------------------------------------------------------------*/ /* This function is called when a remote node has connected to us. We */ /* can look at the assReqInfo to see who it is (assuming that the */ /* AP-Titles are used), or at the cc->rem_init_info to see initiate */ /* request parameters. */ /************************************************************************/ extern ST_ACSE_AUTH u_mvl_connect_ind_ex (MVL_NET_INFO *cc, INIT_INFO *init_info, ACSE_AUTH_INFO *req_auth_info, ACSE_AUTH_INFO *rsp_auth_info) { ST_ACSE_AUTH ret = ACSE_AUTH_SUCCESS; #if defined(S_SEC_ENABLED) /* this Client will reject the connection since there is no security */ /* checking code in place (see Server for sample) */ ret = ACSE_DIAG_NO_REASON; #elif defined(ACSE_AUTH_ENABLED) /* this Client will reject the connection since there is no password */ /* checking code in place (see Server for sample) */ if (g_no_auth==0) ret = ACSE_DIAG_NO_REASON; else return (ret); #endif return (ret); } /************************************************************************/ /* u_mvl_connect_cnf_ex */ /*----------------------------------------------------------------------*/ /* This function is called when we have received an initiate response. */ /* Depending on the server's authentication scheme, we may have been */ /* sent responding authentication that we can pull out of the response */ /* PDU. */ /************************************************************************/ ST_ACSE_AUTH u_mvl_connect_cnf_ex (MVL_NET_INFO *cc, AARE_APDU *ass_rsp_info) { ST_RET ret = ACSE_AUTH_SUCCESS; #if defined(S_SEC_ENABLED) /* check security parameters of the Associate Confirm */ ret = ulCheckSecureAssocConf (cc); #elif defined(ACSE_AUTH_ENABLED) if (g_no_auth==0) { ACSE_AUTH_INFO *rsp_auth_info; rsp_auth_info = &ass_rsp_info->auth_info; if(rsp_auth_info->auth_pres == SD_TRUE) { /* Looks like we have some authentication to look at, simply print */ /* the password and continue as normal. */ if(rsp_auth_info->mech_type == ACSE_AUTH_MECH_PASSWORD) { //printf("\nPassword recieved from peer: %s\n", rsp_auth_info->u.pw_auth.password); } /* We were sent a mechanism we don't support, let's reject the */ /* the connection with the appropriate diagnostic. */ else { ret = ACSE_DIAG_AUTH_MECH_NAME_NOT_RECOGNIZED; } } else { /* Hmm... looks like we weren't sent any authentication even though */ /* we require it. Let's reject with the appropriate diagnostic. */ ret = ACSE_AUTH_SUCCESS;//ww 2024-01-09 ACSE DIAG AUTH REQUIRED } } #endif /* defined(ACSE_AUTH_ENABLED) */ /* to accept the confirm ACSE_AUTH_SUCCESS need to be returned */ return ((ST_ACSE_AUTH) ret); } /************************************************************************/ /* disc_ind_fun */ /************************************************************************/ /* This function is called when connection is terminated. */ static ST_VOID disc_ind_fun (MVL_NET_INFO *cc, ST_INT discType) { ALL_RCB_INFO *all_rcb_info; RCB_INFO *rcb_info; printf("disc_ind_fun clientNetInfo= 0x%x discType=%i\n",cc,discType); Callback_channel_disconnect_ind(cc, discType); /* Free up rcb_info if necessary. */ if (cc->user_info) { all_rcb_info = (ALL_RCB_INFO*)cc->user_info; while ((rcb_info =(RCB_INFO*) list_get_first (&all_rcb_info->rcb_info_list)) != NULL) rcb_info_destroy (rcb_info); chk_free (all_rcb_info); cc->user_info=NULL; } cc->rem_vmd = NULL; } #if (MMS_IDENT_EN & RESP_EN) /************************************************************************/ /* u_mvl_ident_ind */ /************************************************************************/ ST_VOID u_mvl_ident_ind (MVL_IND_PEND *indCtrl) { //#if 0 /* enable this to print when Ind received */ printf ("\n Identify Indication received."); //#endif indCtrl->u.ident.resp_info = &identify_response_info; mplas_ident_resp (indCtrl); } #endif /* #if (MMS_IDENT_EN & RESP_EN) */ /************************************************************************/ /* getFile */ /************************************************************************/ ST_RET mms_getFile (MVL_NET_INFO *clientNetInfo, ST_CHAR *loc_file, ST_CHAR *rem_file, ST_INT iTimeout) { FREAD_REQ_INFO fread_req_info; FCLOSE_REQ_INFO fclose_req_info; ST_RET ret; FILE *loc_fp; MVL_REQ_PEND *reqCtrl; ST_INT32 frsmid; ST_BOOLEAN more_follows; ret = mvla_fopen (clientNetInfo, rem_file, 0, /* init_pos: start at beginning of file */ &reqCtrl); if (ret == SD_SUCCESS) ret = waitReqDone (reqCtrl, iTimeout); if (ret == SD_SUCCESS) frsmid = reqCtrl->u.fopen.resp_info->frsmid; /* save frsmid */ mvl_free_req_ctrl (reqCtrl); if (ret != SD_SUCCESS) return (ret); loc_fp = fopen (loc_file, "wb"); if (loc_fp == NULL) goto ERR; fread_req_info.frsmid = frsmid; /* "fread" request doesn't chg. */ do { ret = mvla_fread (clientNetInfo, &fread_req_info, &reqCtrl); if (ret == SD_SUCCESS) ret = waitReqDone (reqCtrl, iTimeout); if (ret == SD_SUCCESS) { more_follows = reqCtrl->u.fread.resp_info->more_follows; fwrite (reqCtrl->u.fread.resp_info->filedata, 1, reqCtrl->u.fread.resp_info->fd_len, loc_fp); } mvl_free_req_ctrl (reqCtrl); if (ret != SD_SUCCESS) goto ERR; } while (more_follows); fclose_req_info.frsmid = frsmid; ret = mvla_fclose (clientNetInfo, &fclose_req_info, &reqCtrl); if (ret == SD_SUCCESS) ret = waitReqDone (reqCtrl, iTimeout); if (ret != SD_SUCCESS) printf ("\n mvl_fclose failed, ret = 0x%X", ret); mvl_free_req_ctrl (reqCtrl); fclose (loc_fp); return (SD_SUCCESS); ERR: if (loc_fp == NULL) { return (SD_FAILURE); /* Can't open local file. */ } else { fclose(loc_fp); return (ret); } } /************************************************************************/ /* init_mem */ /************************************************************************/ static ST_VOID mem_chk_error_detected (ST_VOID); static ST_VOID *my_malloc_err (ST_UINT size); static ST_VOID *my_calloc_err (ST_UINT num, ST_UINT size); static ST_VOID *my_realloc_err (ST_VOID *old, ST_UINT size); static ST_CHAR *spareMem; static ST_VOID init_mem () { #if defined(NO_GLB_VAR_INIT) mvl_init_glb_vars (); #endif /* Allocate spare memory to allow logging/printing memory errors */ spareMem = (ST_CHAR *) malloc (500); /* trap mem_chk errors */ mem_chk_err = mem_chk_error_detected; m_memerr_fun = my_malloc_err; c_memerr_fun = my_calloc_err; r_memerr_fun = my_realloc_err; #if 0 m_heap_check_enable = SD_TRUE; m_check_list_enable = SD_TRUE; m_no_realloc_smaller = SD_TRUE; m_fill_en = SD_TRUE; #endif m_mem_debug = SD_TRUE; } /************************************************************************/ /* This function is called from the DEBUG version of the mem library */ /* when an error of any type is detected. */ /************************************************************************/ static ST_INT memErrDetected; static ST_VOID mem_chk_error_detected (ST_VOID) { if (!memErrDetected) { free (spareMem); memErrDetected = SD_TRUE; printf ("\n Memory Error Detected!"); dyn_mem_ptr_status (); } } /************************************************************************/ /* Memory Allocation Error Handling Functions. */ /* These functions are called from mem_chk when it is unable to */ /* perform the requested operation. These functions must either return */ /* a valid buffer or not return at all. */ /************************************************************************/ static ST_VOID *my_malloc_err (ST_UINT size) { mem_chk_error_detected (); printf ("\n Malloc"); exit (2); return (NULL); } static ST_VOID *my_calloc_err (ST_UINT num, ST_UINT size) { mem_chk_error_detected (); exit (3); return (NULL); } static ST_VOID *my_realloc_err (ST_VOID *old, ST_UINT size) { mem_chk_error_detected (); exit (4); return (NULL); } ///////////////////////////////////////////////////////////////////////// //#define MAX_FILE_HANDLE_NUM (256) //static FILE *fp_arr[MAX_FILE_HANDLE_NUM]; //static ST_INT32 cur_handle = 0; //ST_INT32 set_file_pointer( FILE *fp) //{ // ST_INT32 the_handle = cur_handle; // fp_arr[cur_handle++] = fp; // cur_handle %= MAX_FILE_HANDLE_NUM; // return the_handle; //} //FILE* get_file_pointer(ST_INT32 handle) //{ // return fp_arr[handle]; //} /////////////////////////////////////////////////////////////////////// #if (MMS_FOPEN_EN & RESP_EN) /************************************************************************/ /* u_mvl_fopen_ind */ /************************************************************************/ ST_VOID u_mvl_fopen_ind (MVL_IND_PEND *indCtrl) { //FILE *fp; //FOPEN_RESP_INFO resp_info; //struct stat stat_buf; //fp = fopen (indCtrl->u.fopen.filename, "rb"); /* CRITICAL: use "b" flag for binary transfer*/ //if (fp == NULL) // { // _mplas_err_resp (indCtrl,11,6); /* File-access denied */ // return; // } //if (fseek (fp, indCtrl->u.fopen.init_pos, SEEK_SET)) // { // _mplas_err_resp (indCtrl,11,5); /* Position invalid */ // return; // } ///* WARNING: this only works if (FILE *) is a 32-bit pointer. */ //resp_info.frsmid = set_file_pointer(fp); //(ST_INT32) fp; //if (fstat (fileno (fp), &stat_buf)) // { /* Can't get file size or time */ // _mplas_err_resp (indCtrl,11,0); /* File Problem, Other */ // return; // } //else // { // resp_info.ent.fsize = stat_buf.st_size; // resp_info.ent.mtimpres = SD_TRUE; // resp_info.ent.mtime = stat_buf.st_mtime; // } //indCtrl->u.fopen.resp_info = &resp_info; //mplas_fopen_resp (indCtrl); } #endif /* MMS_FOPEN_EN & RESP_EN */ #if (MMS_FREAD_EN & RESP_EN) /************************************************************************/ /* u_mvl_fread_ind */ /************************************************************************/ ST_VOID u_mvl_fread_ind (MVL_IND_PEND *indCtrl) { //FILE *fp; //ST_UCHAR *tmp_buf; //MVLAS_FREAD_CTRL *fread_ctrl = &indCtrl->u.fread; //FREAD_RESP_INFO resp_info; //fp = get_file_pointer(fread_ctrl->req_info->frsmid);// (FILE *) fread_ctrl->req_info->frsmid; ///* Do NOT read more than "max_size". */ //tmp_buf = (ST_UCHAR *) chk_malloc (fread_ctrl->max_size); //resp_info.fd_len = fread (tmp_buf, 1, fread_ctrl->max_size, fp); //if (resp_info.fd_len == 0 && ferror (fp)) // { // _mplas_err_resp (indCtrl, 3, 0); // return; // } //resp_info.filedata = tmp_buf; //if (resp_info.fd_len == fread_ctrl->max_size) // resp_info.more_follows = SD_TRUE; //else // resp_info.more_follows = SD_FALSE; //fread_ctrl->resp_info = &resp_info; //mplas_fread_resp (indCtrl); //chk_free (tmp_buf); /* Temporary buffer */ } #endif /* #if (MMS_FREAD_EN & RESP_EN) */ #if (MMS_FCLOSE_EN & RESP_EN) /************************************************************************/ /* u_mvl_fclose_ind */ /************************************************************************/ ST_VOID u_mvl_fclose_ind (MVL_IND_PEND *indCtrl) { //FILE *fp; //MVLAS_FCLOSE_CTRL *fclose_ctrl = &indCtrl->u.fclose; //fp = get_file_pointer(fclose_ctrl->req_info->frsmid);//(FILE *) fclose_ctrl->req_info->frsmid; //if (fclose (fp)) // _mplas_err_resp (indCtrl, 11, 0); /* File problem, other */ //else // mplas_fclose_resp (indCtrl); } #endif /* #if (MMS_FCLOSE_EN & RESP_EN) */ /************************************************************************/ /* waitReqDone */ /*----------------------------------------------------------------------*/ /* Wait for request to complete. Service communications while waiting. */ /* Check for timeout or Ctrl-C (i.e. doIt=SD_FALSE). */ /* NOTE: if other processing should be done while waiting, add it to */ /* this function. */ /* Parameters: */ /* req request to wait for. */ /* timeout time to wait (seconds). 0 means wait forever. */ /* RETURNS: SD_SUCCESS, MVL_ERR_USR_TIMEOUT or other MVL error code. */ /************************************************************************/ ST_RET waitReqDone (MVL_REQ_PEND *req, ST_INT timeout) { ST_DOUBLE stopTime = sGetMsTime() + (ST_DOUBLE) timeout * 1000.0; while (req->done == SD_FALSE) /* wait until done */ { if (timeout != 0 && sGetMsTime() > stopTime) { req->result = MVL_ERR_USR_TIMEOUT; MVL_LOG_ERR1 ("MMS request (opcode = %d) timed out", req->op); break; } doCommService(); /* wait for events if possible & call mvl_comm_serve*/ } /* end loop */ return (req->result); } void doCommForSecs (ST_INT timeout) { ST_DOUBLE stopTime = sGetMsTime() + (ST_DOUBLE) timeout * 1000.0; while ( sGetMsTime() < stopTime) { doCommService(); /* wait for events if possible & call mvl_comm_serve*/ } } /************************************************************************/ /* named_var_read */ /* Read a single named variable. */ /* scope = VMD_SPEC, DOM_SPEC, or AA_SPEC */ /* CRITICAL: the local variable "parse_info" is written indirectly */ /* from waitReqDone when the response is received. The call */ /* to "waitReqDone" MUST NOT be moved outside this function. */ /************************************************************************/ ST_RET mms_named_var_read (MVL_NET_INFO *net_info, ST_CHAR *varName, ST_INT scope, ST_CHAR *domName, ST_INT type_id, ST_VOID *dataDest, ST_INT timeOut) { ST_INT num_data; ST_CHAR buffer[512]; MVL_READ_RESP_PARSE_INFO parse_info; READ_REQ_INFO *req_info; VARIABLE_LIST *vl; ST_INT ret; MVL_REQ_PEND *reqCtrl; /* Create a read request info struct */ req_info = (READ_REQ_INFO *) buffer; req_info->spec_in_result = SD_FALSE; req_info->va_spec.var_acc_tag = VAR_ACC_VARLIST; req_info->va_spec.num_of_variables = 1; vl = (VARIABLE_LIST *) (req_info + 1); vl->alt_access_pres = SD_FALSE; vl->var_spec.var_spec_tag = VA_SPEC_NAMED; vl->var_spec.vs.name.object_tag = scope; /* set scope */ if (scope == DOM_SPEC) vl->var_spec.vs.name.domain_id = domName; /* set domain name */ vl->var_spec.vs.name.obj_name.vmd_spec = varName; num_data = 1; /* Number of named variables returned */ /* IMPORTANT: start with clean structure, then set appropriate elements.*/ memset (&parse_info, 0, sizeof (parse_info)); parse_info.dest = dataDest; parse_info.type_id = type_id; parse_info.descr_arr = SD_FALSE; /* Send read request. */ ret = mvla_read_variables (net_info,req_info,num_data, &parse_info, &reqCtrl); /* If request sent successfully, wait for reply. */ if (ret == SD_SUCCESS) ret = waitReqDone (reqCtrl, timeOut); mvl_free_req_ctrl (reqCtrl); if (ret != SD_SUCCESS) return (ret); return (parse_info.result); /* Return the single variable result */ } /************************************************************************/ /* mms_named_var_write */ /* Write a single named variable. */ /* scope = VMD_SPEC, DOM_SPEC, or AA_SPEC */ /* CRITICAL: the local variable "wr_info" is written indirectly */ /* from waitReqDone when the response is received. The call */ /* to "waitReqDone" MUST NOT be moved outside this function. */ /************************************************************************/ ST_RET mms_named_var_write (MVL_NET_INFO *netInfo, ST_CHAR *varName, ST_INT scope, ST_CHAR *domName, ST_INT type_id, ST_VOID *dataSrc, ST_INT timeOut) { ST_CHAR buffer[512]; MVL_WRITE_REQ_INFO *wr_info; WRITE_REQ_INFO *req_info; VARIABLE_LIST *vl; ST_RET ret; MVL_REQ_PEND *reqCtrl; req_info = (WRITE_REQ_INFO *) buffer; req_info->num_of_data = 1; req_info->va_spec.var_acc_tag = VAR_ACC_VARLIST; req_info->va_spec.num_of_variables = 1; vl = (VARIABLE_LIST *) (req_info + 1); vl->alt_access_pres = SD_FALSE; vl->var_spec.var_spec_tag = VA_SPEC_NAMED; vl->var_spec.vs.name.object_tag = scope; /* set scope */ if (scope == DOM_SPEC) vl->var_spec.vs.name.domain_id = domName; /* set domain name */ vl->var_spec.vs.name.obj_name.vmd_spec = varName; /* Alloc array of structs. Here only one var so alloc one struct. */ /* To read multiple vars, allocate more. */ /* CRITICAL: response code writes to this struct. Do not free until */ /* response received. */ wr_info = (MVL_WRITE_REQ_INFO*)chk_calloc (1, sizeof (MVL_WRITE_REQ_INFO)); wr_info->local_data = dataSrc; wr_info->type_id = type_id; wr_info->arr = SD_FALSE; /* Send write request. */ ret = mvla_write_variables (netInfo, req_info, 1, wr_info, &reqCtrl); /* If request sent successfully, wait for response. */ if (ret == SD_SUCCESS) ret = waitReqDone (reqCtrl, timeOut); mvl_free_req_ctrl (reqCtrl); if (ret == SD_SUCCESS) /* response received OK. */ ret = wr_info->result; /* return single variable result */ chk_free (wr_info); return (ret); } /************************************************************************/ /* init_log_cfg */ /************************************************************************/ #define HARD_CODED_CFG #ifdef DEBUG_SISCO ST_VOID init_log_cfg (ST_VOID) { static char log_filename[256]; #if defined (HARD_CODED_CFG) /* Use File logging */ sLogCtrl->logCtrl = LOG_FILE_EN; /* Use time/date time log */ sLogCtrl->logCtrl |= (LOG_DIFFTIME_EN | LOG_TIME_EN); /* File Logging Control defaults */ #ifdef _OS_UNIX_ apr_snprintf(log_filename,sizeof(log_filename),"/usr/local/saslog/pt61850netd_pqfe_%d.log",g_node_id); #else apr_snprintf(log_filename,sizeof(log_filename),"../etc/log/pt61850netd_pqfe_%d.log",g_node_id); #endif sLogCtrl->fc.fileName = log_filename; sLogCtrl->fc.maxSize = 50000000L; // 50M sLogCtrl->fc.ctrl = (FIL_CTRL_WIPE_EN | FIL_CTRL_WRAP_EN | // FIL_CTRL_NO_APPEND | FIL_CTRL_MSG_HDR_EN); mms_debug_sel |= MMS_LOG_ERR; mms_debug_sel |= MMS_LOG_NERR; // mms_debug_sel |= MMS_LOG_DEC; // mms_debug_sel |= MMS_LOG_ENC; mvl_debug_sel |= MVLLOG_ERR; mvl_debug_sel |= MVLLOG_NERR; mvl_debug_sel |= MVLLOG_ACSE; #if 0 mvl_debug_sel |= MVLLOG_ACSEDATA; mvl_debug_sel |= MVLLOG_TIMING; #endif acse_debug_sel |= ACSE_LOG_ERR; #if 0 acse_debug_sel |= ACSE_LOG_ENC; acse_debug_sel |= ACSE_LOG_DEC; acse_debug_sel |= COPP_LOG_ERR; acse_debug_sel |= COPP_LOG_DEC; acse_debug_sel |= COPP_LOG_DEC_HEX; acse_debug_sel |= COPP_LOG_ENC; acse_debug_sel |= COPP_LOG_ENC_HEX; acse_debug_sel |= COSP_LOG_ERR; acse_debug_sel |= COSP_LOG_DEC; acse_debug_sel |= COSP_LOG_DEC_HEX; acse_debug_sel |= COSP_LOG_ENC; acse_debug_sel |= COSP_LOG_ENC_HEX; #endif tp4_debug_sel |= TP4_LOG_ERR; #if 0 tp4_debug_sel |= TP4_LOG_FLOWUP; tp4_debug_sel |= TP4_LOG_FLOWDOWN; #endif #if !defined(REDUCED_STACK) clnp_debug_sel |= CLNP_LOG_ERR; clnp_debug_sel |= CLNP_LOG_NERR; #if 0 clnp_debug_sel |= CLNP_LOG_REQ; clnp_debug_sel |= CLNP_LOG_IND; clnp_debug_sel |= CLNP_LOG_ENC_DEC; clnp_debug_sel |= CLNP_LOG_LLC_ENC_DEC; clnp_debug_sel |= CLSNS_LOG_REQ; clnp_debug_sel |= CLSNS_LOG_IND; #endif #endif #else /* !defined (HARD_CODED_CFG) */ #if defined(S_SEC_ENABLED) logCfgAddMaskGroup (&secLogMaskMapCtrl); logCfgAddMaskGroup (&ssleLogMaskMapCtrl); #endif logCfgAddMaskGroup (&mvlLogMaskMapCtrl); logCfgAddMaskGroup (&mmsLogMaskMapCtrl); logCfgAddMaskGroup (&acseLogMaskMapCtrl); logCfgAddMaskGroup (&tp4LogMaskMapCtrl); logCfgAddMaskGroup (&clnpLogMaskMapCtrl); logCfgAddMaskGroup (&asn1LogMaskMapCtrl); logCfgAddMaskGroup (&sxLogMaskMapCtrl); #if defined(S_MT_SUPPORT) logCfgAddMaskGroup (&gsLogMaskMapCtrl); #endif logCfgAddMaskGroup (&sockLogMaskMapCtrl); logCfgAddMaskGroup (&memLogMaskMapCtrl); logCfgAddMaskGroup (&memDebugMapCtrl); if (logcfgx_ex (sLogCtrl, "logcfg.xml", NULL, SD_FALSE, SD_FALSE) != SD_SUCCESS) { printf ("\n Parsing of 'logging' configuration file failed."); if (sLogCtrl->fc.fileName) printf ("\n Check log file '%s'.", sLogCtrl->fc.fileName); exit (5); } #endif /* !defined (HARD_CODED_CFG) */ } #endif /* DEBUG_SISCO */