diff --git a/Esiur.ASPNet/Program.cs b/Esiur.ASPNet/Program.cs index 8801f77..5af07c4 100644 --- a/Esiur.ASPNet/Program.cs +++ b/Esiur.ASPNet/Program.cs @@ -1,48 +1,75 @@ +using Esiur.ASPNet; +using Esiur.Core; +using Esiur.Net.IIP; +using Esiur.Net.Sockets; +using Esiur.Resource; +using Esiur.Stores; +using Microsoft.AspNetCore.Hosting.Server; +using System.Net.WebSockets; +using System.Reflection; +using System.Text; + var builder = WebApplication.CreateBuilder(args); // Add services to the container. -builder.Services.AddControllers(); +//builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle -builder.Services.AddEndpointsApiExplorer(); -builder.Services.AddSwaggerGen(); +//builder.Services.AddEndpointsApiExplorer(); +//builder.Services.AddSwaggerGen(); + +builder.WebHost.UseUrls("http://localhost:8080"); var app = builder.Build(); -// Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) +var webSocketOptions = new WebSocketOptions() { - app.UseSwagger(); - app.UseSwaggerUI(); -} + KeepAliveInterval = TimeSpan.FromSeconds(120), +}; -app.UseHttpsRedirection(); +app.UseWebSockets(webSocketOptions); -app.UseAuthorization(); -app.MapControllers(); +// Configure the HTTP request pipeline. +//if (app.Environment.IsDevelopment()) +//{ + // app.UseSwagger(); +// app.UseSwaggerUI(); +//} -app.UseWebSockets(); +//app.UseHttpsRedirection(); + +//app.UseAuthorization(); + +//app.MapControllers(); + + +await Warehouse.Put("sys", new MemoryStore()); +await Warehouse.Put("sys/service", new MyResource()); +var server = await Warehouse.Put("sys/server", new DistributedServer()); + +await Warehouse.Open(); app.Use(async (context, next) => { - if (context.Request.Path == "/esiur") + var buffer = new ArraySegment(new byte[10240]); + + if (context.WebSockets.IsWebSocketRequest) { - if (context.WebSockets.IsWebSocketRequest) - { - using var webSocket = await context.WebSockets.AcceptWebSocketAsync(); - } - else - { - context.Response.StatusCode = StatusCodes.Status400BadRequest; - } + var webSocket = await context.WebSockets.AcceptWebSocketAsync("iip"); + var socket = new FrameworkWebSocket(webSocket); + var iipConnection = new DistributedConnection(); + server.Add(iipConnection); + iipConnection.Assign(socket); + socket.Begin(); + + while (webSocket.State == WebSocketState.Open) ; } else { await next(context); } - }); -app.Run(); +await app.RunAsync(); diff --git a/Esiur/Net/IIP/DistributedConnection.cs b/Esiur/Net/IIP/DistributedConnection.cs index f913fd1..a51f1ac 100644 --- a/Esiur/Net/IIP/DistributedConnection.cs +++ b/Esiur/Net/IIP/DistributedConnection.cs @@ -1595,7 +1595,7 @@ public partial class DistributedConnection : NetworkConnection, IStore { var os = RuntimeInformation.FrameworkDescription; if (UseWebSocket || RuntimeInformation.OSDescription == "Browser") - socket = new ClientWSocket(); + socket = new FrameworkWebSocket(); else socket = new TCPSocket(); } diff --git a/Esiur/Net/Sockets/ClientWSocket.cs b/Esiur/Net/Sockets/FrameworkWebSocket.cs similarity index 72% rename from Esiur/Net/Sockets/ClientWSocket.cs rename to Esiur/Net/Sockets/FrameworkWebSocket.cs index d23716c..7c17dd8 100644 --- a/Esiur/Net/Sockets/ClientWSocket.cs +++ b/Esiur/Net/Sockets/FrameworkWebSocket.cs @@ -11,13 +11,15 @@ using System.Drawing; using System.Threading; using System.Threading.Tasks; using System.Net.Sockets; +using Microsoft.CodeAnalysis; namespace Esiur.Net.Sockets { - public class ClientWSocket : ISocket + public class FrameworkWebSocket : ISocket { + bool began; - ClientWebSocket sock; + WebSocket sock; NetworkBuffer receiveNetworkBuffer = new NetworkBuffer(); NetworkBuffer sendNetworkBuffer = new NetworkBuffer(); @@ -38,16 +40,34 @@ namespace Esiur.Net.Sockets public IPEndPoint RemoteEndPoint { get; } = new IPEndPoint(IPAddress.Any, 0); - public SocketState State { get; internal set; } = SocketState.Closed; + public SocketState State => sock == null ? SocketState.Closed : sock.State switch + { + WebSocketState.Aborted => SocketState.Closed, + WebSocketState.Closed => SocketState.Closed, + WebSocketState.Connecting => SocketState.Connecting, + WebSocketState.Open => SocketState.Established, + WebSocketState.CloseReceived => SocketState.Closed, + WebSocketState.CloseSent => SocketState.Closed, + WebSocketState.None => SocketState.Initial, + _ => SocketState.Initial + }; public INetworkReceiver Receiver { get; set; } - public ClientWSocket() + public FrameworkWebSocket() { websocketReceiveBufferSegment = new ArraySegment(websocketReceiveBuffer); } + public FrameworkWebSocket(WebSocket webSocket) + { + websocketReceiveBufferSegment = new ArraySegment(websocketReceiveBuffer); + sock = webSocket; + + } + + public void Send(byte[] message) { @@ -88,7 +108,7 @@ namespace Esiur.Net.Sockets public void Close() { - sock.CloseAsync(WebSocketCloseStatus.NormalClosure, "", new System.Threading.CancellationToken()); + sock?.CloseAsync(WebSocketCloseStatus.NormalClosure, "", new System.Threading.CancellationToken()); } public bool Secure { get; set; } @@ -97,23 +117,36 @@ namespace Esiur.Net.Sockets { var url = new Uri($"{(Secure ? "wss" : "ws")}://{hostname}:{port}"); - sock = new ClientWebSocket(); - await sock.ConnectAsync(url, new CancellationToken()); + var ws = new ClientWebSocket(); + sock = ws; - State = SocketState.Established; + await ws.ConnectAsync(url, new CancellationToken()); - sock.ReceiveAsync(websocketReceiveBufferSegment, new CancellationToken()) + + sock.ReceiveAsync(websocketReceiveBufferSegment, CancellationToken.None) .ContinueWith(NetworkReceive); return true; - - } public bool Begin() { + + // Socket destroyed + if (sock == null) + return false; + + if (began) + return false; + + began = true; + + sock.ReceiveAsync(websocketReceiveBufferSegment, CancellationToken.None) + .ContinueWith(NetworkReceive); + return true; + } public bool Trigger(ResourceTrigger trigger) @@ -187,27 +220,27 @@ namespace Esiur.Net.Sockets public AsyncReply BeginAsync() { - return new AsyncReply(true); + return new AsyncReply(Begin()); } private void NetworkReceive(Task task) { - if (sock.State == WebSocketState.Closed) + if (sock.State == WebSocketState.Closed || sock.State == WebSocketState.Aborted) { Receiver?.NetworkClose(this); return; } - + var receivedLength = task.Result.Count; receiveNetworkBuffer.Write(websocketReceiveBuffer, 0, (uint)receivedLength); Receiver?.NetworkReceive(this, receiveNetworkBuffer); - sock.ReceiveAsync(websocketReceiveBufferSegment, new CancellationToken()) + sock.ReceiveAsync(websocketReceiveBufferSegment, CancellationToken.None) .ContinueWith(NetworkReceive); }