private bool HadSuccess = true; //Asume a working condition at first

        public void PublishToAzure(PingDiagnostic diagnostic)
        {
            string urlToUse = ComposeUrl(azureConfig.Endpoint, diagnostic);

            new Thread(() => {
                try
                {
                    logger.LogDebug($"Publishing to to Azure {urlToUse}");
                    HttpClient client = new HttpClient();
                    var objectString  = JsonConvert.SerializeObject(diagnostic);

                    var content = new StringContent(objectString, Encoding.UTF8, "application/json");
                    var res     = client.PostAsync(urlToUse, content).GetAwaiter().GetResult();
                    logger.LogDebug($"Published to Azure {urlToUse} - {res.StatusCode}");

                    //Inform if connection is restored
                    if (!HadSuccess)
                    {
                        logger.LogWarning($"Restored publish to Azure {urlToUse}");
                    }
                    HadSuccess = true;
                }
                catch (Exception e)
                {
                    if (HadSuccess)
                    {
                        //Signal warning only on change
                        logger.LogWarning($"Cannot publish to Azure {urlToUse}: {e.Message}, will inform again when online");
                    }
                    logger.LogDebug($"Cannot publish to Azure {urlToUse}: {e.Message}");
                    HadSuccess = false;
                }
            }).Start();
        }
 // Check if there is already a response from this device, we are not doing duplicates
 private bool IsNewResponseForPing(PingDiagnostic tripData, PingDiagnosticResponse response)
 {
     if (tripData == null || response == null)
     {
         return(false);
     }
     return(!tripData.Responders.Any(r => r.Channel == response.Channel && r.ReceiverIdentifier == response.ReceiverIdentifier));
 }
 private string ComposeUrl(string rootUrl, PingDiagnostic diag)
 {
     if (!rootUrl.EndsWith("/"))
     {
         rootUrl += "/";
     }
     return($"{rootUrl}api/Ping/{diag.SessionIdentifier}/{diag.PingIdentifier}/");
 }
 private void HandleFinalizeOfPing(PingDiagnostic roundtrip, int sleep)
 {
     new Thread(() => {
         Thread.Sleep(sleep);
         logger.LogDebug($"Waking up to resolve ping: {roundtrip.SessionIdentifier}");
         CleanupPingResult(roundtrip);
         OutputPingResult(roundtrip);
     }).Start();
 }
Example #5
0
 private void RegisterPingRequest(PingDiagnostic diagnostic)
 {
     logger.LogInformation($"Writing request: {diagnostic.PingIdentifier}");
     RunQuery(SQLStoreRequest, new
     {
         SessionIdentifier = diagnostic.SessionIdentifier,
         PingIdentifier    = diagnostic.PingIdentifier,
         StartTime         = diagnostic.StartTime
     });
 }
        public PingDiagnostic RegisterTripStart(string sessionIdentifier, string pingIdentifier)
        {
            var rt = new PingDiagnostic()
            {
                SessionIdentifier = sessionIdentifier, PingIdentifier = pingIdentifier, StartTime = DateTime.Now
            };

            MulticastPings.Add(pingIdentifier, rt);
            return(rt);
        }
Example #7
0
 private static void WarnOnInconsistentIdentifiers(PingDiagnostic diag, ILogger log)
 {
     if (!diag.Responders?.Any() == true)
     {
         return;
     }
     if (diag.Responders.Any(r => r.PingIdentifier != diag.PingIdentifier || r.SessionIdentifier != diag.SessionIdentifier))
     {
         log.LogWarning($"One or more responses in ping {diag.SessionIdentifier}|{diag.PingIdentifier} did not contain the same identifiers (but will be forced to the parent ping anyway)");
     }
 }
 private void OutputPingToLog(PingDiagnostic roundtrip)
 {
     if (roundtrip.IsSuccess)
     {
         string formattedReplies = String.Join("|", roundtrip.Responders.Select(r => FormatReply(r)));
         logger.LogInformation($"{{{roundtrip.StartTime.ToString("HH:mm:ss.fff")}|{sessionIdentifier}|{roundtrip.PingIdentifier}|SUCCESS|{{{formattedReplies}}}}}");
     }
     else
     {
         logger.LogCritical($"{{{roundtrip.StartTime.ToString("HH:mm:ss.fff")}|{sessionIdentifier}|{roundtrip.PingIdentifier}|FAILED}}");
     }
 }
 public void PurgeTripResponse(PingDiagnostic result)
 {
     try
     {
         this.MulticastPings.Remove(result.PingIdentifier);
         logger.LogDebug($"Purged record: {result.PingIdentifier}");
     }
     catch (Exception e)
     {
         logger.LogDebug($"Cannot purge: {result.PingIdentifier} -> {e.Message}");
     }
 }
 public async System.Threading.Tasks.Task WritePing(PingDiagnostic ping)
 {
     try
     {
         await firebaseClient
         .Child(configuration.TopicRequests)
         .Child(GetIdentifier(ping))
         .PutAsync(ping.GetCopy());
     }
     catch (Exception e)
     {
         logger.LogWarning($"Cannot put ping {GetIdentifier(ping)}: {e.Message}");
     }
 }
 //TODO: The dispose is possibly not called for missed pings, which is flooding the datastream
 public async System.Threading.Tasks.Task DisposePing(PingDiagnostic ping)
 {
     try
     {
         await firebaseClient
         .Child(configuration.TopicRequests)
         .Child(GetIdentifier(ping))
         .DeleteAsync();
     }
     catch (Exception e)
     {
         logger.LogWarning($"Cannot dispose ping {GetIdentifier(ping)}: {e.Message}");
     }
 }
Example #12
0
 private void RegisterPongResponse(PingDiagnostic diagnostic, PingDiagnosticResponse response)
 {
     logger.LogInformation($"Writing response: {response.ReceiverIdentifier} for ping {diagnostic.PingIdentifier}");
     RunQuery(SQLStoreResponse, new {
         SessionIdentifier      = diagnostic.SessionIdentifier,
         PingIdentifier         = diagnostic.PingIdentifier,
         ReceiverIdentifer      = response.ReceiverIdentifier,
         ReceiveTime            = response.ReceiveTime,
         Channel                = response.Channel.ToString(),
         CellularType           = response.DeviceDetail.CellularType,
         CellularProvider       = response.DeviceDetail.CellularProvider,
         CellularSignalStrength = response.DeviceDetail.CellularSignalStrength,
         WifiProvider           = response.DeviceDetail.WifiProvider,
         WifiSignalStrength     = response.DeviceDetail.WifiSignalStrength,
         BatteryPercentage      = response.DeviceDetail.BatteryPercentage,
         VolumePercentage       = response.DeviceDetail.VolumePercentage
     });
 }
        public PingLookupResult RegisterTripResponse(PingDiagnostic tripData, PingDiagnosticResponse response)
        {
            //If the tripdata was not ours we skip processing and signal that it's not our process for now
            if (tripData == null)
            {
                return(PingLookupResult.Invalid);
            }

            if (IsNewResponseForPing(tripData, response))
            {
                tripData.Responders.Add(response);
            }
            else
            {
                logger.LogDebug($"Response on ping {tripData.SessionIdentifier}|{tripData.PingIdentifier} by {response.ReceiveTime} over {response.Channel} is already processed, skipping duplicate");
            }
            return(PingLookupResult.Found); //whether or not we were allowed to process this
        }
 private void TransmitPing(PingDiagnostic ping)
 {
     //TODO: The order of execution might influence how soon everything is processed, however this might be a bit overdone to make this a set of parallel threads
     try
     {
         if (configuration.TestFirebase)
         {
             firebaseChannel.WritePing(ping);
         }
         if (configuration.TestMulticast)
         {
             multicastClient.SendMessage($"MCPING|{ping.SessionIdentifier}|{ping.PingIdentifier}");
         }
     }catch (Exception e)
     {
         logger.LogWarning($"Failed to transmit ping: {e.Message}");
     }
 }
Example #15
0
        public static async Task <IActionResult> RegisterPingData([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "Ping/{sessionId}/{pingId}")] HttpRequest req,
                                                                  ILogger log, ExecutionContext context, string sessionId, string pingId)
        {
            try
            {
                string         requestBody = await new StreamReader(req.Body).ReadToEndAsync();
                PingDiagnostic ping        = JsonConvert.DeserializeObject <PingDiagnostic>(requestBody);
                log.LogInformation($"Received ping: {sessionId}|{pingId}");
                log.LogInformation($"Ping data: {ping?.IsSuccess}");

                //Sanity checks
                if (ping == null)
                {
                    log.LogError("No ping data provided"); return(new BadRequestObjectResult("No ping body received"));
                }
                if (sessionId != ping.SessionIdentifier)
                {
                    log.LogError($"Mismatch in sessionID: {sessionId} vs {ping.SessionIdentifier}"); return(new BadRequestObjectResult("SessionID mismatch between endpoint and body"));
                }
                if (pingId != ping.PingIdentifier)
                {
                    log.LogError($"Mismatch in ping: {pingId} vs {ping.PingIdentifier}"); return(new BadRequestObjectResult("PingID mismatch between endpoint and body"));
                }
                WarnOnInconsistentIdentifiers(ping, log);

                //Init config
                var configRoot = GetConfigurationRoot(context);

                //Store the data
                new PingDataWriter(configRoot, log).RegisterPingData(ping);

                //Success, tnx and bye
                return(new OkObjectResult(new { success = true, message = $"Stored ping {sessionId}|{pingId}" }));
            }
            catch (Exception e)
            {
                log.LogError($"Failed request: {e.ToString()}");
                return(new BadRequestObjectResult(new { success = false, message = $"Could not process request: {e.Message}" }));
            }
        }
Example #16
0
 public void RegisterPingData(PingDiagnostic diagnostic)
 {
     logger.LogInformation($"Processing storage of diagnostic with {diagnostic.Responders?.Count ?? 0} responses");
     RegisterPingRequest(diagnostic);
     diagnostic?.Responders?.ForEach(r => RegisterPongResponse(diagnostic, r));
 }
 private string GetIdentifier(PingDiagnostic ping)
 {
     return($"{ping.SessionIdentifier}|{ping.PingIdentifier}");
 }
 private void OutputPingResult(PingDiagnostic roundtrip)
 {
     OutputPingToLog(roundtrip);
     azurePublisher.PublishToAzure(roundtrip);
 }
 private void CleanupPingResult(PingDiagnostic roundtrip)
 {
     firebaseChannel.DisposePing(roundtrip);
     container.PurgeTripResponse(roundtrip);
 }