[fix]修正UdpServer在接收广播时连续启动接收的错误,在StarAgent中,此时可能收到广播包,SocketFlags是Broadcast,需要清空,否则报错“参考的对象类型不支持尝试的操作”; 无需设置SocketOptionName.PacketInformation,在ReceiveMessageFromAsync时会自动设置,并且支持ipv6;
石头 编写于 2024-10-10 00:36:00 石头 提交于 2024-10-10 00:45:43
X
namespace NewLife.Model;

/// <summary>管道。进站顺序,出站逆序</summary>
public interface IPipeline
{
    #region 属性
    #endregion

    #region 基础方法
    /// <summary>添加处理器到末尾</summary>
    /// <param name="handler">处理器</param>
    /// <returns></returns>
    void Add(IHandler handler);
    #endregion

    #region 执行逻辑
    /// <summary>读取数据,返回结果作为下一个处理器消息</summary>
    /// <param name="context">上下文</param>
    /// <param name="message">消息</param>
    Object? Read(IHandlerContext context, Object message);

    /// <summary>写入数据,返回结果作为下一个处理器消息</summary>
    /// <param name="context">上下文</param>
    /// <param name="message">消息</param>
    Object? Write(IHandlerContext context, Object message);

    /// <summary>打开连接</summary>
    /// <param name="context">上下文</param>
    Boolean Open(IHandlerContext context);

    /// <summary>关闭连接</summary>
    /// <param name="context">上下文</param>
    /// <param name="reason">原因</param>
    Boolean Close(IHandlerContext context, String reason);

    /// <summary>发生错误</summary>
    /// <param name="context">上下文</param>
    /// <param name="exception">异常</param>
    Boolean Error(IHandlerContext context, Exception exception);
    #endregion
}

/// <summary>管道。进站顺序,出站逆序</summary>
public class Pipeline : IPipeline
{
    #region 属性
    /// <summary>处理器集合</summary>
    public IList<IHandler> Handlers { get; } = [];
    #endregion

    #region 构造
    #endregion

    #region 方法
    /// <summary>添加处理器到末尾</summary>
    /// <param name="handler">处理器</param>
    /// <returns></returns>
    public virtual void Add(IHandler handler)
    {
        handler.Next = null;
        handler.Prev = null;

        var hs = Handlers;
        if (hs.Count > 0)
        {
            var last = hs[hs.Count - 1];
            last.Next = handler;
            handler.Prev = last;
        }
        Handlers.Add(handler);
    }
    #endregion

    #region 执行逻辑
    /// <summary>读取数据,顺序过滤消息,返回结果作为下一个处理器消息</summary>
    /// <remarks>
    /// 最终处理器决定如何使用消息。
    /// 处理得到单个消息时,调用一次下一级处理器,返回下级结果给上一级;
    /// 处理得到多个消息时,调用多次下一级处理器,返回null给上一级;
    /// </remarks>
    /// <param name="context">上下文</param>
    /// <param name="message">消息</param>
    public virtual Object? Read(IHandlerContext context, Object message) => Handlers.FirstOrDefault()?.Read(context, message);

    /// <summary>写入数据,逆序过滤消息,返回结果作为下一个处理器消息</summary>
    /// <param name="context">上下文</param>
    /// <param name="message">消息</param>
    public virtual Object? Write(IHandlerContext context, Object message) => Handlers.LastOrDefault()?.Write(context, message);

    /// <summary>打开连接</summary>
    /// <param name="context">上下文</param>
    public virtual Boolean Open(IHandlerContext context) => Handlers.FirstOrDefault()?.Open(context) ?? true;

    /// <summary>关闭连接</summary>
    /// <param name="context">上下文</param>
    /// <param name="reason">原因</param>
    public virtual Boolean Close(IHandlerContext context, String reason) => Handlers.FirstOrDefault()?.Close(context, reason) ?? true;

    /// <summary>发生错误</summary>
    /// <param name="context">上下文</param>
    /// <param name="exception">异常</param>
    public virtual Boolean Error(IHandlerContext context, Exception exception) => Handlers.FirstOrDefault()?.Error(context, exception) ?? true;
    #endregion
}