void InvalidSendToInfluxShouldNotPass() { string nodeId = "4816d758dd37833a3a5551001dac8a5fa737a342"; PayloadSigner signer = new PayloadSigner(nodeId, new FileKeyStore("./")); signer.Init(); RealTimeTelemetryManager mgr = new RealTimeTelemetryManager( nodeId, "http://127.0.0.1", "ws://127.0.0.1", "https://localhost:5010/api/ingress/realtime", "ED:40:5C:C9:E2:71:44:11:78:47:1C:09:6F:28:2E:B5:F9:4D:6E:CE:90:BC:64:5B:ED:9A:46:1F:20:E2:EE:4E", signer, _ftpMgr, true); RealTimeTelemetryPayload rttp = new RealTimeTelemetryPayload { Client = "Parity", BlockNum = 0, BlockHash = "", BlockTS = 0, BlockReceived = 0, NumPeers = 0, NumTxInBlock = 0 }; RealTimeTelemetry rtt = new RealTimeTelemetry { NodeId = "", Payload = rttp, Signature = signer.SignPayload(JsonConvert.SerializeObject(rttp)) }; var currentConsoleOut = Console.Out; using (var cop = new ConsoleOutputCapturer()) { MethodInfo methodInfo = typeof(RealTimeTelemetryManager).GetMethod("SendDataToIngress", BindingFlags.NonPublic | BindingFlags.Instance); object[] parameters = { rtt }; methodInfo.Invoke(mgr, parameters); string ret = cop.GetOuput(); Assert.Contains("Connection refused", ret); //Assert.True(ret.Contains("ERROR Occurred While sending data to Ingress")); } }
/// <summary> /// Function for sending data to ingress restful end point /// </summary> /// <param name="rtt">Reference of RealTimeTelemetry instance</param> private void SendDataToIngress(RealTimeTelemetry rtt) { try { //random pause of 55ms so we dnt have spike on ingress Thread.Sleep(new Random().Next(1, 500)); //push data to ingress real time telemetry endpoint string jsonPayload = JsonConvert.SerializeObject(rtt); bool sendSuccess = _tti.SendRequest(jsonPayload).Result; if (!sendSuccess) { // unable to send real time telemetry to ingress - send by second channel Console.WriteLine("ERROR: Unable to send to real time telemetry ingress. Sending data on second channel."); string fileName = $"{_nodeId}-{DateTime.UtcNow:yyyy-MM-dd_HH-mm-ss}.json"; try { if (!_ftpMgr.TransferData(jsonPayload, fileName)) { Console.WriteLine("ERROR: Unable to send real time telemetry on second channel. Data File {0}", fileName); } } catch (Exception ex) { Console.WriteLine("ERROR: Unable to send real time telemetry on second channel. Error Details {0}", ex); } } else { Console.WriteLine("Real Time Telemetry Block data sent to Ingress Block # {0}", rtt.Payload.BlockNum); } } catch (Exception ex) { Console.WriteLine("ERROR Occurred While sending data to Ingress. {0}", ex); } }
/// <summary> /// Receive method for web socket connection, It receivesreal time block data from parity and sends that to Ingress restful end point /// </summary> /// <param name="webSocket">ClientWebSocket instance reference</param> private async Task Receive(ClientWebSocket webSocket) { int bufferSize = 4096; byte[] temporaryBuffer = new byte[bufferSize]; byte[] buffer = new byte[bufferSize * 20]; int offset = 0; while (true) { WebSocketReceiveResult response = await webSocket.ReceiveAsync( new ArraySegment <byte>(temporaryBuffer), CancellationToken.None); temporaryBuffer.CopyTo(buffer, offset); offset += response.Count; temporaryBuffer = new byte[bufferSize]; if (response.EndOfMessage) { RealTimeTelemetry rtt = ParseAndSignData(buffer); if (rtt != null) { SendDataToIngress(rtt); } Array.Clear(temporaryBuffer, 0, temporaryBuffer.Length); Array.Clear(buffer, 0, buffer.Length); offset = 0; } if (response.MessageType == WebSocketMessageType.Close) { await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None); break; } } }
public ActionResult PostRealTimeTelemetry([FromBody] RealTimeTelemetry realTimePackage) { // verify incoming data if (realTimePackage?.NodeId == null || string.IsNullOrWhiteSpace(realTimePackage.Signature) || realTimePackage.Payload == null || string.IsNullOrWhiteSpace(realTimePackage.Payload.Client) || string.IsNullOrWhiteSpace(realTimePackage.Payload.BlockHash) ) { Console.WriteLine("Bad Request: " + JsonConvert.SerializeObject(realTimePackage, Formatting.Indented)); return(BadRequest()); } // Get Node key from keystore string nodeKey; try { nodeKey = _keyStore.GetKeyForNode(realTimePackage.NodeId); } catch (KeyNotFoundException) { Console.WriteLine($"Node Unknown: {realTimePackage.NodeId}"); return(StatusCode(403)); } // Verify Signature string payload = JsonConvert.SerializeObject(realTimePackage.Payload); bool signatureValid = SignatureVerifier.IsSignatureValid(payload, realTimePackage.Signature, nodeKey); if (!signatureValid) { Console.WriteLine($"Bad signature from node: {realTimePackage.NodeId}"); return(StatusCode(403)); } //Point format |measurement|,tag_set| |field_set| |timestamp| //create a point from incoming JSON Console.WriteLine($"Accepted RT telemetry from {realTimePackage.NodeId} "); long nanotimestamp = (long)(realTimePackage.Payload.BlockReceived * 1e9); string influxPoint = string.Format("parity,nodeid={0},client={1} blocknum={2},numpeers={3},blockts={4},numtxinblock={5},propagationtime={6},gaslimit={8},gasused={9} {7}", realTimePackage.NodeId, realTimePackage.Payload.Client, realTimePackage.Payload.BlockNum, realTimePackage.Payload.NumPeers, realTimePackage.Payload.BlockTS, realTimePackage.Payload.NumTxInBlock, (realTimePackage.Payload.BlockReceived - realTimePackage.Payload.BlockTS), nanotimestamp, realTimePackage.Payload.GasLimit, realTimePackage.Payload.GasUsed); // Signature valid - record to db if (_influx.Enqueue(influxPoint, true)) { return(Accepted()); } else { return(StatusCode(400)); } }
/// <summary> /// Function for parsing and signing block data /// </summary> /// <param name="buffer">block data in byte array</param> /// <returns>returns instance of RealTimeTelemetry if valid data is provided else null</returns> private RealTimeTelemetry ParseAndSignData(byte[] buffer) { try { string numPeers = GetCurrentNumPeers(); string clientVersion = GetCurrentClientVersion(); dynamic jsonObj = JsonConvert.DeserializeObject(_encoder.GetString(buffer).Trim()); dynamic paramsObj = jsonObj["params"]; if (paramsObj != null && paramsObj["result"] != null) { dynamic resultObj = paramsObj["result"]; string gasLimit = resultObj["gasLimit"]; string gasUsed = resultObj["gasUsed"]; long currentEPoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; RealTimeTelemetryPayload rttp = new RealTimeTelemetryPayload { Client = clientVersion, BlockNum = Convert.ToUInt64(resultObj["number"].ToString(), 16), BlockHash = resultObj["hash"].ToString(), BlockTS = Convert.ToInt64(resultObj["timestamp"].ToString(), 16), BlockReceived = currentEPoch, NumPeers = Convert.ToUInt16(numPeers, 16), NumTxInBlock = (ushort)resultObj["transactions"].Count, GasLimit = Convert.ToInt64(gasLimit, 16), GasUsed = Convert.ToInt64(gasUsed, 16) }; RealTimeTelemetry rtt = new RealTimeTelemetry { NodeId = _nodeId, Payload = rttp, Signature = _signer.SignPayload(JsonConvert.SerializeObject(rttp)) }; if (_verbose) { Console.WriteLine("New Block received"); Console.WriteLine("block num: {0}", rttp.BlockNum); Console.WriteLine("block hash: {0}", rttp.BlockHash); Console.WriteLine("block time stamp: {0}", rttp.BlockTS); Console.WriteLine("Tx Count: {0}", rttp.NumTxInBlock); Console.WriteLine("Gas Limit: {0}", Convert.ToInt64(gasLimit, 16)); Console.WriteLine("Gas Used: {0}", Convert.ToInt64(gasUsed, 16)); Console.WriteLine("Peers: {0} ", rttp.NumPeers); } return(rtt); } Console.WriteLine("Unable to Parse\\Sign real Time data. Invalid Data"); } catch (Exception ex) { Console.WriteLine("Unable to Parse\\Sign real Time data. Error Occurred {0}", ex); } return(null); }