2025-01-16 16:17:01 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @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 <ctype.h> //lnk20241119
|
2025-03-04 17:29:04 +08:00
|
|
|
|
#include "../cfg_parse/custom_printf.h"//lnk20250225
|
2025-01-16 16:17:01 +08:00
|
|
|
|
extern uint32_t g_node_id;
|
|
|
|
|
|
extern char subdir[128];
|
|
|
|
|
|
unsigned int g_no_auth = 0;
|
2025-05-09 16:53:07 +08:00
|
|
|
|
DEV_TYPE_LIST gDev_rcb_list; //全局报告控制块链表
|
2025-01-16 16:17:01 +08:00
|
|
|
|
#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)
|
2025-05-09 16:53:07 +08:00
|
|
|
|
{//只返回 rt_ctrl.rt_num 中第一个数据的类型和 长度
|
2025-01-16 16:17:01 +08:00
|
|
|
|
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);
|
|
|
|
|
|
|
2025-05-09 16:53:07 +08:00
|
|
|
|
memset(&gDev_rcb_list, 0, sizeof(DEV_TYPE_LIST)); //WW 2023-08-29 全局装置报告指针初始化
|
2025-01-16 16:17:01 +08:00
|
|
|
|
|
|
|
|
|
|
// 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;
|
2025-05-09 16:53:07 +08:00
|
|
|
|
mvlCfg.max_msg_size = 320000; //to enlage to fit the 主设备保护
|
2025-01-16 16:17:01 +08:00
|
|
|
|
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
|
|
|
|
|
|
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//用于发送文件目录请求,获取远程设备的文件列表,并返回符合条件的文件名。
|
2025-01-16 16:17:01 +08:00
|
|
|
|
#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");
|
|
|
|
|
|
//}
|
2025-05-09 16:53:07 +08:00
|
|
|
|
printf("★");//
|
2025-01-16 16:17:01 +08:00
|
|
|
|
//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)
|
|
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//先注销报告先
|
2025-01-16 16:17:01 +08:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//WW 2023-08-29 增加设备类型处理,优化报告触发速度
|
2025-01-16 16:17:01 +08:00
|
|
|
|
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 */
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//一、装置类型查找判断---------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
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)) //①遍历 全局装置报告控制块链表
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//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)) //匹配 装置类型
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
bFindDevType = 1; //查找到装置类型
|
|
|
|
|
|
//LOG_INFO("(报告触发)匹配到装置类型,dev_type_name= %s", dev_rcb->dev_type_name); //仅调试使用! zl 2019-12-24 00:23:55
|
2025-01-16 16:17:01 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-05-09 16:53:07 +08:00
|
|
|
|
} //遍历 装置类型链表 结束
|
|
|
|
|
|
if (!bFindDevType) //未查找到装置类型
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
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); //添加 全局装置报告控制块链表
|
2025-01-16 16:17:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//二、装置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、端口链表
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//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 && 端口号
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
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
|
2025-01-16 16:17:01 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-05-09 16:53:07 +08:00
|
|
|
|
}//遍历 装置IP、端口链表 结束
|
|
|
|
|
|
if (!bFindIpPort) //未查找到装置IP、端口
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
dev_info = (Dev_IP_Port_INFO *)chk_calloc(1, sizeof(Dev_IP_Port_INFO)); //调用 申请连续内存空间,并初始化为0,返回首地址指针,相当于New
|
2025-01-16 16:17:01 +08:00
|
|
|
|
|
2025-05-09 16:53:07 +08:00
|
|
|
|
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、端口链表
|
2025-01-16 16:17:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//三、装置报告控制块查找判断----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
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)) //③遍历 全局装置报告控制块链表->报告控制块信息链表
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//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)) //匹配 装置报告控制块
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
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
|
2025-01-16 16:17:01 +08:00
|
|
|
|
break; /* rcb_info now points to right structure */
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-05-09 16:53:07 +08:00
|
|
|
|
if (!bFindRCB) //未查找到装置报告控制块
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
rcb_info = rcb_info_create(clientNetInfo, dom_name, rcb_name, rpt_typeids, timeOut); //调用 创建装置报告控制块 —>> 注:该函数较为耗时,若本装置类型的报告控制块已创建过,则不需再进行创建!
|
2025-01-16 16:17:01 +08:00
|
|
|
|
if (rcb_info == NULL) {
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//LOG_INFO("(报告触发)创建报告控制块失败!dev_type_name= %s, dom= %s,rcb= %s", dev_rcb->dev_type_name, dom, rpt); //仅调试使用! zl 2019-3-13 14:24:43
|
2025-01-16 16:17:01 +08:00
|
|
|
|
return SD_FAILURE;
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//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); //添加 全局报告控制块链表->报告控制块信息链表
|
2025-01-16 16:17:01 +08:00
|
|
|
|
}
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//TRACE("(报告触发)创建报告控制块!dom= %s rcb= %s,耗时:%0.6f,报告大小:%d", dom, rpt, dwEnd - dwStart, sizeof(RCB_INFO));
|
2025-01-16 16:17:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (rcb_info)
|
|
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//先注销报告先 WW 2023-08-29注释先注销报告的代码
|
2025-01-16 16:17:01 +08:00
|
|
|
|
//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];
|
2025-05-09 16:53:07 +08:00
|
|
|
|
ST_RET ret; //函数执行返回值
|
2025-01-16 16:17:01 +08:00
|
|
|
|
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//一、装置类型查找判断---------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
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)) //①遍历 全局装置报告控制块链表
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//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)) //匹配 装置类型
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
bFindDevType = 1; //查找到装置类型
|
|
|
|
|
|
//LOG_INFO("(报告停止)匹配到装置类型,dev_type_name= %s", dev_rcb->dev_type_name); //仅调试使用! zl 2019-12-24 00:23:55
|
2025-01-16 16:17:01 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-05-09 16:53:07 +08:00
|
|
|
|
} //遍历 装置类型链表 结束
|
2025-01-16 16:17:01 +08:00
|
|
|
|
|
2025-05-09 16:53:07 +08:00
|
|
|
|
if (!bFindDevType) //未查找到装置类型
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
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); //添加 全局装置报告控制块链表
|
2025-01-16 16:17:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//二、装置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、端口链表
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//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 && 端口号
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
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
|
2025-01-16 16:17:01 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-05-09 16:53:07 +08:00
|
|
|
|
} //遍历 装置IP、端口链表 结束
|
|
|
|
|
|
if (!bFindIpPort) //未查找到装置IP、端口
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
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、端口链表
|
2025-01-16 16:17:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//三、装置报告控制块查找判断----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
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)) //③遍历 全局装置报告控制块链表->报告控制块信息链表
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//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)) //匹配 装置报告控制块
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
bFindRCB = 1; //查找到装置报告控制块
|
|
|
|
|
|
//LOG_INFO("(报告停止)匹配到报告控制块dom= %s,rcb= %s,已触发过!", dom, rpt); //仅调试使用! zl 2019-3-13 14:24:43
|
2025-01-16 16:17:01 +08:00
|
|
|
|
break; /* rcb_info now points to right structure */
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-05-09 16:53:07 +08:00
|
|
|
|
if (!bFindRCB) //未查找到装置报告控制块
|
2025-01-16 16:17:01 +08:00
|
|
|
|
{
|
2025-05-09 16:53:07 +08:00
|
|
|
|
rcb_info = rcb_info_create(clientNetInfo, dom_name, rcb_name, rpt_typeids, timeOut); //调用 创建装置报告控制块 —>> 注:该函数较为耗时,若本装置类型的报告控制块已创建过,则不需再进行创建!
|
2025-01-16 16:17:01 +08:00
|
|
|
|
if (rcb_info == NULL) {
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//LOG_INFO("(报告停止)创建报告控制块失败!dom= %s,rcb= %s", dom, rpt); //仅调试使用! zl 2019-3-13 14:24:43
|
2025-01-16 16:17:01 +08:00
|
|
|
|
return SD_FAILURE;
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//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); //添加 全局报告控制块链表->报告控制块信息链表
|
2025-01-16 16:17:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-09 16:53:07 +08:00
|
|
|
|
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); //调用 写入装置报告控制块(报告停止)
|
2025-01-16 16:17:01 +08:00
|
|
|
|
|
|
|
|
|
|
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 */
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
|
2025-05-09 16:53:07 +08:00
|
|
|
|
// 检查字符串是否为空、仅空格或不可见字符lnk20241119
|
2025-01-16 16:17:01 +08:00
|
|
|
|
int is_empty_or_whitespace(const char* str) {
|
|
|
|
|
|
if (str == NULL) {
|
2025-05-09 16:53:07 +08:00
|
|
|
|
return 1; // NULL 情况,视为"空"
|
2025-01-16 16:17:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
while (*str) {
|
|
|
|
|
|
if (!isspace((unsigned char)*str)) {
|
2025-05-09 16:53:07 +08:00
|
|
|
|
return 0; // 有非空格字符,非"空"
|
2025-01-16 16:17:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
str++;
|
|
|
|
|
|
}
|
2025-05-09 16:53:07 +08:00
|
|
|
|
return 1; // 全是空格或不可见字符,视为"空"
|
2025-01-16 16:17:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
|
|
2025-05-09 16:53:07 +08:00
|
|
|
|
//lnk20241119添加判断和打印,确保识别码秘钥为空时不调用加密
|
2025-01-16 16:17:01 +08:00
|
|
|
|
if (!is_empty_or_whitespace(dev_series) || !is_empty_or_whitespace(dev_key)) {
|
2025-03-04 17:29:04 +08:00
|
|
|
|
printf("dev_series= %s,dev_key= %s\n", dev_series,dev_key);
|
2025-01-16 16:17:01 +08:00
|
|
|
|
/* 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 <<endl
|
|
|
|
|
|
//strcpy (authInfo->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 */
|
|
|
|
|
|
|