/* * TCP内部的子站串行发送管理:ASDU调度、I帧交接、完成分派和确认记录;不执行socket I/O。 * * 本头文件供Connection实现使用;下文的调用方指内部协调层,业务只通过TcpServer接入: * - TcpServer_Send_Response经Connection_Submit_Response校验会话,本模块Submit_Response直接准备或入HIGH。 * - NORMAL由TcpServer直接缓存到服务队列;本模块仅在有效会话中准备实际发送时分配协议N(S)。 * - Prepare_Next_Send或Submit_Response取得字节,TcpServer经Net写socket,再经Connection回报写入增量或失败。 * 暂不可写时保留当前帧等待;本模块的Handle接口不代替实际I/O。 * - Connection从Receiver取得完整APDU及APCI,将I/S帧交给Handle_I_S_Frame处理累计ACK。 * - TcpServer经Connection查询回执,成功复制为RECORD事件后移除内部记录;业务用NextEvent取事件副本。 * * Manager是本连接Link和SendBuffer的运行期修改入口,在一次调用内完成成组更新;没有后台自动同步。 * Link维护协议序号,SendBuffer保存当前I帧及控制FIFO,AsduQueue保留原文,Manager保存帧记录和NORMAL来源编号。 * 同连接的这些操作由Connection串行组织;已经交给Manager的事件不得再手动调用底层接口重复提交。 */ #ifndef IEC104_SENDMANAGER_H #define IEC104_SENDMANAGER_H #include "IEC104_AsduQueue.h" #include "IEC104_SendBuffer.h" #ifdef __cplusplus extern "C" { #endif /* 按具体结果分支:Prepare_Next_Send及Submit_Response返回OK才提供可写字节;仅入队返回QUEUED。 * WAIT等正数不表示本次有报文可发送,FRAME_WRITTEN表示完整完成流程已经提交。 */ typedef enum { IEC104_SEND_MANAGER_PROTOCOL_ERROR = -3, /* I/S报文被Link拒绝,须结束连接;与内部交接失败区分 */ IEC104_SEND_MANAGER_FATAL = -2, /* 当前连接必须结束,先回收业务再Abort */ IEC104_SEND_MANAGER_ERROR = -1, /* 参数、代次、frame_id或接入状态非法 */ IEC104_SEND_MANAGER_EMPTY = 0, /* 没有待处理项,具体含义见各接口说明 */ IEC104_SEND_MANAGER_OK = 1, /* 当前操作成功;Prepare可写,Handle_Send_Progress尚未整帧写完 */ IEC104_SEND_MANAGER_QUEUED = 2, /* 控制帧进入FIFO,或Submit_Response已缓存HIGH;尚未发送 */ IEC104_SEND_MANAGER_WAIT = 3, /* 门控/窗口/容量/待完成义务阻塞,不重置期限 */ IEC104_SEND_MANAGER_FRAME_WRITTEN = 4, /* 本地完成处理成功且已释放当前帧缓冲,不能再手动完成同一帧 */ IEC104_SEND_MANAGER_IGNORED = 5, /* 重复STOP或当前没有匹配等待过程的TESTFR_CON,不重启过程 */ } IEC104_SendManagerResult_t; /* * 每个I帧一条存储记录,只保存关联、序号快照及完成事实,不保存完整APDU。 * records数组使用Storage类型,帧身份只存frame_serial;连接代次由所属Manager统一保存。 * local_send_completed由Handle_Send_Progress登记,peer_acknowledged由Handle_I_S_Frame登记; * 必须先提交本地发送完成,再处理覆盖该帧的ACK;两项都成立时才返回就绪回执。 * SendBuffer在本地完成时就释放APDU槽;就绪记录由TcpServer复制为事件后,经Connection调用Remove移除。 * 收尾时剩余记录先复制为closing事件,再由Connection_Close统一清理;不等待业务处理事件。 * 队列HIGH原文在I帧提交及记录建立后即出队;直接应答不入ASDU队列,使用相同HIGH记录。 * NORMAL原文保留到有效ACK或被后续入队覆盖。 * 两级发送记录均独立等待本地完成和有效ACK;HIGH队列清空不撤回已提交I帧。 * 原文存储与回执消费分开;asdu_entry_serial只用于NORMAL确认匹配,HIGH为0;不保存业务user_tag。 * 覆盖不撤回帧、不提前释放k窗口;两级发送完成及回执仍使用独立frame_id。 */ typedef struct { uint64_t frame_serial; /* 本连接内不复用的发送编号;代次取所属Manager */ uint64_t asdu_entry_serial; /* NORMAL条目编号;HIGH固定0,不提供ASDU业务身份 */ uint64_t queued_at_ms; /* 实际准备I帧的时刻,本地发送期限起点 */ uint64_t written_at_ms; /* local_send_completed==1时有效,允许0 */ IEC104_IFrameTx_t i_frame_snapshot; /* 原始N(S)/N(R)/长度快照 */ IEC104_AsduPriority_t asdu_priority; /* 原始优先级 */ uint8_t local_send_completed; /* 0/1:完整写出且Link.Complete成功 */ uint8_t peer_acknowledged; /* 0/1:有效累计ACK覆盖 */ } IEC104_IFrameSendRecordStorage_t; /* 内部查询的独立数值副本:用Manager代次补齐frame_id;TcpServer另转换为公开记录类型。 */ typedef struct { IEC104_SendFrameId_t frame_id; /* 连接代次 + 不复用的发送身份 */ uint64_t asdu_entry_serial; /* NORMAL用于ACK释放;HIGH固定0,按frame_id读取帧回执 */ uint64_t queued_at_ms; /* 实际准备I帧的时刻,本地发送期限起点 */ uint64_t written_at_ms; /* local_send_completed==1时有效,允许0 */ IEC104_IFrameTx_t i_frame_snapshot; /* 原始N(S)/N(R)/长度快照 */ IEC104_AsduPriority_t asdu_priority; /* 原始优先级;HIGH只确认记录,NORMAL另确认原文队列 */ uint8_t local_send_completed; /* 0/1:完整写出且Link.Complete成功 */ uint8_t peer_acknowledged; /* 0/1:有效累计ACK覆盖,非业务执行结果 */ } IEC104_IFrameSendRecord_t; /* 完成结果不含已移出发送FIFO槽的裸指针;TESTFR_ACT完成时可记录等待CON的原始起点。 */ typedef struct { IEC104_SendFrameId_t frame_id; /* 已完成帧的连接代次与帧身份,供接入方关联事件 */ IEC104_SendBufferFrameType_t frame_type; /* 原帧保存的帧类型,不根据完成后的链路状态推断 */ IEC104_LinkResult_t link_completion_result; /* 保留OK/IGNORED,供调用方决定是否启动过程计时 */ IEC104_IFrameTx_t i_frame_snapshot; /* 仅I帧有效 */ uint64_t queued_at_ms; /* 原始入队时刻,部分写入或重试不续期 */ uint64_t written_at_ms; /* 实际整帧写完时刻;主动U帧成功后用于启动等待CON计时 */ } IEC104_LocalSendCompletion_t; /* * 发送管理器由Connection内含,完整布局用于内部静态存储;仅借用下列对象和数组。 * link_state/send_buffer指向本连接实际对象,不复制整份状态。 * 对Link/SendBuffer/AsduQueue的更新通过模块接口完成,Manager直接维护自身控制字段及records数组。 * 字段由接口维护,不提供锁或TCP连接存活判定。 */ typedef struct { IEC104_AsduQueue_t *asdu_queue; /* 仍保留的原文及NORMAL覆盖待确认计数 */ IEC104_SendBuffer_t *send_buffer; /* 唯一当前I帧及独立紧凑S/U FIFO */ IEC104_LinkState_t *link_state; /* 本连接唯一的CONTROLLED链路状态 */ IEC104_IFrameSendRecordStorage_t *records; /* 调用方提供的存储数组,各条不重复保存连接代次 */ uint16_t record_capacity; /* 包括未完成记录和未消费帧回执的总容量 */ uint16_t record_head_index; /* 最早尚未由TcpServer转为事件并移除的记录下标 */ uint16_t record_count; /* ACK已到也不自动减计数,消费回执后才释放 */ uint16_t high_unacked_count; /* 已登记且未ACK的HIGH I帧数,含直接应答及已出队应答 */ uint16_t next_record_ns; /* 下一条新登记I帧记录的N(S),与Link下一分配位置一致 */ uint16_t send_window_k; /* 交给Link检查的未确认I帧窗口上限 */ uint16_t high_priority_burst_limit; /* 0严格高优先;非0限制NORMAL有未提交条目时连续选择HIGH的次数 */ uint16_t high_priority_burst_count; /* 成功交接后更新;Init及从停用状态启动时清零 */ uint64_t connection_generation; /* 本Manager所有记录共用的代次;旧事件不得提交到新连接 */ uint8_t is_initialized; /* 1表示发送管理器已初始化,不表示TCP可用 */ } IEC104_SendManager_t; /* 存储概况,不包含可修改的队列/Link指针;FAILED回收可用,不要求运行中的Link仍合法。 */ typedef struct { uint64_t connection_generation; /* 当前绑定代次,Abort后不再可查询 */ uint16_t record_capacity; /* 调用方提供的记录槽总数 */ uint16_t record_count; /* 尚未消费的全部记录,包含已ACK回执 */ uint16_t high_unacked_count; /* HIGH已交接但尚未被对端ACK的记录数 */ } IEC104_SendManagerStatus_t; /* 读取存储快照,OK写status,ERROR不改输出;不消费记录、不检查跨模块运行一致性。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Get_Status( const IEC104_SendManager_t *manager, IEC104_SendManagerStatus_t *status); /* 当前发送期限的只读计算结果,不保存第二份计时起点。 * 对应has_*为1时remaining_ms有效,0表示已经到期;起点为0也是合法时刻。 * 队首身份与本地期限来自同一次查询,供超时后提交该帧失败;控制容量供连接安排t2/t3唤醒。 */ typedef struct { IEC104_SendFrameId_t head_frame_id; uint32_t local_send_remaining_ms; uint32_t i_ack_remaining_ms; uint8_t has_send_head; uint8_t has_i_ack_deadline; uint8_t control_has_room; } IEC104_SendManagerDeadlines_t; /* OK写完整副本,ERROR不改输出;两项期限均须非零,代次匹配,now_ms不得早于活动起点。 * 只观察已准备队首和最早已写完未ACK记录,不选择ASDU、不编号、不推进发送或关闭连接。 * 部分写入、重复ACK及队首更换不续期;部分ACK后使用下一条记录原有的written_at_ms。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Get_Deadlines( const IEC104_SendManager_t *manager, uint64_t connection_generation, uint64_t now_ms, uint32_t local_send_timeout_ms, uint32_t t1_ms, IEC104_SendManagerDeadlines_t *deadlines); /* * 通过绑定的队列复制ASDU入队,避免上层取出manager内部指针再修改队列。 * HIGH仅在STARTED+IDLE时接手;否则先ERROR,不检查容量、不入队。 * OK成功,WAIT队列空间/条目编号窗口不足,ERROR参数/会话/阶段非法;不生成I帧或分配N(S)。 * NORMAL覆盖和内部条目编号规则同AsduQueue,入队不表示已完成本地发送或收到ACK。 * 受理新STOPDT_ACT时,尚在HIGH中的应答作废;已提交I帧及NORMAL不受该清理影响。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Enqueue( IEC104_SendManager_t *manager, uint64_t connection_generation, IEC104_AsduPriority_t priority, const uint8_t *asdu, uint16_t asdu_length); /* 仅STARTED+IDLE时接手;否则在容量检查前ERROR,不入HIGH。 * 准入后优先尝试直接准备I帧,不执行socket I/O;已有帧/旧HIGH/公平配额/窗口或记录容量阻塞时进入HIGH。 * START受理后即可接手;已有CON时暂存HIGH,不能越过控制FIFO发送。已启用时重复START保留HIGH。 * OK表示SendBuffer及发送记录已接手,仅此时写head_info;QUEUED表示HIGH已复制,WAIT表示尚未接手。 * QUEUED不保证最终发送;受理新STOPDT_ACT时,HIGH待发条目作废且不产生逐条回执。 * 直接应答不经过ASDU队列,也不调用Mark_Submitted;仍按HIGH计入未确认记录,使用相同的完成及ACK路径。 * ERROR表示输入/状态非法或HIGH总容量装不下,FATAL可能已编号,必须收尾;输出和输入不得重叠。 * 调用前Connection须先处理控制义务及期限;OK后应紧接一次有界的非阻塞写入尝试。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Submit_Response( IEC104_SendManager_t *manager, uint64_t connection_generation, const uint8_t *asdu, uint16_t asdu_length, uint64_t now_ms, IEC104_SendBufferHeadInfo_t *head_info); /* 不排队应答:仅在无当前帧、HIGH/NORMAL无待发条目且窗口/记录有容量时准备I帧。 * OK已固定N(S)并复制进SendBuffer;WAIT不接手,不缓存原文,不产生QUEUED。 * 已提交待ACK的NORMAL不阻挡本次尝试,仍受k窗口限制;其余校验同Submit_Response。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Try_Submit_Response( IEC104_SendManager_t *manager, uint64_t connection_generation, const uint8_t *asdu, uint16_t asdu_length, uint64_t now_ms, IEC104_SendBufferHeadInfo_t *head_info); /* * 紧邻实际发送前调用;OK返回当前帧剩余字节,没有当前帧时才选择ASDU并分配N(S)。 * 输入:已Init的manager、匹配代次及当前单调时刻;输出head_info只在OK时有效。 * 当前I帧先续传,否则先发控制FIFO,再按优先级及配额选择未提交ASDU;最多一帧I待本地完成。 * 重复调用只返回同一当前帧,不重复编号;EAGAIN保持身份、内容、进度和原期限。 * EMPTY表示既无已准备帧,也无未提交ASDU;WAIT为门控/k窗口/记录容量阻塞。非OK不写head_info。 * Link构帧成功后的状态提交异常返回FATAL,须结束连接,不能撤回序号后重试。 * APDU提交及记录建立后,HIGH原文出队,NORMAL原文标记已提交;当前APDU与记录独立保留。 * 仅准备成功才推进调度配额;未提交ASDU被覆盖时没有对应帧回执。 * 跨字节环尾部的ASDU通过249字节局部缓冲拼接;连续ASDU直接借用,不malloc。 * now_ms为单调时刻。NORMAL没有未提交条目时,选择HIGH会清零配额计数。 * 先安排当前应生成的S/U,再调用本接口;不执行I/O,不因调用本接口即认定实际已发送。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Prepare_Next_Send( IEC104_SendManager_t *manager, uint64_t connection_generation, uint64_t now_ms, IEC104_SendBufferHeadInfo_t *head_info); /* * S/U入队接口:同连接串行执行会话校验、控制槽预留、Link构帧和FIFO提交。 * 公共参数:manager须已Init且绑定对象持续有效;connection_generation须与当前连接一致; * now_ms为单调毫秒读数,允许0;apci参数须来自Parse_APCI成功的完整报文。 * now_ms是本次入队的单调时刻,不是发送完成时刻;不执行I/O或创建定时器。 * QUEUED表示已提交一帧,后续统一用Handle_Send_Progress/Failure处理发送结果。 * Queue_*返回WAIT表示控制队列满/尚未到期/当前不能生成,无新报文;可稍后重试。 * 外部遗留的未结束预留属于接入状态错误,会在会话校验中返回ERROR。 * 未生成报文时取消本次预留;已使用的frame_serial不复用。 * ERROR表示参数、会话、预留或准备结果非法;构帧成功后提交异常、取消预留异常均为FATAL,须断连。 * FATAL前可能已经改变Link状态,不能假定整次调用未发生,也不能取消预留后重试原会话。 * Handle_*接收接口的WAIT表示本次请求尚未受理:调用方必须有界保留该请求, * 在其被处理前不得越过它分派后续接收帧;不能保留时按过载断连,不得静默丢弃。 * START成功受理即结束此前停止的总计时;新STOP从收到该请求时起计总期限。 * apci不得与本模块存储重叠。NULL、错误帧类型/功能码在入口返回ERROR;已解析I/S报文被Link * 按接收阶段、序号或ACK规则拒绝时返回PROTOCOL_ERROR,内部状态或交接异常返回ERROR/FATAL。 * 所有构帧接口先预留再调用Link,无容量时优先WAIT;EMPTY/无需报文等结果不是独立状态查询。 * 采用这些接口后,不再为同一操作手动Reserve、Link构帧或Commit_Frame。 */ /** * 功能:按w门限、立即确认或子站停止排空规则生成S确认并入队。 * 输入参数:公共参数见上;w范围1..32767;immediate非0跳过数量门限,但不跳过启停/在途S门控。 * 输出参数:无独立输出对象;Link冻结N(R),SendBuffer保存S帧,发送完成后才提交确认位置。 * 返回值:QUEUED表示S已入队;WAIT表示暂不能生成或无需确认;ERROR/FATAL按公共约定处理。 * 调用时机:I帧接收、启动CON发送完成或其他确认条件变化后,由连接调度代码调用。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Queue_S_Ack( IEC104_SendManager_t *manager, uint64_t connection_generation, uint16_t w, int immediate, uint64_t now_ms); /** * 功能:t2到期后按公共S规则准备确认,仍受启停和已有S在途约束。 * 输入参数:公共参数见上;elapsed_ms为原待确认数据起点至今的毫秒数,t2_ms须非0。 * 输出参数:无独立输出对象;成功生成的S进入发送FIFO,不直接执行发送或读取时钟。 * 返回值:QUEUED表示S已入队;WAIT包括未到期、没有可发S或容量不足;ERROR/FATAL按公共约定。 * 说明:elapsed_ms等于t2_ms即到期;等待或重试不续期,接入方负责保存正确的原计时起点。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Queue_T2_Ack( IEC104_SendManager_t *manager, uint64_t connection_generation, uint32_t elapsed_ms, uint32_t t2_ms, uint64_t now_ms); /** * 功能:子站主动生成并排队TESTFR_ACT,不要求当前已经STARTED。 * 输入参数:公共参数见上;本入口不检查空闲时长,按t3触发时使用Queue_T3_Testfr。 * 输出参数:无独立输出对象;Link进入ACT_SEND_PENDING,ACT进入SendBuffer。 * 返回值:QUEUED表示ACT已入队;WAIT表示控制容量不足或已有探测;ERROR/FATAL按公共约定。 * 说明:完整发送后经Handle_Send_Progress才进入CON_PENDING,以实际written_at_ms作为t1起点。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Queue_Testfr_Act( IEC104_SendManager_t *manager, uint64_t connection_generation, uint64_t now_ms); /** * 功能:空闲达到t3后准备TESTFR_ACT,复用同一主动探测状态。 * 输入参数:公共参数见上;idle_elapsed_ms为距有效链路活动的毫秒数,t3_ms须非0。 * 输出参数:无独立输出对象;成功时ACT入队,Link等待本地完整发送。 * 返回值:QUEUED表示ACT已入队;WAIT包括未到期、已有探测或容量不足;ERROR/FATAL按公共约定。 * 说明:等于t3_ms即满足空闲门限;不更新活动时间,不重置已有探测的t1,不创建系统定时器。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Queue_T3_Testfr( IEC104_SendManager_t *manager, uint64_t connection_generation, uint32_t idle_elapsed_ms, uint32_t t3_ms, uint64_t now_ms); /** * 功能:子站接收TESTFR_ACT并排队TESTFR_CON,不结束本端正在进行的主动探测。 * 输入参数:公共参数见上;apci必须是TESTFR_ACT,now_ms为应答入队时刻。 * 输出参数:无独立输出对象;每次QUEUED均生成一帧CON,按同一FIFO完成发送。 * 返回值:QUEUED表示已安排应答;WAIT表示请求尚未受理;ERROR/FATAL按公共约定。 * 说明:WAIT须有界保留请求并保持接收顺序;TESTFR_CON没有Link完成接口,仍用Manager提交发送结果。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Handle_Testfr_Act( IEC104_SendManager_t *manager, uint64_t connection_generation, const IEC104_ApciInfo_t *apci, uint64_t now_ms); /* 按当前主动探测阶段受理TESTFR_CON;不需要发送槽,不生成应答。 * OK表示已结束CON_PENDING,Connection此时才撤销探测t1;提前/无匹配CON返回IGNORED且不缓存。 * ERROR表示参数或会话非法,FATAL表示Link处理异常;调用方不得再直接向Link重复提交。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Handle_Testfr_Con( IEC104_SendManager_t *manager, uint64_t connection_generation, const IEC104_ApciInfo_t *apci); /* * TcpServer取得待发字节并经Net写socket后,由Connection提交本次成功写入增量bytes_written_now。 * OK表示未写完;FRAME_WRITTEN表示已提交适用的链路完成结果并释放缓冲槽,同时写completion。 * TESTFR_CON没有Link.Complete;其完整写入只提交缓冲完成,不推进链路过程。 * bytes_written_now=0不续期;最后一次now_ms为整帧实际发送时刻。错误不写completion。 * 链路Complete或SendBuffer.Commit_Send_Completion异常时返回FATAL。 * 同一写入增量不能重复提交,也不能再手动调用缓冲进度、链路Complete或缓冲完成接口。 * 该函数完成后再分派依赖本地完成的接收事件;不自动处理TESTFR_CON或创建t1定时器。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Handle_Send_Progress( IEC104_SendManager_t *manager, IEC104_SendFrameId_t frame_id, uint16_t bytes_written_now, uint64_t now_ms, IEC104_LocalSendCompletion_t *completion); /* 匹配队首发送失败/发送超时,分派对应Complete(-1),返回FATAL;错frame_id返回ERROR。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Handle_Send_Failure( IEC104_SendManager_t *manager, IEC104_SendFrameId_t frame_id); /* * apci须已通过Parse_APCI;仅接受I/S,Link.Handle验证后登记ACK,HIGH核减未确认记录数,NORMAL清理原文或覆盖计数。 * 内部记录保留到转为事件后显式移除;ACK不代替本地Complete。Link拒绝报文返回PROTOCOL_ERROR; * 接受后的同步或原文释放异常返回FATAL,参数、会话或记录预检非法返回ERROR。 * N(R)只能覆盖已由Handle_Send_Progress提交整帧完成的I帧;ACK越界时不推进确认和接收位置。 * 异步接入须先提交对应发送结果,再按接收顺序分派相关I/S帧,不能用ACK推定写入成功。 * 调用方不能先手动Handle再调用本接口,也不能直接用网络N(R)释放业务记录。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Handle_I_S_Frame( IEC104_SendManager_t *manager, uint64_t connection_generation, const IEC104_ApciInfo_t *apci); /* * 返回最早已本地完成、尚未ACK的I帧记录;OK复制记录,EMPTY/ERROR不改输出。 * 报文槽可能已复用,结果只包含帧身份、序号、时间及NORMAL来源编号,不提供完整APDU或user_tag。 * 只读当前有效会话,不消费回执;仅有排队/部分发送帧时返回EMPTY。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Peek_Oldest_Sent_Unacked_Record( const IEC104_SendManager_t *manager, IEC104_IFrameSendRecord_t *record); /* * 按最早已完成未确认I帧的原始written_at_ms检查t1;无定时器或断连副作用。 * 1到期、0无等待/未到期、-1非法;t1_ms非零,代次须匹配,时钟不得早于起点。 * ACK越过旧记录后选取下一条的原始时刻;重复ACK和后续发送均不续期。 */ extern int IEC104_SendManager_T1_I_Ack_Expired( const IEC104_SendManager_t *manager, uint64_t connection_generation, uint64_t now_ms, uint32_t t1_ms); /* * 返回最早同时满足本地完成和对端ACK的业务记录;无记录EMPTY,尚未就绪WAIT。 * OK只复制记录,不释放;TcpServer成功复制到事件队列后,经Connection调用Remove_Confirmed_Record。 * 确认记录未被消费也占record_capacity,满时Prepare_Next_Send等待;S/U仍可继续发送。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Peek_Confirmed_Record( const IEC104_SendManager_t *manager, IEC104_IFrameSendRecord_t *record); /* TcpServer已成功保存事件副本后,经Connection调用;核对队首frame_id及两个完成标志,返回OK或ERROR。 */ extern IEC104_SendManagerResult_t IEC104_SendManager_Remove_Confirmed_Record( IEC104_SendManager_t *manager, IEC104_SendFrameId_t frame_id); /* * 按交接顺序复制第offset条业务记录,供故障回收;不依赖故障后的链路状态。 * 0<=offset