/****************************************************************************/
/* Copyright (c) 2007,许继集团有限公司                                      */
/* All rights reserved.                                                     */
/*                                                                          */
/*  模块描述：                                                              */
/** 请求队列管理模块对外接口声明及数据结构定义。
 *  @file  ac_reqm.h                                                      
 *  @author yh  huiy@xjgc.com												*/
/*                                                                          */
/* 日期         作者    注释                                                */
/* 2007/07/16   YH    创建文件                                              */
/****************************************************************************/

#ifndef IEC61850_AC_REQM_INCLUDED
#define IEC61850_AC_REQM_INCLUDED

#include "ai_def.h"
#include "mms_mp.h"
#include "mvl_defs.h"


#ifdef __cplusplus
extern "C" {
#endif
 	

#define  MAX_FILE_NAME_LENGTH 255
/**  关联服务请求所需信息结构定义*/
typedef struct
{
	SOCKET	sock;		/**< 保存socket句柄，用于超时返回时关闭socket */
	MVL_NET_INFO *net_info;         /**< 关联上以后通道信息结构指针*/
}AC_ASSOC_REQ_CTRL;

/**  读服务请求所需信息结构定义*/
typedef struct 
{
	AI_OBJ_ID  *obj_ids;            /**< 命名变量ID数组*/
	AI_OBJ_TYPE obj_type;         /**<  对象类型*/
    ST_INT num_obj;               /**< 命名变量个数，如果是DS则是DS的数据成员的个数*/

	AI_OBJ_VAL *obj_vals;          /**< 命名变量的值信息结构指针*/
	ST_INT *results;              /**< 结果*/
}AC_READ_REQ_CTRL;

/**  读数据集服务请求所需信息结构定义*/
typedef struct 
{
	AI_OBJ_ID ds_id;                /**< 数据集ID*/
	ST_INT num;                     /**<  数据成员数目 */

	AI_OBJ_VAL *obj_vals;           /**< 每个成员变量的值信息结构指针*/
}AC_GETDSV_REQ_CTRL;

/**  写服务请求所需信息结构定义*/
typedef struct 
{
	AI_OBJ_VAL *obj_vals;           /**< 命名变量的值信息结构指针*/
	ST_INT  num_obj;                /**< 命名变量总数*/

	ST_INT *results;              /**< 结果*/
}AC_WRITE_REQ_CTRL;

/**  获取ied目录服务请求所需信息结构定义*/
typedef struct 
{
	ST_CHAR **names; //ld 名称数组
	ST_INT  num;     //ld个数
}AC_GIEDD_REQ_CTRL;


/**  获取ld目录服务请求所需信息结构定义*/
typedef struct 
{
	ST_CHAR      ld_name[MAX_IDENT_LEN+1];
	AI_OBJ_TYPE  obj_type;    //var 或 nvl
	ST_CHAR      **names;     //var或nvl名称数组
	ST_INT       num;         //var个数
	ST_BOOLEAN   morefollow;
}AC_GLDD_REQ_CTRL;


/**  获取对象结构定义请求所需信息结构定义，可以为ln及ln以下所有类型*/
typedef struct 
{
    AI_OBJ_REF obj_ref;
	ST_CHAR *tdl;
}AC_GOBJDEF_REQ_CTRL;

 
/**  获取ds目录服务请求所需信息结构定义*/
typedef struct 
{
	AI_OBJ_REF ds_ref;
	AI_OBJ_REF *mb_refs;
	ST_INT  mb_num;
	ST_BOOLEAN deletable;
        
}AC_GDSD_REQ_CTRL;


/**  创建数据集服务请求所需信息结构定义*/
typedef struct
{
	AI_OBJ_REF ds_ref;              /**<  数据集名称参引*/
	ST_INT *mb_ids;				    /**< 成员ID数组*/
	OBJECT_NAME ds_name;            /**< 参引*/
	OBJECT_NAME *mb_names;          /**< 成员参引数组*/
	ST_INT num_var;                 /**< 成员总数*/

	ST_INT ds_id;                   /**<  数据集ID */
} AC_CREDS_REQ_CTRL;

/**  删除数据集服务请求所需信息结构定义*/
typedef struct
{
	ST_INT ds_id;                   /**< 数据集ID*/  
} AC_DELDS_REQ_CTRL;

/**  文件服务请求所需信息结构定义*/
typedef struct 
{

	ST_CHAR filename[MAX_FILE_NAME_LENGTH+1];/**< 文件名称*/
	ST_UINT32 filesize;               /**<  文件大小 */
	MMS_UTC_TIME t;                   /**<  文件最后修改时间 */
}AC_FILE_ATTRIBUTE_REQ_CTRL;

/**
 * 读定值请求结构定义     
 */
typedef struct 
{
	AI_OBJ_ID sgcb_id;				/**< sgcb控制块的对象ID */
	ST_INT  group;					/**< 定值组号 */
	ST_BOOLEAN isSe;				/**< SD_TRUE读编辑区定值，SD_FALSE读激活区定值*/
	
	ST_INT  sg_num;					/**< 取回的定值个数 */
	AI_OBJ_VAL *sg_vals;			/**< 取回的定值，数组 */
        ST_INT  counter;                /**< 一次读一个定值时，用于未返回的请求计数 */
}AC_GSGV_REQ_CTRL;

/**
 * 写定值请求结构定义     
 */
typedef struct 
{
	AI_OBJ_ID sgcb_id;				/**< sgcb控制块的对象ID */
	ST_INT  group;					/**< 定值组号 */
	
	ST_INT  sg_num;					/**< 下发的定值个数 */
	AI_OBJ_VAL *sg_vals;			/**< 下发的定值，数组 */
    ST_INT  counter;                /**< 一次读写一个定值时，用于未返回的请求计数 */
	ST_BOOLEAN	write_cnf;			/**< 是否包括写定值确认步骤 */
}AC_SSGV_REQ_CTRL;


typedef struct
{
	ST_INT	frsmid;	/**< 从服务器返回的文件标识，一般是服务器端打开文件得到的文件句柄*/
	FILE	*fp;	/**< 本地打开文件得到的句柄 */
}FILE_READ_IDFP;

/**
 * 读文件请求结构定义
 */
typedef struct
{
	ST_CHAR	src_fname[MAX_FILE_NAME_LENGTH+1];	/**< 源文件名称，远方服务器文件名    */
	ST_CHAR	dest_fname[MAX_FILE_NAME_LENGTH+1];	/**< 目标文件名称，存到本地文件系统中用的名字  */
	FILE_READ_IDFP *hp;
}AC_GETF_REQ_CTRL;

/**
 * 写文件请求结构定义     
 */
typedef struct
{
	ST_CHAR	src_fname[MAX_FILE_NAME_LENGTH+1];	/**< 源文件名称，本地文件的名字    */
	ST_CHAR	dest_fname[MAX_FILE_NAME_LENGTH+1];	/**< 目标文件名称，写到远方服务器时用的名字   */
}AC_SETF_REQ_CTRL;

/**
 * 删除文件     
 */
typedef struct
{
	ST_CHAR	file_name[MAX_FILE_NAME_LENGTH+1];	/**< 要删除的远方服务器中文件的名字 */
}AC_DELF_REQ_CTRL;


/**
 * 文件属性结构定义     
 */
typedef struct
{
	ST_CHAR			file_name[MAX_FILE_NAME_LENGTH+1];	/**< File Name  */
	ST_INT32		file_size;							/**< 文件尺寸 */
	ST_TIMESTAMP	last_modified;						/**< 文件最后修改时间 */
}AC_FILE_ATTR;

/**
 * 读文件属性或某个目录下所有文件属性的请求结构定义    
 */
typedef struct 
{
	ST_CHAR	file_name[MAX_FILE_NAME_LENGTH+1];	/**< 请求的文件的名称或目录的名称*/

	ST_INT  file_num;							/**< 返回的文件个数，如果file_name为文件名，则此值为1 */
	AC_FILE_ATTR *file_attrs;					/**< 返回的文件属性，数组 */
}AC_GETFAV_REQ_CTRL;

/** 控制请求，选择、取消、执行结构中值结构定义 */
typedef struct  /* Values -7-2-17.5.2.2 and -8-1-E4.4 */
{
	union
	{
		ST_BOOLEAN	bVal;   /* SPC or DPC */
		ST_INT32	iVal32; /* INC */
		ST_INT8		iVal8;  /* ISC */
		CODE_ENUM_TDEF cdVal;/* BSC*/
		ST_UINT8    iUVal8;
		struct
		{
			ST_INT32	iVal;   /* for i */
			ST_FLOAT	fVal;   /* for f */
		}setMag; /* APC only one attribute f or i shall be present at a given time for APC*/
	}val;
	
	struct  {
		ST_INT8 orCat;
		ST_OSTRING64 orIdent;
	} origin;
	
	ST_UINT8      ctlNum;
	ST_TIMESTAMP  operTm;
	ST_TIMESTAMP  T;
	ST_CHECK  check;
	ST_BOOLEAN  Test;
} AC_CTRL_VALUE;

/** 控制请求，选择、取消、执行请求结构定义 */
typedef struct 
{
	AI_OBJ_ID  ctrl_obj;
	AC_CTRL_VALUE ctrl_val;

	ST_RET  result;
}AC_CTRL_REQ_CTRL;


/** 按时间读日志 */
typedef struct 
{
	EntryID_TDEF	EntryID;		/**< 条目ID*/
	EntryTime_TDEF  TimeOfEntry;	/**< 条目时间*/
	AI_OBJ_VAL      *obj_vals;		/**< 数据，数组*/
	AI_OBJ_REF      *obj_ref;   	/**< 参引*/     
	ST_INT          obj_num;		/**< 数据个数*/
	ST_RET  result;
}AC_QLOGENTRY_CTRL;

/** 按时间读日志 */
typedef struct 
{
	AI_OBJ_ID  dom_id;				/**< LDID */
	EntryTime_TDEF start_time;      /**< 起始时间 */
	EntryTime_TDEF stop_time;       /**< 终止时间 */
	EntryID_TDEF   startEntryID;	/**< 起始条目ID*/

	ST_INT          entry_num;		/**< 条目个数*/
    AC_QLOGENTRY_CTRL *entry_info;  /**< 条目信息*/
	ST_RET  result;
}AC_QLOG_CTRL;

/**
  * ENABLE报告请求信息结构
*/
typedef struct
{
	AI_OBJ_ID rcb_id;              /**<  报告ID*/ 
	ST_INT OptFlds;            /**<  OptFlds值*/ 
	ST_INT TrgOps;              /**<  TrgOps值*/
	ST_INT IntgPd;                 /**<  IntgPd值*/
	ST_BOOLEAN rptEna;
	ST_VOID * attr_info;
}AC_ENAREPORT_CTRL;

/**  请求所需信息结构定义*/
typedef struct ac_req_ctrl
{
	DBL_LNK l;
    ST_INT  srv_id;                   /**< 服务器ID	*/
	IEC61850_OP  op;                  /**< 请求服务类型*/
	union{
		AC_ASSOC_REQ_CTRL assoCtrl;			/**< associate */
		AC_READ_REQ_CTRL  rdCtrl;			/**< read */
		AC_WRITE_REQ_CTRL wrCtrl;			/**< write */
		AC_GIEDD_REQ_CTRL gieddCtrl;		/**< get server directory */
		AC_GLDD_REQ_CTRL  glddCtrl;			/**< get ld directory */
		AC_GOBJDEF_REQ_CTRL  gobjdefCtrl;	/**< get obj definition */
		AC_GDSD_REQ_CTRL  gdsdCtrl;			/**< get dataSet directory */
		AC_CREDS_REQ_CTRL credsCtrl;		/**< create dataSet */
		AC_DELDS_REQ_CTRL deldsCtrl;		/**< delete dataSet */
		AC_GETDSV_REQ_CTRL getdsvCtrl;		/**< get dataSet value */
		AC_GSGV_REQ_CTRL  getsgvCtrl;		/**< get sg value */
		AC_SSGV_REQ_CTRL  setsgvCtrl;		/**< set sg value */
		AC_CTRL_REQ_CTRL  ctrlCtrl;			/**< select selectWithVal cancel oper */
		AC_GETF_REQ_CTRL  getfCtrl;			/**< get file */
		AC_SETF_REQ_CTRL  setfCtrl;			/**< set file */
		AC_DELF_REQ_CTRL  delfCtrl;			/**< delete file */
		AC_GETFAV_REQ_CTRL getfavCtrl;		/**< get file attribute value */
		AC_QLOG_CTRL      qlogCtrl; 	        	/**< querylogbytime */
		AC_ENAREPORT_CTRL enaRptCtrl;       /**< 报告击活*/
	}u;                                /**< 不同请求服务结构联合体*/
	ST_RET  result;                    /**< 服务最终结果，成功或者错误码*/
	ST_DOUBLE timeout;					/**<  请求超时时间*/

	/**< 回调给应用层的回调指针*/
	ST_VOID  (*u_ac_req_done)(struct ac_req_ctrl *req_ctrl);
	ST_VOID *sg_info;
	ST_VOID *user_info;
	//new
	AC_CHANNEL chnl;      //A、B网标志
}AC_REQ_CTRL;

/** 服务请求返回给应用层回调函数指针*/
typedef ST_VOID (*U_AC_REQ_DONE)(AC_REQ_CTRL *req_ctrl); 

/**
 * 构造一个请求实例并将结构成员。
 * 服务类型标志赋值、请求超时时间赋值、前一个后一个节点指针赋值
 * @param  op          服务类型标志，目前定义的值为0~20
 * @param  srv_id      服务器ID
 * @param  time_out    服务超时时间
 * @param  u_req_done  服务回调指针
 * @return AC_REQ_CTRL *为请求结构内存头指针，失败返回NULL
 */
AC_REQ_CTRL *ac_create_reqCtrl(IEC61850_OP op, ST_INT srv_id, ST_INT time_out, U_AC_REQ_DONE u_req_done);
/**
 * 销毁一个请求实例
 * 根据服务类型释放调用不同服务接口函数释放其成员的资源，最后释放其自身的资源
 * @param  reqCtrl   请求结构指针
 * @return ST_VOID
 */
ST_VOID ac_destroy_reqCtrl(AC_REQ_CTRL *reqCtrl);

/**
 * 销毁一个请求实例,先将请求从请求队列中解列，再释放。
 * 根据服务类型释放调用不同服务接口函数释放其成员的资源，最后释放其自身的资源
 * @param  reqCtrl   请求结构指针
 * @return ST_VOID
 */
ST_VOID ac_cancel_reqCtrl(AC_REQ_CTRL *reqCtrl);

/**
 * 根据服务类型不同调用不同的发送函数发送一个请求
 * @param  reqCtrl      请求结构指针
 * @retval SD_FAILURE   失败  
 * @retval SD_SUCCESS   成功  
 */
ST_RET  ac_send_req(AC_REQ_CTRL *reqCtrl);

/**
 * 清空一个站点的待发送请求队列。
 * 包括解列和释放
 * @param  srv_id      站点ID
 * @return ST_VOID
 */
ST_VOID ac_cleanup_acReqList(ST_INT srv_id);

/**
 * 检测已发送请求队列每个请求超时，并处理
 * @param  net_info      网络通道指针
 * @return ST_VOID
 */
ST_VOID ac_mvlReqList_handle(MVL_NET_INFO *net_info);

/**
 * 检测待发送队列中每个请求超时，并处理； 是否允许发送，允许则发送
 * @param  srv_id 
 * @return ST_VOID
 */
ST_VOID ac_acReqList_handle(ST_INT srv_id);

/**
 * 释放MVL_REQ_PEND结构
 * @param  reqPend   已发送的请求结构指针
 * @return ST_VOID
 */
ST_VOID ac_destroy_mvlReqPend(MVL_REQ_PEND  *reqPend);

/**
 * 检测待发送请求是否超时
 * @param  reqCtrl   请求结构指针
 * @retval SD_TRUE   超时
 * @retval SD_FALSE  未超时
 */
ST_BOOLEAN ac_req_timeout(AC_REQ_CTRL *reqCtrl);

/**
 * 通过站点的ID向请求链表加入一个请求结构
 * @param   srv_id          服务器ID
 * @param   req_ctrl        要加入的请求结构
 * @retval  SD_SUCCESS 成功 SD_FAILURE 失败
 */
ST_RET ac_add_req_last(ST_INT srv_id, AC_REQ_CTRL *req_ctrl);

/**
 * 通过站点的ID获得取得请求链表中第一个请求结构
 * @param   srv_id          服务器ID
 * @retval  AC_REQ_CTRL 取得请求链表中第一个请求结构，失败或为空返回NULL
 */
AC_REQ_CTRL * ac_get_req_first(ST_INT srv_id);

/**
 * 通过站点的ID获得取得请求链表中req_ctrl后一个请求结构
 * @param   srv_id          服务器ID
 * @param   req_ctrl        要加入的请求结构
 * @retval  AC_REQ_CTRL 取得的请求结构，失败或为空返回NULL
 */
AC_REQ_CTRL * ac_get_req_next(ST_INT srv_id, AC_REQ_CTRL *req_ctrl);

/**
 * 从请求链表里解裂一个请求机构
 * @param   srv_id          服务器ID
 * @param   req_ctrl        要解裂的请求结构
 */
ST_VOID ac_unlink_req(ST_INT srv_id, AC_REQ_CTRL *req_ctrl);
 
/** 
 * 请求处理结束，调用用户回调
 * @param req_ctrl 请求结构
 * @param ret 请求处理结果
 */
ST_VOID ac_req_done(AC_REQ_CTRL *req_ctrl, ST_RET ret);

#ifdef __cplusplus
}
#endif


#endif /**<  IEC61850_AC_REQM_INCLUDE */









