示例#1
0
        private async Task HandleAfterSocketAsync
            (WebSocket nativeSocket, MariBaseWebSocketService service, HttpContext context)
        {
            using var socket = new MariWebSocket(nativeSocket, service.Cts.Token, service);
            _logger.LogDebug($"The new WebSocket has the Id: {socket.Id}");

            service.AddClient(socket);

            await service.OnOpenAsync(socket, context)
            .Try(_logger, service, socket, false);

            try
            {
                await ReadAsync(socket, service, context);
            }
            catch (Exception ex)
            {
                if (ex is TaskCanceledException)
                {
                    return;
                }

                await service.OnDisconnectedAsync(socket, WebSocketCloseStatus.ProtocolError, ex.Message)
                .Try(_logger, service, socket, false);

                if (socket.WebSocket.State.Equals(WebSocketState.Open))
                {
                    await socket.WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure,
                                                      "Closed by remote", service.Cts.Token)
                    .Try(_logger, service, socket, false);
                }
            }
            nativeSocket.Dispose();
        }
示例#2
0
        private static async Task HandleExceptionFromTryAsync<T>
            (Exception ex, ILogger<T> logger, MariBaseWebSocketService service, MariWebSocket socket, bool cancel)
        {
            await service.OnErrorAsync(ex, socket);

            if (cancel)
                throw ex;
            else if (logger.HasContent())
                logger.LogError(ex, ex.Message);
        }
示例#3
0
        private async Task ReadAsync
            (MariWebSocket socket, MariBaseWebSocketService service, HttpContext context)
        {
            while (socket.WebSocket.State == WebSocketState.Open)
            {
                var buffer = new byte[service.BufferLength];
                var result = await socket.WebSocket.ReceiveAsync(buffer, service.Cts.Token)
                             .Try(_logger, service, socket);

                if (result.HasNoContent())
                {
                    continue;
                }

                await ReadMessageAsync(result, buffer, service, socket, context);
            }
        }
示例#4
0
        private async Task ReadMessageAsync
            (WebSocketReceiveResult result, byte[] buffer,
            MariBaseWebSocketService service, MariWebSocket socket, HttpContext context)
        {
            if (!result.EndOfMessage)
            {
                return;
            }

            _logger.LogTrace($"Incoming WebSocket message from " +
                             $"{context.Connection.RemoteIpAddress}:{context.Connection.RemotePort}.");
            _logger.LogDebug($"Received WebSocket message from client's id: {socket.Id}");

            if (result.MessageType.Equals(WebSocketMessageType.Text))
            {
                await service.OnMessageAsync(socket, Encoding.UTF8.GetString(buffer))
                .Try(_logger, service, socket, false);
            }
            else if (result.MessageType.Equals(WebSocketMessageType.Close))
            {
                _logger.LogTrace($"Incoming WebSocket disconnect from " +
                                 $"{context.Connection.RemoteIpAddress}:{context.Connection.RemotePort}.");
                _logger.LogDebug($"WebSocket with id {socket.Id} disconnected.");

                await service.OnDisconnectedAsync(
                    socket, result.CloseStatus.Value, Encoding.UTF8.GetString(buffer))
                .Try(_logger, service, socket, false);

                service.RemoveClient(socket);

                await socket.WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure,
                                                  "Closed by remote", service.Cts.Token)
                .Try(_logger, service, socket, false);

                socket.Dispose();
            }
        }
 internal MessageEventArgs(MariWebSocket webSocket, string message)
 {
     WebSocket = webSocket;
     Message   = message;
 }
 /// <summary>
 /// Indicates when a message is received.
 /// </summary>
 /// <param name="socket">The client who sent the message.</param>
 /// <param name="message">The message sent by the client.</param>
 /// <returns></returns>
 internal abstract Task OnMessageAsync(MariWebSocket socket, string message);
 /// <summary>
 /// Indicates when a client disconnected.
 /// </summary>
 /// <param name="socket">The WebSocket client disconnected.</param>
 /// <param name="code">The code reason of the disconnect.</param>
 /// <param name="reason">The description of the close reason.</param>
 /// <returns></returns>
 internal abstract Task OnDisconnectedAsync
     (MariWebSocket socket, WebSocketCloseStatus code, string reason);
 /// <summary>
 /// Indicates when an error occurs.
 /// </summary>
 /// <param name="exception">The Exception throwed.</param>
 /// <param name="socket">The <see cref="MariWebSocket"/> where the error ocurried, can be null.</param>
 /// <returns></returns>
 internal abstract Task OnErrorAsync(Exception exception, MariWebSocket socket);
 /// <summary>
 /// Indicates when a WebSocket connection is successfully opened.
 /// </summary>
 /// <param name="webSocket">The <see cref="MariWebSocket"/> connected.</param>
 /// <param name="context">The context of the new connection.</param>
 /// <returns></returns>
 internal abstract Task OnOpenAsync(MariWebSocket webSocket, HttpContext context);
 /// <summary>
 /// Try get a client with the specific id.
 /// </summary>
 /// <param name="id">The id of the <see cref="MariWebSocket"/>.</param>
 /// <param name="webSocket">The <see cref="MariWebSocket"/> instance.</param>
 /// <returns>A <see cref="bool"/> representing if this client exists or no.</returns>
 protected bool TryGetClient(string id, out MariWebSocket webSocket)
 => Sockets.TryGetValue(id, out webSocket);
 internal void RemoveClient(MariWebSocket socket)
 => RemoveClient(socket.Id);
 internal void AddClient(MariWebSocket socket)
 => Sockets.TryAdd(socket.Id, socket);
 internal DisconnectEventArgs(MariWebSocket webSocket, WebSocketCloseStatus code, string reason)
 {
     WebSocket = webSocket;
     Code      = code;
     Reason    = reason;
 }
 internal ErrorEventArgs(Exception exception, MariWebSocket socket)
 {
     Exception = exception;
     WebSocket = socket;
 }
示例#15
0
 internal OpenEventArgs(MariWebSocket socket, HttpContext context)
 {
     WebSocket = socket;
     Context   = context;
 }
示例#16
0
 /// <summary>
 /// Try await the task and calls
 /// <see cref="MariBaseWebSocketService"/>#OnErroAsync
 /// if a exception throws.
 /// </summary>
 /// <typeparam name="T">The <see cref="ILogger"/> type.</typeparam>
 /// <param name="task">The <see cref="Task"/> that will await.</param>
 /// <param name="logger">The ASP.NET Core <see cref="ILogger"/> for the Middleware.</param>
 /// <param name="service">The Socketservice.</param>
 /// <param name="socket">The <see cref="MariWebSocket"/>.</param>
 /// <param name="cancel">A Boolen indicates if that Method will throw the exception or not.</param>
 /// <returns></returns>
 internal static async Task Try<T>
     (this Task task, ILogger<T> logger, MariBaseWebSocketService service, MariWebSocket socket, bool cancel = true)
 {
     await task
         .TryAsync((ex) => HandleExceptionFromTryAsync(ex, logger, service, socket, cancel));
 }