private void OnClientConnected(Tcp con, IPEndPoint endpointConfig, Loop loop) { try { var remoteEndPoint = con.GetPeerEndPoint(); // get rid of banned clients as early as possible if (banManager?.IsBanned(remoteEndPoint.Address) == true) { logger.Debug(() => $"[{LogCat}] Disconnecting banned ip {remoteEndPoint.Address}"); con.Dispose(); return; } var connectionId = CorrelationIdGenerator.GetNextId(); logger.Debug(() => $"[{LogCat}] Accepting connection [{connectionId}] from {remoteEndPoint.Address}:{remoteEndPoint.Port}"); // setup client connection con.KeepAlive(true, 1); // setup client var client = new StratumClient(); client.Init(loop, con, ctx, clock, endpointConfig, connectionId, data => OnReceive(client, data), () => OnReceiveComplete(client), ex => OnReceiveError(client, ex)); // register client lock (clients) { clients[connectionId] = client; } OnConnect(client); } catch (Exception ex) { logger.Error(ex, () => nameof(OnClientConnected)); } }
private void OnClientConnected(Tcp con, IPEndPoint endpointConfig, Loop loop) { try { var remoteEndPoint = con.GetPeerEndPoint(); // get rid of banned clients as early as possible if (banManager?.IsBanned(remoteEndPoint.Address) == true) { logger.Debug(() => $"[{LogCat}] Disconnecting banned ip {remoteEndPoint.Address}"); con.Dispose(); return; } var connectionId = CorrelationIdGenerator.GetNextId(); logger.Debug(() => $"[{LogCat}] Accepting connection [{connectionId}] from {remoteEndPoint.Address}:{remoteEndPoint.Port}"); // setup client var client = new StratumClient <TClientContext>(); client.Init(loop, con, ctx, endpointConfig, connectionId); // request subscription var sub = client.Received .Select(data => Observable.FromAsync(() => Task.Run(() => // get off of LibUV event-loop-thread immediately { // boot pre-connected clients if (banManager?.IsBanned(client.RemoteEndpoint.Address) == true) { logger.Info(() => $"[{LogCat}] [{connectionId}] Disconnecting banned client @ {remoteEndPoint.Address}"); DisconnectClient(client); data.Dispose(); return(Unit.Default); } logger.Trace(() => $"[{LogCat}] [{client.ConnectionId}] Received request data: {StratumClient<TClientContext>.Encoding.GetString(data.Array, 0, data.Size)}"); // parse request var request = ParseRequest(data); logger.Debug(() => $"[{LogCat}] [{client.ConnectionId}] Dispatching request '{request.Method}' [{request.Id}]"); try { // dispatch request OnRequestAsync(client, new Timestamped <JsonRpcRequest>(request, clock.UtcNow)).Wait(); } catch (Exception ex) { logger.Error(ex, () => $"[{LogCat}] [{client.ConnectionId}] Error processing request {request.Method} [{request.Id}]"); } return(Unit.Default); }))) .Concat() .Subscribe(_ => { }, ex => OnReceiveError(client, ex), () => OnReceiveComplete(client)); // ensure subscription is disposed on loop thread var disposer = loop.CreateAsync((handle) => { sub.Dispose(); handle.Dispose(); }); client.Subscription = Disposable.Create(() => { disposer.Send(); }); // register client lock (clients) { clients[connectionId] = client; } OnConnect(client); } catch (Exception ex) { logger.Error(ex, () => nameof(OnClientConnected)); } }
private void OnClientConnected(Tcp con, IPEndPoint endpointConfig, Loop loop) { try { var remoteEndPoint = con.GetPeerEndPoint(); // get rid of banned clients as early as possible if (banManager?.IsBanned(remoteEndPoint.Address) == true) { logger.Trace(() => $"[{LogCat}] Disconnecting banned ip {remoteEndPoint.Address}"); con.Dispose(); return; } var connectionId = CorrelationIdGenerator.GetNextId(); logger.Trace(() => $"[{LogCat}] Accepting connection [{connectionId}] from {remoteEndPoint.Address}:{remoteEndPoint.Port}"); // setup client var client = new StratumClient <TClientContext>(); client.Init(con, ctx, endpointConfig, connectionId); // request subscription var sub = client.Requests .ObserveOn(TaskPoolScheduler.Default) // WARN: never add .SubscribeOn here (must sub/unsub on UV event-loop thread) .Subscribe(async tsRequest => { var request = tsRequest.Value; logger.Debug(() => $"[{LogCat}] [{client.ConnectionId}] Received request {request.Method} [{request.Id}]"); try { // boot pre-connected clients if (banManager?.IsBanned(client.RemoteEndpoint.Address) == true) { logger.Trace(() => $"[{LogCat}] [{connectionId}] Disconnecting banned client @ {remoteEndPoint.Address}"); DisconnectClient(client); return; } await OnRequestAsync(client, tsRequest); } catch (Exception ex) { logger.Error(ex, () => $"Error handling request: {request.Method}"); } }, ex => OnReceiveError(client, ex), () => OnReceiveComplete(client)); // ensure subscription is disposed on loop thread var disposer = loop.CreateAsync((handle) => { sub.Dispose(); handle.Dispose(); }); client.Subscription = Disposable.Create(() => { disposer.Send(); }); // register client lock (clients) { clients[connectionId] = client; } OnConnect(client); } catch (Exception ex) { logger.Error(ex, () => nameof(OnClientConnected)); } }
private void OnClientConnected(Tcp con, IPEndPoint endpointConfig, Loop loop) { try { var remoteEndPoint = con.GetPeerEndPoint(); // get rid of banned clients as early as possible if (banManager?.IsBanned(remoteEndPoint.Address) == true) { logger.Debug(() => $"[{LogCat}] Disconnecting banned ip {remoteEndPoint.Address}"); con.Dispose(); return; } var connectionId = CorrelationIdGenerator.GetNextId(); logger.Debug(() => $"[{LogCat}] Accepting connection [{connectionId}] from {remoteEndPoint.Address}:{remoteEndPoint.Port}"); // setup client var client = new StratumClient <TClientContext>(); client.Init(loop, con, ctx, endpointConfig, connectionId); var sub = client.Received.Subscribe(data => { // get off of LibUV event-loop-thread immediately Task.Run(() => { using (data) { JsonRpcRequest request = null; try { // boot pre-connected clients if (banManager?.IsBanned(client.RemoteEndpoint.Address) == true) { logger.Info(() => $"[{LogCat}] [{connectionId}] Disconnecting banned client @ {remoteEndPoint.Address}"); DisconnectClient(client); return; } // de-serialize logger.Trace(() => $"[{LogCat}] [{client.ConnectionId}] Received request data: {StratumClient<TClientContext>.Encoding.GetString(data.Array, 0, data.Size)}"); request = DeserializeRequest(data); if (request != null) { // dispatch logger.Debug(() => $"[{LogCat}] [{client.ConnectionId}] Dispatching request '{request.Method}' [{request.Id}]"); OnRequestAsync(client, new Timestamped <JsonRpcRequest>(request, clock.UtcNow)).Wait(); } else { logger.Trace(() => $"[{LogCat}] [{client.ConnectionId}] Unable to deserialize request"); } } catch (JsonReaderException jsonEx) { // junk received (no valid json) logger.Error(() => $"[{LogCat}] [{client.ConnectionId}] Connection json error state: {jsonEx.Message}"); if (clusterConfig.Banning?.BanOnJunkReceive.HasValue == false || clusterConfig.Banning?.BanOnJunkReceive == true) { logger.Info(() => $"[{LogCat}] [{client.ConnectionId}] Banning client for sending junk"); banManager?.Ban(client.RemoteEndpoint.Address, TimeSpan.FromMinutes(30)); } } catch (Exception ex) { if (request != null) { logger.Error(ex, () => $"[{LogCat}] [{client.ConnectionId}] Error processing request {request.Method} [{request.Id}]"); } } } }); }, ex => OnReceiveError(client, ex), () => OnReceiveComplete(client)); // ensure subscription is disposed on loop thread var disposer = loop.CreateAsync((handle) => { sub.Dispose(); handle.Dispose(); }); client.Subscription = Disposable.Create(() => { disposer.Send(); }); // register client lock (clients) { clients[connectionId] = client; } OnConnect(client); } catch (Exception ex) { logger.Error(ex, () => nameof(OnClientConnected)); } }
private void OnClientConnected(Tcp con, IPEndPoint endpointConfig, Loop loop) { try { var remoteEndPoint = con.GetPeerEndPoint(); // get rid of banned clients as early as possible if (banManager?.IsBanned(remoteEndPoint.Address) == true) { logger.Trace(() => $"[{LogCat}] Disconnecting banned ip {remoteEndPoint.Address}"); con.Dispose(); return; } var connectionId = CorrelationIdGenerator.GetNextId(); logger.Trace(() => $"[{LogCat}] Accepting connection [{connectionId}] from {remoteEndPoint.Address}:{remoteEndPoint.Port}"); // setup client var client = new StratumClient <TClientContext>(); client.Init(loop, con, ctx, endpointConfig, connectionId); // request subscription var sub = client.Requests .Do(x => logger.Trace(() => $"[{LogCat}] [{client.ConnectionId}] Received request {x.Value.Method} [{x.Value.Id}]")) .Select(tsRequest => Observable.FromAsync(() => Task.Run(() => // get off of LibUV event-loop-thread immediately { var request = tsRequest.Value; logger.Trace(() => $"[{LogCat}] [{client.ConnectionId}] Dispatching request {request.Method} [{request.Id}]"); try { // boot pre-connected clients if (banManager?.IsBanned(client.RemoteEndpoint.Address) == true) { logger.Trace(() => $"[{LogCat}] [{connectionId}] Disconnecting banned client @ {remoteEndPoint.Address}"); DisconnectClient(client); return; } OnRequestAsync(client, tsRequest).Wait(); } catch (Exception ex) { logger.Error(ex, () => $"Error handling request: {request.Method}"); } }))) .Concat() .Subscribe(_ => { }, ex => OnReceiveError(client, ex), () => OnReceiveComplete(client)); // ensure subscription is disposed on loop thread var disposer = loop.CreateAsync((handle) => { sub.Dispose(); handle.Dispose(); }); client.Subscription = Disposable.Create(() => { disposer.Send(); }); // register client lock (clients) { clients[connectionId] = client; } OnConnect(client); } catch (Exception ex) { logger.Error(ex, () => nameof(OnClientConnected)); } }