diff --git a/CUERipper/frmCUERipper.cs b/CUERipper/frmCUERipper.cs index fcd19dc..0140e8e 100644 --- a/CUERipper/frmCUERipper.cs +++ b/CUERipper/frmCUERipper.cs @@ -382,7 +382,7 @@ namespace CUERipper cueSheet.Artist, cueSheet.Title); bool canFix = false; - if (cueSheet.CTDB.AccResult == HttpStatusCode.OK && audioSource.ErrorsCount != 0) + if (cueSheet.CTDB.QueryExceptionStatus == WebExceptionStatus.Success && audioSource.ErrorsCount != 0) { foreach (DBEntry entry in cueSheet.CTDB.Entries) if (entry.hasErrors && entry.canRecover) diff --git a/CUETools.CTDB.EACPlugin/FormSubmitParity.Designer.cs b/CUETools.CTDB.EACPlugin/FormSubmitParity.Designer.cs index 7fc3c9d..2d0e7e8 100644 --- a/CUETools.CTDB.EACPlugin/FormSubmitParity.Designer.cs +++ b/CUETools.CTDB.EACPlugin/FormSubmitParity.Designer.cs @@ -44,6 +44,7 @@ // backgroundWorker1 // this.backgroundWorker1.WorkerReportsProgress = true; + this.backgroundWorker1.WorkerSupportsCancellation = true; this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork); this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted); this.backgroundWorker1.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker1_ProgressChanged); @@ -53,7 +54,6 @@ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(349, 49); - this.ControlBox = false; this.Controls.Add(this.progressBar1); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; this.MaximizeBox = false; @@ -63,6 +63,7 @@ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Contacting CTDB..."; this.Load += new System.EventHandler(this.FormMetadata_Load); + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormSubmitParity_FormClosing); this.ResumeLayout(false); } diff --git a/CUETools.CTDB.EACPlugin/FormSubmitParity.cs b/CUETools.CTDB.EACPlugin/FormSubmitParity.cs index 6818cbe..4888ab3 100644 --- a/CUETools.CTDB.EACPlugin/FormSubmitParity.cs +++ b/CUETools.CTDB.EACPlugin/FormSubmitParity.cs @@ -69,5 +69,15 @@ namespace CUETools.CTDB.EACPlugin this.progressBar1.Style = e.ProgressPercentage != 0 ? ProgressBarStyle.Continuous : ProgressBarStyle.Marquee; this.progressBar1.Value = Math.Max(0, Math.Min(100, e.ProgressPercentage)); } + + private void FormSubmitParity_FormClosing(object sender, FormClosingEventArgs e) + { + if (this.backgroundWorker1.IsBusy) + { + e.Cancel = true; + this.progressBar1.Style = ProgressBarStyle.Marquee; + this.ctdb.CancelRequest(); + } + } } } diff --git a/CUETools.CTDB.EACPlugin/Metadata.cs b/CUETools.CTDB.EACPlugin/Metadata.cs index 27abfba..9432bb7 100644 --- a/CUETools.CTDB.EACPlugin/Metadata.cs +++ b/CUETools.CTDB.EACPlugin/Metadata.cs @@ -90,7 +90,7 @@ namespace MetadataPlugIn public string GetPluginName() { - return "CUETools DB Metadata Plugin V2.1.2"; + return "CUETools DB Metadata Plugin V2.1.2b"; } public void ShowOptions() diff --git a/CUETools.CTDB.EACPlugin/Plugin.cs b/CUETools.CTDB.EACPlugin/Plugin.cs index c5061d1..3e04652 100644 --- a/CUETools.CTDB.EACPlugin/Plugin.cs +++ b/CUETools.CTDB.EACPlugin/Plugin.cs @@ -54,7 +54,7 @@ namespace AudioDataPlugIn // the plugin and for display in the log file public string GetAudioTransferPluginName() { - return "CUETools DB Plugin V2.1.2"; + return "CUETools DB Plugin V2.1.2b"; } // Each plugin should have its own options page. @@ -219,7 +219,7 @@ namespace AudioDataPlugIn m_data.AlbumArtist, m_data.AlbumTitle); form.ShowDialog(); - sw.WriteLine("[CTDB TOCID: {0}] {1}{2}.", + sw.WriteLine("[CTDB TOCID: {0}] {1}{2}", TOC.TOCID, ctdb.DBStatus ?? "found", (ctdb.SubStatus == null) ? "" : (", Submit result: " + ctdb.SubStatus)); @@ -245,7 +245,7 @@ namespace AudioDataPlugIn status); } bool canFix = false; - if (ctdb.AccResult == HttpStatusCode.OK) + if (ctdb.QueryExceptionStatus == WebExceptionStatus.Success) { foreach (DBEntry entry in ctdb.Entries) if (entry.hasErrors && entry.canRecover) diff --git a/CUETools.CTDB/CUEToolsDB.cs b/CUETools.CTDB/CUEToolsDB.cs index d68b919..92479e1 100644 --- a/CUETools.CTDB/CUEToolsDB.cs +++ b/CUETools.CTDB/CUEToolsDB.cs @@ -24,15 +24,16 @@ namespace CUETools.CTDB private CDRepairEncode verify; private CDImageLayout toc; - private HttpStatusCode accResult; private string subResult; private int length; private int total; - List entries = new List(); - List metadata = new List(); - DBEntry selectedEntry; - IWebProxy proxy; - HttpUploadHelper uploadHelper; + private List entries = new List(); + private List metadata = new List(); + private DBEntry selectedEntry; + private IWebProxy proxy; + private HttpUploadHelper uploadHelper; + private HttpWebRequest currentReq; + private int connectTimeout, socketTimeout; public CUEToolsDB(CDImageLayout toc, IWebProxy proxy) { @@ -40,6 +41,19 @@ namespace CUETools.CTDB this.length = (int)toc.AudioLength * 588; this.proxy = proxy; this.uploadHelper = new HttpUploadHelper(); + this.QueryExceptionStatus = WebExceptionStatus.Pending; + this.connectTimeout = 15000; + this.socketTimeout = 30000; + } + + public void CancelRequest() + { + var r = currentReq; + // copy link to currentReq, because it can be set to null by other thread. + if (r != null) + { + r.Abort(); + } } public void ContactDB(string userAgent, string driveName, bool musicbrainz, bool fuzzy) @@ -55,57 +69,73 @@ namespace CUETools.CTDB req.Method = "GET"; req.Proxy = proxy; req.UserAgent = this.userAgent; + req.Timeout = connectTimeout; + req.ReadWriteTimeout = socketTimeout; if (uploadHelper.onProgress != null) uploadHelper.onProgress(this, new UploadProgressEventArgs(req.RequestUri.AbsoluteUri, 0)); + currentReq = req; try { - HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); - accResult = resp.StatusCode; - - if (accResult == HttpStatusCode.OK) + using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse()) { - XmlSerializer serializer = new XmlSerializer(typeof(CTDBResponse)); - this.total = 0; - using (Stream responseStream = resp.GetResponseStream()) + this.QueryExceptionStatus = WebExceptionStatus.ProtocolError; + this.QueryResponseStatus = resp.StatusCode; + if (this.QueryResponseStatus == HttpStatusCode.OK) { - CTDBResponse ctdbResp = serializer.Deserialize(responseStream) as CTDBResponse; - if (ctdbResp.entry != null) - foreach (var ctdbRespEntry in ctdbResp.entry) - { - if (ctdbRespEntry.toc == null) - continue; + XmlSerializer serializer = new XmlSerializer(typeof(CTDBResponse)); + this.total = 0; + using (Stream responseStream = resp.GetResponseStream()) + { + CTDBResponse ctdbResp = serializer.Deserialize(responseStream) as CTDBResponse; + if (ctdbResp.entry != null) + foreach (var ctdbRespEntry in ctdbResp.entry) + { + if (ctdbRespEntry.toc == null) + continue; - var parity = Convert.FromBase64String(ctdbRespEntry.parity); - var entry_toc = CDImageLayout.FromString(ctdbRespEntry.toc); - this.total += ctdbRespEntry.confidence; - var entry = new DBEntry( - parity, - 0, - parity.Length, - ctdbRespEntry.confidence, - ctdbRespEntry.npar, - ctdbRespEntry.stride, - uint.Parse(ctdbRespEntry.crc32, NumberStyles.HexNumber), - ctdbRespEntry.id, - entry_toc, - ctdbRespEntry.hasparity); - entries.Add(entry); - } - if (ctdbResp.musicbrainz != null && ctdbResp.musicbrainz.Length != 0) - metadata.AddRange(ctdbResp.musicbrainz); + var parity = Convert.FromBase64String(ctdbRespEntry.parity); + var entry_toc = CDImageLayout.FromString(ctdbRespEntry.toc); + this.total += ctdbRespEntry.confidence; + var entry = new DBEntry( + parity, + 0, + parity.Length, + ctdbRespEntry.confidence, + ctdbRespEntry.npar, + ctdbRespEntry.stride, + uint.Parse(ctdbRespEntry.crc32, NumberStyles.HexNumber), + ctdbRespEntry.id, + entry_toc, + ctdbRespEntry.hasparity); + entries.Add(entry); + } + if (ctdbResp.musicbrainz != null && ctdbResp.musicbrainz.Length != 0) + metadata.AddRange(ctdbResp.musicbrainz); + } + if (entries.Count == 0) + this.QueryResponseStatus = HttpStatusCode.NotFound; + else + this.QueryExceptionStatus = WebExceptionStatus.Success; } - if (entries.Count == 0) - accResult = HttpStatusCode.NotFound; } } catch (WebException ex) { - if (ex.Status == WebExceptionStatus.ProtocolError) - accResult = ((HttpWebResponse)ex.Response).StatusCode; - else - accResult = HttpStatusCode.BadRequest; + this.QueryExceptionStatus = ex.Status; + this.QueryExceptionMessage = ex.Message; + if (this.QueryExceptionStatus == WebExceptionStatus.ProtocolError) + this.QueryResponseStatus = (ex.Response as HttpWebResponse).StatusCode; + } + catch (Exception ex) + { + this.QueryExceptionStatus = WebExceptionStatus.UnknownError; + this.QueryExceptionMessage = ex.Message; + } + finally + { + currentReq = null; } } @@ -116,31 +146,36 @@ namespace CUETools.CTDB req.Method = "GET"; req.Proxy = proxy; req.UserAgent = this.userAgent; + req.Timeout = connectTimeout; + req.ReadWriteTimeout = socketTimeout; + currentReq = req; try { - HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); - entry.httpStatus = resp.StatusCode; - - if (entry.httpStatus == HttpStatusCode.OK) + using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse()) { - using (Stream responseStream = resp.GetResponseStream()) + entry.httpStatus = resp.StatusCode; + + if (entry.httpStatus == HttpStatusCode.OK) { - using(MemoryStream memoryStream = new MemoryStream()) + using (Stream responseStream = resp.GetResponseStream()) { - byte[] buffer = new byte[16536]; - int count = 0, pos = 0; - do + using (MemoryStream memoryStream = new MemoryStream()) { - if (uploadHelper.onProgress != null) - uploadHelper.onProgress(url, new UploadProgressEventArgs(req.RequestUri.AbsoluteUri, ((double)pos) / resp.ContentLength)); - count = responseStream.Read(buffer, 0, buffer.Length); - memoryStream.Write(buffer, 0, count); - pos += count; - } while (count != 0); - var contents = memoryStream.ToArray(); - if (!Parse(contents, entry)) - entry.httpStatus = HttpStatusCode.NoContent; + byte[] buffer = new byte[16536]; + int count = 0, pos = 0; + do + { + if (uploadHelper.onProgress != null) + uploadHelper.onProgress(url, new UploadProgressEventArgs(req.RequestUri.AbsoluteUri, ((double)pos) / resp.ContentLength)); + count = responseStream.Read(buffer, 0, buffer.Length); + memoryStream.Write(buffer, 0, count); + pos += count; + } while (count != 0); + var contents = memoryStream.ToArray(); + if (!Parse(contents, entry)) + entry.httpStatus = HttpStatusCode.NoContent; + } } } } @@ -152,6 +187,10 @@ namespace CUETools.CTDB else entry.httpStatus = HttpStatusCode.BadRequest; } + finally + { + currentReq = null; + } } static string uuidInfo = null; @@ -175,7 +214,8 @@ namespace CUETools.CTDB public string Submit(int confidence, int quality, string artist, string title) { - if (this.AccResult != HttpStatusCode.NotFound && this.AccResult != HttpStatusCode.OK) + if (this.QueryExceptionStatus != WebExceptionStatus.Success && + (this.QueryExceptionStatus != WebExceptionStatus.ProtocolError || this.QueryResponseStatus != HttpStatusCode.NotFound)) return this.DBStatus; DBEntry confirm = null; foreach (DBEntry entry in this.Entries) @@ -220,6 +260,8 @@ namespace CUETools.CTDB HttpWebRequest req = (HttpWebRequest)WebRequest.Create(urlbase + "/submit2.php"); req.Proxy = proxy; req.UserAgent = this.userAgent; + req.Timeout = connectTimeout; + req.ReadWriteTimeout = socketTimeout; NameValueCollection form = new NameValueCollection(); if (upload) form.Add("parityfile", "1"); @@ -240,6 +282,7 @@ namespace CUETools.CTDB var ExceptionStatus = WebExceptionStatus.Pending; string ExceptionMessage = null; HttpStatusCode ResponseStatus = HttpStatusCode.OK; + currentReq = req; try { using (HttpWebResponse resp = uploadHelper.Upload(req, files, form)) @@ -263,6 +306,10 @@ namespace CUETools.CTDB if (ExceptionStatus == WebExceptionStatus.ProtocolError) ResponseStatus = (ex.Response as HttpWebResponse).StatusCode; } + finally + { + currentReq = null; + } subResult = ExceptionStatus == WebExceptionStatus.Success ? null : ExceptionStatus != WebExceptionStatus.ProtocolError ? ("database access error: " + (ExceptionMessage ?? ExceptionStatus.ToString())) : ResponseStatus != HttpStatusCode.NotFound ? "database access error: " + ResponseStatus.ToString() : @@ -333,7 +380,7 @@ namespace CUETools.CTDB public void DoVerify() { - if (this.AccResult != HttpStatusCode.OK) + if (this.QueryExceptionStatus != WebExceptionStatus.Success) return; foreach (DBEntry entry in entries) { @@ -392,11 +439,20 @@ namespace CUETools.CTDB } } - public HttpStatusCode AccResult + public WebExceptionStatus QueryExceptionStatus { get; private set; } + + public string QueryExceptionMessage { get; private set; } + + public HttpStatusCode QueryResponseStatus { get; private set; } + + public string DBStatus { get { - return accResult; + return QueryExceptionStatus == WebExceptionStatus.Success ? null : + QueryExceptionStatus != WebExceptionStatus.ProtocolError ? ("database access error: " + (QueryExceptionMessage ?? QueryExceptionStatus.ToString())) : + QueryResponseStatus != HttpStatusCode.NotFound ? "database access error: " + QueryResponseStatus.ToString() : + "disk not present in database"; } } @@ -420,16 +476,6 @@ namespace CUETools.CTDB } } - public string DBStatus - { - get - { - return accResult == HttpStatusCode.NotFound ? "disk not present in database" : - accResult == HttpStatusCode.OK ? null - : accResult.ToString(); - } - } - public DBEntry SelectedEntry { set diff --git a/CUETools.Processor/Processor.cs b/CUETools.Processor/Processor.cs index a1a7eed..d2d66c9 100644 --- a/CUETools.Processor/Processor.cs +++ b/CUETools.Processor/Processor.cs @@ -6314,13 +6314,14 @@ string status = processor.Go(); return "AccurateRip: confidence too low, will not submit"; //if (CTDB.AccResult == HttpStatusCode.OK) //return "CUEToolsDB: disc already present in database"; - if (CTDB.AccResult != HttpStatusCode.NotFound && CTDB.AccResult != HttpStatusCode.OK)// && CTDB.AccResult != HttpStatusCode.NoContent) + if (CTDB.QueryExceptionStatus != WebExceptionStatus.Success && + (CTDB.QueryExceptionStatus != WebExceptionStatus.ProtocolError || CTDB.QueryResponseStatus != HttpStatusCode.NotFound)) return "CUEToolsDB: " + CTDB.DBStatus; if (_accurateRipId != null && AccurateRipVerify.CalculateAccurateRipId(_toc) != _accurateRipId) return string.Format("CUEToolsDB: Using preserved id {0}, actual id is {1}", _accurateRipId, AccurateRipVerify.CalculateAccurateRipId(_toc)); _useCUEToolsDBSibmit = true; string status = Go(); - if (CTDB.AccResult == HttpStatusCode.OK) + if (CTDB.QueryExceptionStatus == WebExceptionStatus.Success) foreach (DBEntry entry in CTDB.Entries) if (entry.toc.TrackOffsets == _toc.TrackOffsets && !entry.hasErrors) return "CUEToolsDB: " + CTDB.Status;