/// <summary> /// Add a crash passed in the payload as Xml to the database. /// </summary> /// <param name="id">Unused.</param> /// <returns>The row id of the newly added crash.</returns> public ActionResult AddCrash(int id) { using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(NewCrashId=" + id + ")")) { CrashReporterResult NewCrashResult = new CrashReporterResult(); NewCrashResult.ID = -1; try { using (StreamReader Reader = new StreamReader(Request.InputStream, Request.ContentEncoding)) { string Result = Reader.ReadToEnd(); CrashDescription NewCrash = XmlHandler.FromXmlString <CrashDescription>(Result); NewCrashResult.ID = LocalCrashRepository.AddNewCrash(NewCrash); NewCrashResult.bSuccess = true; } } catch (Exception Ex) { NewCrashResult.Message = Ex.ToString(); NewCrashResult.bSuccess = false; } string ReturnResult = XmlHandler.ToXmlString <CrashReporterResult>(NewCrashResult); return(Content(ReturnResult, "text/xml")); } }
private void UnsafeAddCrash(CrashReporterResult NewCrashResult, CrashRepository Crashes) { using (StreamReader Reader = new StreamReader(Request.InputStream, Request.ContentEncoding)) { string Result = Reader.ReadToEnd(); CrashDescription NewCrash = XmlHandler.FromXmlString <CrashDescription>(Result); NewCrashResult.ID = Crashes.AddNewCrash(NewCrash); NewCrashResult.bSuccess = true; } }
/// <summary> /// Add a crash passed in the payload as Xml to the database. /// </summary> /// <param name="id">Unused.</param> /// <returns>The row id of the newly added crash.</returns> public ActionResult AddCrash(int id) { using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(NewCrashId=" + id + ")")) { CrashRepository Crashes = new CrashRepository(); CrashReporterResult NewCrashResult = new CrashReporterResult(); NewCrashResult.ID = -1; string PayloadString = string.Empty; for (int Index = 0; Index < 3; Index++) { try { using (StreamReader Reader = new StreamReader(Request.InputStream, Request.ContentEncoding)) { PayloadString = Reader.ReadToEnd(); CrashDescription NewCrash = XmlHandler.FromXmlString <CrashDescription>(PayloadString); NewCrashResult.ID = Crashes.AddNewCrash(NewCrash); NewCrashResult.bSuccess = true; } break; } catch (SqlException SqlExc) { if (SqlExc.Number == -2) { FLogger.Global.WriteEvent(string.Format("AddCrash:Timeout, retrying {0} of 3", Index + 1)); } else { NewCrashResult.Message = SqlExc.ToString(); NewCrashResult.bSuccess = false; break; } } catch (Exception Ex) { StringBuilder MessageBuilder = new StringBuilder(); MessageBuilder.AppendLine("Exception was:"); MessageBuilder.AppendLine(Ex.ToString()); MessageBuilder.AppendLine("Received payload was:"); MessageBuilder.AppendLine(PayloadString); NewCrashResult.Message = MessageBuilder.ToString(); NewCrashResult.bSuccess = false; break; } System.Threading.Thread.Sleep(5000 * (Index + 1)); } string ReturnResult = XmlHandler.ToXmlString <CrashReporterResult>(NewCrashResult); return(Content(ReturnResult, "text/xml")); } }
/// <summary> /// Call the web service function with an Xml payload to add a crash to the database. /// </summary> /// <param name="Payload">Xml representation of a new crash to upload.</param> /// <returns>The database id of the newly added row.</returns> private int UploadCrash(string Payload) { int NewID = -1; try { // Simple suppression by blanking out the URL for local testing if (Config.Default.CrashReportWebSite.Length > 0) { bool bDebug = false; string RequestString; if (!bDebug) { RequestString = "http://" + Config.Default.CrashReportWebSite + ":80/Crashes/AddCrash/-1"; } else { RequestString = "http://localhost:80/Crashes/AddCrash/-1"; } string ErrorMessage = string.Empty; for (int Retry = 0; Retry < 3; ++Retry) { string ResponseString = SimpleWebRequest.GetWebServiceResponse(RequestString, Payload); if (ResponseString.Length > 0) { // Convert response into a string CrashReporterResult Result = XmlHandler.FromXmlString <CrashReporterResult>(ResponseString); if (Result.ID > 0) { NewID = Result.ID; break; } ErrorMessage = Result.Message; } Thread.Sleep(200); } if (NewID == -1) { CrashReporterProcessServicer.WriteFailure(string.Format("PROC-{0} ", ProcessorIndex) + "UploadCrash: " + ErrorMessage); } } } catch (Exception Ex) { CrashReporterProcessServicer.WriteException(string.Format("PROC-{0} ", ProcessorIndex) + "UploadCrash: " + Ex.ToString()); } return(NewID); }
/// <summary> /// Check to see if we wish to reject a report based on the WER meta data. /// </summary> /// <param name="Request">A request containing the XML representation of a WERReportMetadata class instance.</param> /// <returns>true if we do not reject.</returns> private CrashReporterResult CheckReportDetail(HttpListenerRequest Request) { CrashReporterResult ReportResult = new CrashReporterResult(); #if DISABLED_CRR ReportResult.bSuccess = false; ReportResult.Message = "CRR disabled"; CrashReporterReceiverServicer.WriteEvent("CheckReportDetail() Report rejected by disabled CRR"); #else string WERReportMetadataString = GetContentStreamString(Request); WERReportMetadata WERData = null; if (WERReportMetadataString.Length > 0) { try { WERData = XmlHandler.FromXmlString <WERReportMetadata>(WERReportMetadataString); } catch (System.Exception Ex) { CrashReporterReceiverServicer.WriteEvent("Error during XmlHandler.FromXmlString, probably incorrect encoding, trying to fix: " + Ex.Message); byte[] StringBytes = System.Text.Encoding.Unicode.GetBytes(WERReportMetadataString); string ConvertedXML = System.Text.Encoding.UTF8.GetString(StringBytes); WERData = XmlHandler.FromXmlString <WERReportMetadata>(ConvertedXML); } } if (WERData != null) { // Ignore crashes in the minidump parser itself ReportResult.bSuccess = true; if (WERData.ProblemSignatures.Parameter0.ToLower() == "MinidumpDiagnostics".ToLower()) { ReportResult.bSuccess = false; ReportResult.Message = "Rejecting MinidumpDiagnostics crash"; } // Ignore Debug and DebugGame crashes string CrashingModule = WERData.ProblemSignatures.Parameter3.ToLower(); if (CrashingModule.Contains("-debug")) { ReportResult.bSuccess = false; ReportResult.Message = "Rejecting Debug or DebugGame crash"; } } #endif return(ReportResult); }
/// <summary> /// Check to see if a report has already been uploaded. /// </summary> /// <param name="Request">A request containing either the Report Id as a string or an XML representation of a CheckReportRequest class instance.</param> /// <returns>Result object, indicating whether the report has already been uploaded.</returns> private CrashReporterResult CheckReport(HttpListenerRequest Request) { var ReportResult = new CrashReporterResult(); var RequestClass = new CheckReportRequest(); RequestClass.ReportId = GetReportIdFromPostData(GetContentStreamString(Request)); ReportResult.bSuccess = !LandingZone.HasReportAlreadyBeenReceived(RequestClass.ReportId); if (!ReportResult.bSuccess) { CrashReporterReceiverServicer.WriteEvent(string.Format("Report \"{0}\" has already been received", RequestClass.ReportId)); } return(ReportResult); }
/// <summary> /// Call the web service function with an Xml payload to add a crash to the database. /// </summary> /// <param name="Payload">Xml representation of a new crash to upload.</param> /// <returns>The database id of the newly added row.</returns> private int UploadCrash(string Payload) { int NewID = -1; try { // Simple suppression by blanking out the URL for local testing if (Properties.Settings.Default.CrashReportWebSite.Length > 0) { bool bDebug = false; string RequestString; if (!bDebug) { RequestString = "http://" + Properties.Settings.Default.CrashReportWebSite + ":80/Crashes/AddCrash/-1"; } else { RequestString = "http://localhost:80/Crashes/AddCrash/-1"; } string ResponseString = SimpleWebRequest.GetWebServiceResponse(RequestString, Payload); if (ResponseString.Length > 0) { // Convert response into a string CrashReporterResult Result = XmlHandler.FromXmlString <CrashReporterResult>(ResponseString); if (Result.ID > 0) { NewID = Result.ID; } else { CrashReporterProcessServicer.WriteFailure("UploadCrash: " + Result.Message); } } } } catch (Exception Ex) { CrashReporterProcessServicer.WriteException("UploadCrash: " + Ex.ToString()); } return(NewID); }
/// <summary> /// Add a crash passed in the payload as Xml to the database. /// </summary> /// <param name="id">Unused.</param> /// <returns>The row id of the newly added crash.</returns> public ActionResult AddCrash(int id) { using (FAutoScopedLogTimer LogTimer = new FAutoScopedLogTimer(this.GetType().ToString() + "(NewCrashId=" + id + ")")) { CrashRepository Crashes = new CrashRepository(); CrashReporterResult NewCrashResult = new CrashReporterResult(); NewCrashResult.ID = -1; for (int Index = 0; Index < 3; Index++) { try { UnsafeAddCrash(NewCrashResult, Crashes); break; } catch (SqlException SqlExc) { if (SqlExc.Number == -2) { FLogger.Global.WriteEvent(string.Format("AddCrash:Timeout, retrying {0} of 3", Index + 1)); } else { NewCrashResult.Message = SqlExc.ToString(); NewCrashResult.bSuccess = false; break; } } catch (Exception Ex) { NewCrashResult.Message = Ex.ToString(); NewCrashResult.bSuccess = false; break; } System.Threading.Thread.Sleep(5000 * (Index + 1)); } string ReturnResult = XmlHandler.ToXmlString <CrashReporterResult>(NewCrashResult); return(Content(ReturnResult, "text/xml")); } }
/// <summary> /// Check to see if a report has already been uploaded. /// </summary> /// <param name="Request">A request containing either the Report Id as a string or an XML representation of a CheckReportRequest class instance.</param> /// <returns>Result object, indicating whether the report has already been uploaded.</returns> private CrashReporterResult CheckReport(HttpListenerRequest Request) { CrashReporterResult ReportResult = new CrashReporterResult(); #if DISABLED_CRR ReportResult.bSuccess = false; CrashReporterReceiverServicer.WriteEvent("CheckReport() Report rejected by disabled CRR"); #else var RequestClass = new CheckReportRequest(); RequestClass.ReportId = GetReportIdFromPostData(GetContentStreamString(Request)); ReportResult.bSuccess = !LandingZone.HasReportAlreadyBeenReceived(RequestClass.ReportId); if (!ReportResult.bSuccess) { CrashReporterReceiverServicer.WriteEvent(string.Format("Report \"{0}\" has already been received", RequestClass.ReportId)); } #endif return(ReportResult); }
/// <summary> /// Rename to the temporary landing zone directory to the final location. /// </summary> /// <param name="Request">A request containing either the Report Id as a string or an XML representation of a CheckReportRequest class instance.</param> /// <returns>true if everything is renamed correctly.</returns> private CrashReporterResult UploadComplete(HttpListenerRequest Request) { var ReportResult = new CrashReporterResult(); var RequestClass = new CheckReportRequest(); RequestClass.ReportId = GetReportIdFromPostData(GetContentStreamString(Request)); string IntermediatePathName = Path.Combine(FileReceiptPath, RequestClass.ReportId); if (!UploadsInProgress.TrySetReportComplete(RequestClass.ReportId)) { ReportResult.Message = string.Format("Report \"{0}\" has already been completed", RequestClass.ReportId); ReportResult.bSuccess = false; return(ReportResult); } DirectoryInfo DirInfo = new DirectoryInfo(IntermediatePathName); if (!DirInfo.Exists) { return(ReportResult); } LandingZone.ReceiveReport(DirInfo, RequestClass.ReportId); ReportResult.bSuccess = true; int CurrentDay = DateTime.UtcNow.Day; if (CurrentDay > LastDay) { // Check the log and create a new one for a new day. CrashReporterReceiverServicer.Log.CreateNewLogFile(); LastDay = CurrentDay; } return(ReportResult); }
/// <summary> /// The main listener callback to handle client requests. /// </summary> /// <param name="ClientRequest">The request from the client.</param> private void AsyncHandleHttpRequest(IAsyncResult ClientRequest) { try { HttpListenerContext Context = ServiceHttpListener.EndGetContext(ClientRequest); ServiceHttpListener.BeginGetContext(AsyncHandleHttpRequest, null); HttpListenerRequest Request = Context.Request; bool bIgnorePerfData = false; using (HttpListenerResponse Response = Context.Response) { // Extract the URL parameters string[] UrlElements = Request.RawUrl.Split("/".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); // http://*:57005/CrashReporter/CheckReport // http://*:57005/CrashReporter/CheckReportDetail CrashReporterResult ReportResult = new CrashReporterResult(); if (UrlElements[0].ToLower() == "crashreporter") { switch (UrlElements[1].ToLower()) { case "ping": ReportResult.bSuccess = true; break; case "checkreport": ReportResult = CheckReport(Context.Request); break; case "checkreportdetail": ReportResult = CheckReportDetail(Context.Request); break; case "uploadreportfile": ReportResult = ReceiveFile(Context.Request); bIgnorePerfData = true; break; case "uploadcomplete": ReportResult = UploadComplete(Context.Request); break; default: ReportResult.bSuccess = false; ReportResult.Message = "Invalid command: " + UrlElements[1]; break; } } else { ReportResult.bSuccess = false; ReportResult.Message = "Invalid application: " + UrlElements[0] + " (expecting CrashReporter)"; } string ResponseString = XmlHandler.ToXmlString <CrashReporterResult>(ReportResult); Response.SendChunked = true; Response.ContentType = "text/xml"; byte[] Buffer = Encoding.UTF8.GetBytes(ResponseString); Response.ContentLength64 = Buffer.Length; Response.OutputStream.Write(Buffer, 0, Buffer.Length); Response.StatusCode = ( int )HttpStatusCode.OK; if (!bIgnorePerfData) { // Update the overhead data. Int64 ContentLenght = Response.ContentLength64 + Request.ContentLength64; Interlocked.Add(ref UploadsInProgress.CurrentReceivedData, ContentLenght); } } } catch (Exception Ex) { CrashReporterReceiverServicer.WriteEvent("Error during async listen: " + Ex.Message); } }
/// <summary> /// Receive a file and write it to a temporary folder. /// </summary> /// <param name="Request">A request containing the file details in the headers (DirectoryName/FileName/FileLength).</param> /// <returns>true if the file is received successfully.</returns> /// <remarks>There is an arbitrary file size limit of CrashReporterConstants.MaxFileSizeToUpload as a simple exploit prevention method.</remarks> private CrashReporterResult ReceiveFile(HttpListenerRequest Request) { CrashReporterResult ReportResult = new CrashReporterResult(); if (!Request.HasEntityBody) { return(ReportResult); } // Take this opportunity to clean out folders for reports that were never completed CheckForAbandonedReports(); // Make sure we have a sensible file size long BytesToReceive = 0; if (long.TryParse(Request.Headers["FileLength"], out BytesToReceive)) { if (BytesToReceive >= CrashReporterConstants.MaxFileSizeToUpload) { return(ReportResult); } } string DirectoryName = Request.Headers["DirectoryName"]; string FileName = Request.Headers["FileName"]; var T = Request.ContentLength64; bool bIsOverloaded = false; if (!UploadsInProgress.TryReceiveFile(DirectoryName, FileName, BytesToReceive, ref ReportResult.Message, ref bIsOverloaded)) { CrashReporterReceiverServicer.WriteEvent(ReportResult.Message); ReportResult.bSuccess = false; return(ReportResult); } string PathName = Path.Combine(FileReceiptPath, DirectoryName, FileName); // Recreate the file receipt directory, just in case. Directory.CreateDirectory(FileReceiptPath); // Create the folder to save files to DirectoryInfo DirInfo = new DirectoryInfo(Path.GetDirectoryName(PathName)); DirInfo.Create(); // Make sure the file doesn't already exist. If it does, delete it. if (File.Exists(PathName)) { File.Delete(PathName); } FileInfo Info = new FileInfo(PathName); FileStream FileWriter = Info.OpenWrite(); // Read in the input stream from the request, and write to a file long OriginalBytesToReceive = BytesToReceive; try { using (BinaryReader Reader = new BinaryReader(Request.InputStream)) { byte[] Buffer = new byte[CrashReporterConstants.StreamChunkSize]; while (BytesToReceive > 0) { int BytesToRead = Math.Min((int)BytesToReceive, CrashReporterConstants.StreamChunkSize); Interlocked.Add(ref UploadsInProgress.CurrentReceivedData, BytesToRead); int ReceivedChunkSize = Reader.Read(Buffer, 0, BytesToRead); if (ReceivedChunkSize == 0) { ReportResult.Message = string.Format("Partial file \"{0}\" received", FileName); ReportResult.bSuccess = false; CrashReporterReceiverServicer.WriteEvent(ReportResult.Message); return(ReportResult); } BytesToReceive -= ReceivedChunkSize; FileWriter.Write(Buffer, 0, ReceivedChunkSize); } } } finally { FileWriter.Close(); Request.InputStream.Close(); UploadsInProgress.FileUploadAttemptDone(OriginalBytesToReceive, bIsOverloaded); bool bWriteMetadata = Path.GetExtension(FileName) == ".ue4crash"; if (bWriteMetadata) { string CompressedSize = Request.Headers["CompressedSize"]; string UncompressedSize = Request.Headers["UncompressedSize"]; string NumberOfFiles = Request.Headers["NumberOfFiles"]; string MetadataPath = Path.Combine(FileReceiptPath, DirectoryName, Path.GetFileNameWithoutExtension(FileName) + ".xml"); XmlHandler.WriteXml <FCompressedCrashInformation>(new FCompressedCrashInformation(CompressedSize, UncompressedSize, NumberOfFiles), MetadataPath); } } ReportResult.bSuccess = true; return(ReportResult); }
/// <summary> /// Add a crash passed in the payload as Xml to the database. /// </summary> /// <param name="id">Unused.</param> /// <returns>The row id of the newly added crash.</returns> public ActionResult AddCrash(int id) { var newCrashResult = new CrashReporterResult(); CrashDescription newCrash; newCrashResult.ID = -1; string payloadString; //Read the request payload try { using (var reader = new StreamReader(Request.InputStream, Request.ContentEncoding)) { payloadString = reader.ReadToEnd(); if (string.IsNullOrEmpty(payloadString)) { FLogger.Global.WriteEvent(string.Format("Add Crash Failed : Payload string empty")); } } } catch (Exception ex) { var messageBuilder = new StringBuilder(); messageBuilder.AppendLine("Error Reading Crash Payload"); messageBuilder.AppendLine("Exception was:"); messageBuilder.AppendLine(ex.ToString()); FLogger.Global.WriteException(messageBuilder.ToString()); newCrashResult.Message = messageBuilder.ToString(); newCrashResult.bSuccess = false; return(Content(XmlHandler.ToXmlString <CrashReporterResult>(newCrashResult), "text/xml")); } // De-serialise the payload string try { newCrash = XmlHandler.FromXmlString <CrashDescription>(payloadString); } catch (Exception ex) { var messageBuilder = new StringBuilder(); messageBuilder.AppendLine("Error Reading CrashDescription XML"); messageBuilder.AppendLine("Exception was: "); messageBuilder.AppendLine(ex.ToString()); FLogger.Global.WriteException(messageBuilder.ToString()); newCrashResult.Message = messageBuilder.ToString(); newCrashResult.bSuccess = false; return(Content(XmlHandler.ToXmlString <CrashReporterResult>(newCrashResult), "text/xml")); } //Add crash to database try { var crash = CreateCrash(newCrash); newCrashResult.ID = crash.Id; newCrashResult.bSuccess = true; } catch (DbEntityValidationException dbentEx) { var messageBuilder = new StringBuilder(); messageBuilder.AppendLine("Exception was:"); messageBuilder.AppendLine(dbentEx.ToString()); var innerEx = dbentEx.InnerException; while (innerEx != null) { messageBuilder.AppendLine("Inner Exception : " + innerEx.Message); innerEx = innerEx.InnerException; } if (dbentEx.EntityValidationErrors != null) { messageBuilder.AppendLine("Validation Errors : "); foreach (var valErr in dbentEx.EntityValidationErrors) { messageBuilder.AppendLine(valErr.ValidationErrors.Select(data => data.ErrorMessage).Aggregate((current, next) => current + "; /n" + next)); } } messageBuilder.AppendLine("Received payload was:"); messageBuilder.AppendLine(payloadString); FLogger.Global.WriteException(messageBuilder.ToString()); newCrashResult.Message = messageBuilder.ToString(); newCrashResult.bSuccess = false; } catch (SqlException sqlExc) { if (sqlExc.Number == -2) //If this is an sql timeout log the timeout and try again. { FLogger.Global.WriteEvent(string.Format("AddCrash: Timeout")); } else { var messageBuilder = new StringBuilder(); messageBuilder.AppendLine("Exception was:"); messageBuilder.AppendLine(sqlExc.ToString()); messageBuilder.AppendLine("Received payload was:"); messageBuilder.AppendLine(payloadString); FLogger.Global.WriteException(messageBuilder.ToString()); newCrashResult.Message = messageBuilder.ToString(); newCrashResult.bSuccess = false; } } catch (Exception ex) { var messageBuilder = new StringBuilder(); messageBuilder.AppendLine("Exception was:"); messageBuilder.AppendLine(ex.ToString()); messageBuilder.AppendLine("Received payload was:"); messageBuilder.AppendLine(payloadString); FLogger.Global.WriteException(messageBuilder.ToString()); newCrashResult.Message = messageBuilder.ToString(); newCrashResult.bSuccess = false; } string returnResult = XmlHandler.ToXmlString <CrashReporterResult>(newCrashResult); return(Content(returnResult, "text/xml")); }
/// <summary> /// Call the web service function with an Xml payload to add a crash to the database. /// </summary> /// <param name="Payload">Xml representation of a new crash to upload.</param> /// <returns>The database id of the newly added row.</returns> private int UploadCrash(string Payload) { int NewID = -1; try { // Simple suppression by blanking out the URL for local testing if (Config.Default.CrashReportWebSite.Length > 0) { bool bDebug = false; string RequestString; if (!bDebug) { RequestString = "http://" + Config.Default.CrashReportWebSite + ":80/Crashes/AddCrash/-1"; } else { RequestString = "http://localhost:80/Crashes/AddCrash/-1"; } Action <UploadRetryState> TryUpload = InRetryState => { string ResponseString = SimpleWebRequest.GetWebServiceResponse(RequestString, Payload, Config.Default.AddCrashRequestTimeoutSeconds * 1000); if (ResponseString.Length > 0) { // Convert response into a string CrashReporterResult Result = XmlHandler.FromXmlString <CrashReporterResult>(ResponseString); if (!Result.bSuccess || Result.ID <= 0) { if (Result.bTimeout) { // Website responded - website->DB connection timeout InRetryState.Timeouts++; } else { // Website responded - fail condition InRetryState.BadResponses++; CrashReporterProcessServicer.WriteEvent(string.Format("PROC-{0} UploadCrash response invalid. FailedResponses={1} Response={2}", ProcessorIndex, InRetryState.BadResponses, Result.Message)); if (InRetryState.BadResponses > Config.Default.AddCrashRejectedRetries) { InRetryState.bShouldRetry = false; CrashReporterProcessServicer.WriteEvent(string.Format("PROC-{0} UploadCrash abandoned. FailedResponses={1}", ProcessorIndex, InRetryState.BadResponses)); } } } else { // Website responded - success NewID = Result.ID; InRetryState.bUploaded = true; return; } } else { // No response InRetryState.Timeouts++; } InRetryState.bUploaded = false; }; Action <UploadRetryState> OnRetry = InRetryState => { if (!InRetryState.bUploaded) { Thread.Sleep(Config.Default.AddCrashRetryDelaySeconds * 1000); CrashReporterProcessServicer.WriteEvent(string.Format("PROC-{0} UploadCrash retrying upload. Timeouts={1} FailedResponses={2}", ProcessorIndex, InRetryState.Timeouts, InRetryState.BadResponses)); } }; UploadRetryState RetryState = new UploadRetryState(); for (; !RetryState.bUploaded && RetryState.bShouldRetry && !CancelSource.IsCancellationRequested; OnRetry(RetryState)) { TryUpload(RetryState); CrashReporterProcessServicer.StatusReporter.AlertOnConsecutiveFails("AddCrash", "Cannot contact CR website. CRP is paused!", "Contact with CR website restored.", TimeSpan.FromSeconds(Config.Default.FailedWebAddAlertTimeSeconds), RetryState.bUploaded); } } #if DEBUG else { // No website set - simulate successful upload var Rnd = new Random(); NewID = Rnd.Next(1, 99999999); } #endif } catch (Exception Ex) { CrashReporterProcessServicer.WriteException(string.Format("PROC-{0} ", ProcessorIndex) + "UploadCrash: " + Ex, Ex); } return(NewID); }
/// <summary> /// Call the web service function with an Xml payload to add a crash to the database. /// </summary> /// <param name="Payload">Xml representation of a new crash to upload.</param> /// <returns>The database id of the newly added row.</returns> private int UploadCrash(string Payload) { int NewID = -1; try { // Simple suppression by blanking out the URL for local testing if (Config.Default.CrashReportWebSite.Length > 0) { bool bDebug = false; string RequestString; if (!bDebug) { RequestString = "http://" + Config.Default.CrashReportWebSite + ":80/Crashes/AddCrash/-1"; } else { RequestString = "http://localhost:80/Crashes/AddCrash/-1"; } string ErrorMessage = string.Empty; const int MaxRetries = 1; for (int AddCrashTry = 0; AddCrashTry < MaxRetries + 1; ++AddCrashTry) { string ResponseString = SimpleWebRequest.GetWebServiceResponse(RequestString, Payload, Config.Default.AddCrashRequestTimeoutMillisec); if (ResponseString.Length > 0) { // Convert response into a string CrashReporterResult Result = XmlHandler.FromXmlString <CrashReporterResult>(ResponseString); if (Result.ID > 0) { NewID = Result.ID; break; } CrashReporterProcessServicer.WriteEvent(string.Format("PROC-{0} UploadCrash response timeout (attempt {1} of {2}): {3}", ProcessorIndex, AddCrashTry + 1, MaxRetries + 1, ErrorMessage)); ErrorMessage = Result.Message; } Thread.Sleep(Config.Default.AddCrashRetryDelayMillisec); } if (NewID == -1) { CrashReporterProcessServicer.WriteFailure(string.Format("PROC-{0} ", ProcessorIndex) + "UploadCrash failed: " + ErrorMessage); } } #if DEBUG else { // No website set - simulate successful upload var Rnd = new Random(); NewID = Rnd.Next(1, 99999999); } #endif } catch (Exception Ex) { CrashReporterProcessServicer.WriteException(string.Format("PROC-{0} ", ProcessorIndex) + "UploadCrash: " + Ex, Ex); } return(NewID); }
/// <summary> /// Call the web service function with an Xml payload to add a crash to the database. /// </summary> /// <param name="Payload">Xml representation of a new crash to upload.</param> /// <returns>The database id of the newly added row.</returns> private int UploadCrash(string Payload) { int NewID = -1; try { // Simple suppression by blanking out the URL for local testing if (Config.Default.CrashReportWebSite.Length > 0) { bool bDebug = false; string RequestString; if (!bDebug) { RequestString = "http://" + Config.Default.CrashReportWebSite + ":80/Crashes/AddCrash/-1"; } else { RequestString = "http://localhost:80/Crashes/AddCrash/-1"; } int Attempt = 1; Func <bool> TryUpload = () => { string ResponseString = SimpleWebRequest.GetWebServiceResponse(RequestString, Payload, Config.Default.AddCrashRequestTimeoutSeconds * 1000); if (ResponseString.Length > 0) { // Convert response into a string CrashReporterResult Result = XmlHandler.FromXmlString <CrashReporterResult>(ResponseString); if (Result.ID > 0) { NewID = Result.ID; return(true); } CrashReporterProcessServicer.WriteEvent(string.Format("PROC-{0} UploadCrash response invalid (upload attempt {1}): {2}", ProcessorIndex, Attempt, Result.Message)); } return(false); }; Action <bool> OnRetry = bUploaded => { if (!bUploaded) { Thread.Sleep(Config.Default.AddCrashRetryDelaySeconds * 1000); CrashReporterProcessServicer.WriteEvent(string.Format("PROC-{0} UploadCrash retrying upload attempt {1}", ProcessorIndex, Attempt)); Attempt++; } }; for (bool bUploaded = false; !bUploaded; OnRetry(bUploaded)) { bUploaded = TryUpload(); CrashReporterProcessServicer.StatusReporter.AlertOnConsecutiveFails("AddCrash", "Cannot contact CR website. CRP is paused!", "Contact with CR website restored.", TimeSpan.FromSeconds(Config.Default.FailedWebAddAlertTimeSeconds), bUploaded); } } #if DEBUG else { // No website set - simulate successful upload var Rnd = new Random(); NewID = Rnd.Next(1, 99999999); } #endif } catch (Exception Ex) { CrashReporterProcessServicer.WriteException(string.Format("PROC-{0} ", ProcessorIndex) + "UploadCrash: " + Ex, Ex); } return(NewID); }