public async Task <byte[]?> Execute(RpcMethod method, RpcPeerInfo callingPeer) { await Task.Delay(delaysMs[callIndex % delaysMs.Count]); callIndex++; return(new byte[] { 42 }); }
public async Task <byte[]?> Execute(RpcMethod method, RpcPeerInfo callingPeer) { var div = Div.FromMethod(method); byte ret = (byte)(div.dividend / div.divisor); // Yes, may throw div/0 exception return(await Task.FromResult(new byte[] { ret })); }
/// <summary> /// Creates a new channel with the given information, already established connection, /// and optionally the given backlog. /// </summary> public static async Task <RpcChannel> Create(RpcPeerInfo remoteInfo, IRpcConnection connection, IRpcMethodExecutor executor, IRpcBacklog?backlog = null) { var ret = new RpcChannel(remoteInfo, connection, executor); ret.callsQueue = await RpcQueue.Create(remoteInfo.PeerID, backlog); return(ret); }
public override async Task Start() { while (false == stopper.IsCancellationRequested) { ClientWebSocket?webSocket = null; try { webSocket = new ClientWebSocket(); auth.Authenticate(webSocket); await webSocket.ConnectAsync(new Uri(ServerUrl), stopper.Token); Log.Debug($"Connection to server established"); serverInfo = RpcPeerInfo.Server(ServerUrl); var connection = new WebSocketRpcConnection(serverInfo, webSocket); channel = await RpcChannel.Create(serverInfo, connection, this, Settings.Backlog); await channel.Start(); Log.Debug($"Connection to server closed"); } catch (Exception ex) { if ((ex as WebSocketException)?.Message.Contains("401") ?? false) { Log.Debug($"Connection to server denied: Unauthorized"); } else if (ex is WebSocketException wsEx) { Log.Debug($"Connection to server unexpectedly closed: " + wsEx.WebSocketErrorCode); } else { Log.Debug($"Connection to server unexpectedly closed: " + ex.Message); } } finally { webSocket?.Dispose(); } if (false == stopper.IsCancellationRequested) { // Reconnect Log.Info($"Trying to reconnect after {Settings.ReconnectTimeMs} ms"); await Task.Delay(Settings.ReconnectTimeMs); if (Settings.ReconnectTimeMs >= 30_000) // Repeat logging after a long pause { Log.Info($"Trying to reconnect now"); } } } }
protected override RpcContext CreateRpcContext(RpcPeerInfo callingPeer) => RpcContext.OnClient(callingPeer);
private async Task ProcessClient(HttpListenerContext httpContext) { string ip = httpContext.GetIP(); // Check authentication var authResult = auth.Authenticate(httpContext.Request); if (false == authResult.Success || authResult.ClientID == null) { Log.Debug($"Connection from {ip} denied" + (authResult.ClientID != null ? $" (client ID {authResult.ClientID})" : "")); httpContext.Close(HttpStatusCode.Unauthorized); return; } string clientID = authResult.ClientID; // Accept web socket var clientInfo = RpcPeerInfo.Client(clientID, ip); WebSocketContext context; try { context = await httpContext.AcceptWebSocketAsync(subProtocol : null); Log.Debug($"Connected {clientInfo}"); } catch (Exception ex) { Log.Debug($"Could not accept WebSocket to {clientInfo}: {ex.Message}"); httpContext.Close(HttpStatusCode.InternalServerError); return; } // WebSocket loop WebSocket webSocket = context.WebSocket; try { var connection = new WebSocketRpcConnection(clientInfo, webSocket); var channel = await RpcChannel.Create(clientInfo, connection, this, Settings.Backlog); if (channelsByClientID.TryGetValue(clientID, out var oldChannel)) { Log.Debug($"Channel for client {clientID} was already open; close it and open a new one after 3 seconds."); oldChannel.Stop(); await Task.Delay(3000); } channelsByClientID[clientID] = channel; await channel.Start(); Log.Debug($"Connection to {clientInfo} closed"); } catch (Exception ex) { if (ex is WebSocketException wsEx) { Log.Debug($"Connection to {clientInfo} unexpectedly closed: " + wsEx.WebSocketErrorCode); } else { Log.Debug($"Connection to {clientInfo} unexpectedly closed: " + ex.Message); } } finally { webSocket?.Dispose(); } channelsByClientID.Remove(clientID); }
protected override RpcContext CreateRpcContext(RpcPeerInfo callingPeer) => RpcContext.OnServer(callingPeer, channelsByClientID.Values.Select(it => it.RemotePeer).ToList());
public WebSocketRpcConnection(RpcPeerInfo remoteInfo, WebSocket webSocket) { this.remoteInfo = remoteInfo; this.webSocket = webSocket; }
public RpcContext(RpcPeerInfo remotePeer, List <RpcPeerInfo>?clients) { RemotePeer = remotePeer; Clients = clients; }
public static RpcContext OnServer(RpcPeerInfo clientPeer, List <RpcPeerInfo> clients) => new RpcContext(clientPeer, clients);
public static RpcContext OnClient(RpcPeerInfo serverPeer) => new RpcContext(serverPeer, clients: null);
public Task <byte[]?> Execute(RpcMethod method, RpcPeerInfo callingPeer) => Task.FromResult((byte[]?)new byte[] { 42 });
/// <summary> /// Use <see cref="Create"/> for creating new instances. /// </summary> private RpcChannel(RpcPeerInfo remotePeer, IRpcConnection connection, IRpcMethodExecutor executor) { RemotePeer = remotePeer; this.connection = connection; this.executor = executor; }