/// <summary>
        /// Instantiate a one-time use Factory
        /// </summary>
        /// <param name="DescLocation">XML Description Uri</param>
        /// <param name="MaxSeconds">Device Refresh Cycle</param>
        /// <param name="deviceCB">Success Callback</param>
        /// <param name="failedCB">Failure Callback</param>
        public UPnPDeviceFactory(Uri DescLocation, int MaxSeconds, UPnPDeviceHandler deviceCB, UPnPDeviceFailedHandler failedCB, IPAddress localaddr, string usn)
        {
            httprequestor = new HttpRequestor();
            httprequestor.OnRequestCompleted += new HttpRequestor.RequestCompletedHandler(httprequestor_OnRequestCompleted);
            expected_usn = usn;

            CBLock = new object();
            OnDevice += deviceCB;
            OnFailed2 += failedCB;
            DUrl = DescLocation.ToString();
            MaxAge = MaxSeconds;
            this.localaddr = localaddr;
            httprequestor.LaunchRequest(DescLocation.ToString(), null, null, null, null);
        }
        /// <summary>
        /// Instantiate a one-time use Factory
        /// </summary>
        /// <param name="DescLocation">XML Description Uri</param>
        /// <param name="MaxSeconds">Device Refresh Cycle</param>
        /// <param name="deviceCB">Success Callback</param>
        /// <param name="failedCB">Failure Callback</param>
        public UPnPDeviceFactory(Uri DescLocation, int MaxSeconds, UPnPDeviceHandler deviceCB, UPnPDeviceFailedHandler failedCB, IPAddress localaddr, string usn)
        {
            OpenSource.Utilities.InstanceTracker.Add(this);
            httprequestor = new HttpRequestor();
            httprequestor.OnRequestCompleted += new HttpRequestor.RequestCompletedHandler(httprequestor_OnRequestCompleted);
            expected_usn = usn;

            CBLock         = new object();
            OnDevice      += deviceCB;
            OnFailed2     += failedCB;
            DUrl           = DescLocation.ToString();
            MaxAge         = MaxSeconds;
            this.localaddr = localaddr;
            httprequestor.LaunchRequest(DescLocation.ToString(), null, null, null, null);
        }
        /// <summary>
        /// Instantiate a one-time use Factory
        /// </summary>
        /// <param name="DescLocation">XML Description Uri</param>
        /// <param name="MaxSeconds">Device Refresh Cycle</param>
        /// <param name="deviceCB">Success Callback</param>
        /// <param name="failedCB">Failure Callback</param>
        public UPnPDeviceFactory(Uri DescLocation, int MaxSeconds, UPnPDeviceHandler deviceCB, UPnPDeviceFailedHandler failedCB, IPAddress localaddr, string usn)
        {
            OpenSource.Utilities.InstanceTracker.Add(this);
            httprequestor = new HttpRequestor();
            httprequestor.OnRequestCompleted += new HttpRequestor.RequestCompletedHandler(httprequestor_OnRequestCompleted);
            expected_usn = usn;

            CBLock = new object();
            OnDevice += deviceCB;
            OnFailed2 += failedCB;
            DUrl = DescLocation.ToString();
            MaxAge = MaxSeconds;
            this.localaddr = localaddr;
            OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.SuccessAudit, "Fetching Description");
            httprequestor.LaunchRequest(DescLocation.ToString(), null, null, null, null);
        }
        public static void UpdateCheck(Form parent)
        {
            if (requestor != null)
            {
                return;
            }
            if (File.Exists(Application.StartupPath + "\\AutoUpdateTool.exe") == false)
            {
                return;
            }
            if (ReadUpdateSettings() == false)
            {
                return;
            }
            if (AllowAutoUpdate == false)
            {
                return;
            }

            parentform = parent;
            requestor  = new HttpRequestor();
            requestor.OnRequestCompleted += new HttpRequestor.RequestCompletedHandler(requestor_OnRequestCompleted);
            requestor.LaunchProxyRequest(updatelink, null, 1);
        }
        private void httprequestor_OnRequestCompleted(HttpRequestor sender, bool success, object tag, string url, byte[] data)
        {
            try
            {
                Exception fetchException = null;
                if (url == null)
                {
                    OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "HTTP: Url is empty");
                    if (TempDevice != null)
                    {
                        TempDevice = null;
                    }
                    return;
                }

                if (false == tolerateFailures)
                {
                    if (!success)
                    {
                        int checkpoint = 0;
                        try
                        {
                            OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "HTTP: Could not connect to target: " + url);
                            checkpoint = 1;
                            if (OnFailed2 != null)
                            {
                                OnFailed2(this, new Uri(url), new Exception("Could not connect to target"), expected_usn);
                            }
                            checkpoint = 2;
                            if (TempDevice != null)
                            {
                                TempDevice = null;
                            }
                            checkpoint = 3;
                        }
                        catch (Exception ex)
                        {
                            OpenSource.Utilities.EventLogger.Log(ex);
                            ex.Data["v-success"]  = success;
                            ex.Data["v-tag"]      = tag;
                            ex.Data["v-url"]      = url;
                            ex.Data["v-data"]     = data;
                            ex.Data["checkpoint"] = checkpoint;
                            OpenSource.UPnP.AutoUpdate.ReportCrash(System.Windows.Forms.Application.ProductName, ex);
                        }
                        return;
                    }

                    if (data == null)
                    {
                        OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "HTTP: Data is empty");
                        if (OnFailed2 != null)
                        {
                            OnFailed2(this, new Uri(url), new Exception("Data is empty"), expected_usn);
                        }
                        if (TempDevice != null)
                        {
                            TempDevice = null;
                        }
                        return;
                    }
                }
                else
                {
                    if (!success)
                    {
                        fetchException = new Exception("HTTP: Could not connect to target: " + url);
                        OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, fetchException.Message);
                    }
                    else if (data == null)
                    {
                        fetchException = new Exception("HTTP: Data is empty: " + url);
                        OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, fetchException.Message);
                    }
                }

                string html = (data != null) ? UTF8Encoding.UTF8.GetString(data) : "";
                if (tag != null)
                {
                    bool IsOK = false;
                    lock (CBLock)
                    {
                        try
                        {
                            UPnPService service = (UPnPService)tag;
                            if (null == fetchException)
                            {
                                service.ParseSCPD(html, 0);
                            }
                            else
                            {
                                service.ErrorException = fetchException;
                            }
                        }
                        catch (Exception e)
                        {
                            OpenSource.Utilities.EventLogger.Log(e, "Invalid SCPD XML on device:\r\n   Friendly: " + this.TempDevice.FriendlyName +
                                                                 "\r\n   Service: " + ((UPnPService)tag).ServiceURN +
                                                                 "\r\n   URL: " + url +
                                                                 "\r\n   XML:\r\n" + html +
                                                                 "\r\n");
                            if (false == tolerateFailures)
                            {
                                return;
                            }
                        }

                        --ServiceNum;
                        if ((ServiceNum == 0) && (OnDevice != null))
                        {
                            IsOK = true;
                        }
                    }
                    if (IsOK == true)
                    {
                        TempDevice.descXmlLocation = new Uri(url);
                        UPnPDevice device = (null != expected_usn) ? TempDevice.GetDevice(expected_usn) : TempDevice;
                        OnDevice(this, device, new Uri(url));
                        TempDevice = null;
                    }
                    return;
                }

                try
                {
                    if (null == fetchException)
                    {
                        TempDevice = UPnPDevice.Parse(html, new Uri(url), localaddr);
                    }
                    else
                    {
                        TempDevice = new UPnPDevice(fetchException, expected_usn, new Uri(url), localaddr);
                    }
                }
                catch (Exception ex)
                {
                    OpenSource.Utilities.EventLogger.Log(ex, "UPnP Device Description XML parsing exception: URL=" + url);
                    if (false == tolerateFailures)
                    {
                        if (OnFailed2 != null)
                        {
                            OnFailed2(this, new Uri(url), new Exception("UPnP Device Description XML parsing exception: URL=" + url), expected_usn);
                        }
                        if (TempDevice != null)
                        {
                            TempDevice = null;
                        }
                    }
                    return;
                }
                if (TempDevice == null)
                {
                    //OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "Invalid UPnP Device Description: URL=" + url);
                    if (OnFailed2 != null)
                    {
                        OnFailed2(this, new Uri(url), new Exception("Invalid UPnP Device Description XML @" + url), expected_usn);
                    }
                    return;
                }
                if (expected_usn != null && TempDevice.GetDevice(expected_usn) == null)
                {
                    OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, string.Format("Unique ID mismatch between SSDP packet and device description: {0} / {1} ", TempDevice.UniqueDeviceName, expected_usn));
                    if (OnFailed2 != null)
                    {
                        OnFailed2(this, new Uri(url), new Exception(string.Format("Unique ID mismatch between SSDP packet and device description: {0} / {1} ", TempDevice.UniqueDeviceName, expected_usn)), expected_usn);
                    }
                    if (TempDevice != null)
                    {
                        TempDevice = null;
                    }
                    return;
                }
                TempDevice.LocationURL       = url;
                TempDevice.ExpirationTimeout = MaxAge;
                if (TempDevice != null)
                {
                    ServiceNum = FetchServiceCount(TempDevice);
                    if (ServiceNum == 0)
                    {
                        if (OnDevice != null)
                        {
                            OnDevice(this, TempDevice, new Uri(url));
                            TempDevice = null;
                            return;
                        }
                    }
                    FetchServiceDocuments(TempDevice);
                }
            }
            catch (NullReferenceException ex)
            {
                // This happens often, so add data to this exception.
                ex.Data["v-success"] = success;
                ex.Data["v-tag"]     = tag;
                ex.Data["v-url"]     = url;
                ex.Data["v-data"]    = data;
                OpenSource.Utilities.EventLogger.Log(ex);
                OpenSource.UPnP.AutoUpdate.ReportCrash(System.Windows.Forms.Application.ProductName, ex);
            }
        }
        private void httprequestor_OnRequestCompleted(HttpRequestor sender, bool success, object tag, string url, byte[] data)
        {
            try
            {
                if (url == null)
                {
                    OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "HTTP: Url is empty");
                    if (TempDevice != null) TempDevice = null;
                    return;
                }

                if (!success)
                {
                    int checkpoint = 0;
                    try
                    {
                        OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "HTTP: Could not connect to target: " + url);
                        checkpoint = 1;
                        if (OnFailed2 != null) OnFailed2(this, new Uri(url), new Exception("Could not connect to target"), expected_usn);
                        checkpoint = 2;
                        if (TempDevice != null) TempDevice = null;
                        checkpoint = 3;
                    }
                    catch (Exception ex)
                    {
                        OpenSource.Utilities.EventLogger.Log(ex);
                        ex.Data["v-success"] = success;
                        ex.Data["v-tag"] = tag;
                        ex.Data["v-url"] = url;
                        ex.Data["v-data"] = data;
                        ex.Data["checkpoint"] = checkpoint;
                        OpenSource.UPnP.AutoUpdate.ReportCrash(System.Windows.Forms.Application.ProductName, ex);
                    }
                    return;
                }

                if (data == null)
                {
                    OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "HTTP: Data is empty");
                    if (OnFailed2 != null) OnFailed2(this, new Uri(url), new Exception("Data is empty"), expected_usn);
                    if (TempDevice != null) TempDevice = null;
                    return;
                }

                string html = UTF8Encoding.UTF8.GetString(data);
                if (tag != null)
                {
                    bool IsOK = false;
                    lock (CBLock)
                    {
                        try
                        {
                            ((UPnPService)tag).ParseSCPD(html,0);
                        }
                        catch (Exception e)
                        {
                            OpenSource.Utilities.EventLogger.Log(e, "Invalid SCPD XML on device:\r\n   Friendly: " + this.TempDevice.FriendlyName +
                                                                    "\r\n   Service: " + ((UPnPService)tag).ServiceURN +
                                                                    "\r\n   URL: " + url +
                                                                    "\r\n   XML:\r\n" + html +
                                                                    "\r\n");
                            return;
                        }

                        --ServiceNum;
                        if ((ServiceNum == 0) && (OnDevice != null)) IsOK = true;
                    }
                    if (IsOK == true)
                    {
                        TempDevice.descXmlLocation = new Uri(url);
                        OnDevice(this, TempDevice, new Uri(url));
                        TempDevice = null;
                    }
                    return;
                }

                try
                {
                    TempDevice = UPnPDevice.Parse(html, new Uri(url), localaddr);
                }
                catch (Exception ex)
                {
                    OpenSource.Utilities.EventLogger.Log(ex, "UPnP Device Description XML parsing exception: URL=" + url);
                    if (OnFailed2 != null) OnFailed2(this, new Uri(url), new Exception("UPnP Device Description XML parsing exception: URL=" + url), expected_usn);
                    if (TempDevice != null) TempDevice = null;
                    return;
                }
                if (TempDevice == null)
                {
                    //OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "Invalid UPnP Device Description: URL=" + url);
                    if (OnFailed2 != null) OnFailed2(this, new Uri(url), new Exception("Invalid UPnP Device Description XML @" + url), expected_usn);
                    if (TempDevice != null) TempDevice = null;
                    return;
                }
                if (expected_usn != null && TempDevice.UniqueDeviceName != expected_usn)
                {
                    OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, string.Format("Unique ID mismatch between SSDP packet and device description: {0} / {1} ", TempDevice.UniqueDeviceName, expected_usn));
                    if (OnFailed2 != null) OnFailed2(this, new Uri(url), new Exception(string.Format("Unique ID mismatch between SSDP packet and device description: {0} / {1} ", TempDevice.UniqueDeviceName, expected_usn)), expected_usn);
                    if (TempDevice != null) TempDevice = null;
                    return;
                }
                TempDevice.LocationURL = url;
                TempDevice.ExpirationTimeout = MaxAge;
                if (TempDevice != null)
                {
                    ServiceNum = FetchServiceCount(TempDevice);
                    if (ServiceNum == 0)
                    {
                        if (OnDevice != null)
                        {
                            OnDevice(this, TempDevice, new Uri(url));
                            TempDevice = null;
                            return;
                        }
                    }
                    FetchServiceDocuments(TempDevice);
                }
            }
            catch (NullReferenceException ex)
            {
                // This happens often, so add data to this exception.
                ex.Data["v-success"] = success;
                ex.Data["v-tag"] = tag;
                ex.Data["v-url"] = url;
                ex.Data["v-data"] = data;
                OpenSource.Utilities.EventLogger.Log(ex);
                OpenSource.UPnP.AutoUpdate.ReportCrash(System.Windows.Forms.Application.ProductName, ex);
            }
        }
        private void httprequestor_OnRequestCompleted(HttpRequestor sender, bool success, object tag, string url, byte[] data)
        {
            if (!success)
            {
                OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "HTTP: Could not connect to target: " + url);
                OnFailed2(this, new Uri(DUrl), new Exception("Could not connect to target"), expected_usn);
                if (TempDevice != null) TempDevice = null;
                return;
            }

            if (data == null)
            {
                OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "HTTP: Data is empty");
                OnFailed2(this, new Uri(DUrl), new Exception("Data is empty"), expected_usn);
                if (TempDevice != null) TempDevice = null;
                return;
            }

            if (url == null)
            {
                OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "HTTP: Url is empty");
                OnFailed2(this, new Uri(DUrl), new Exception("Url is empty"), expected_usn);
                if (TempDevice != null) TempDevice = null;
                return;
            }

            string html = UTF8Encoding.UTF8.GetString(data);
            if (tag != null)
            {
                bool IsOK = false;
                lock (CBLock)
                {
                    try
                    {
                        ((UPnPService)tag).ParseSCPD(html);
                    }
                    catch (Exception e)
                    {
                        OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "Invalid SCPD XML on device:\r\n   Friendly: " + this.TempDevice.FriendlyName + "\r\n   Service: " + ((UPnPService)tag).ServiceURN + "\r\n   @" + TempDevice.LocationURL);
                        OpenSource.Utilities.EventLogger.Log(e);
                        return;
                    }

                    --ServiceNum;
                    if ((ServiceNum == 0) && (OnDevice != null)) IsOK = true;
                }
                if (IsOK == true)
                {
                    TempDevice.descXmlLocation = new Uri(DUrl);
                    OnDevice(this, TempDevice, new Uri(DUrl));
                    TempDevice = null;
                }
                return;
            }

            try
            {
                TempDevice = UPnPDevice.Parse(html, new Uri(DUrl), localaddr);
            }
            catch (Exception)
            {
                OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "Invalid Device Description XML @" + DUrl);
                OnFailed2(this, new Uri(DUrl), new Exception("Invalid Device Description XML @" + DUrl), expected_usn);
                if (TempDevice != null) TempDevice = null;
                return;
            }
            if (TempDevice == null)
            {
                OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "Invalid Device Description XML @" + DUrl);
                OnFailed2(this, new Uri(DUrl), new Exception("Invalid Device Description XML @" + DUrl), expected_usn);
                if (TempDevice != null) TempDevice = null;
                return;
            }
            if (expected_usn != null && TempDevice.UniqueDeviceName != expected_usn)
            {
                OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, string.Format("Unique ID mismatch between SSDP packet and device description: {0} / {1} ", TempDevice.UniqueDeviceName, expected_usn));
                OnFailed2(this, new Uri(DUrl), new Exception(string.Format("Unique ID mismatch between SSDP packet and device description: {0} / {1} ", TempDevice.UniqueDeviceName, expected_usn)), expected_usn);
                if (TempDevice != null) TempDevice = null;
                return;
            }
            TempDevice.LocationURL = DUrl;
            TempDevice.ExpirationTimeout = MaxAge;
            if (TempDevice != null)
            {
                ServiceNum = FetchServiceCount(TempDevice);
                if (ServiceNum == 0)
                {
                    if (OnDevice != null)
                    {
                        OnDevice(this, TempDevice, new Uri(DUrl));
                        TempDevice = null;
                        return;
                    }
                }
                FetchServiceDocuments(TempDevice);
            }
        }
Ejemplo n.º 8
0
        private static void requestor_OnRequestCompleted(HttpRequestor sender, bool success, object tag, string url, byte[] data)
        {
            if (success == true)
            {
                // Fetch version information
                int newversion = 0;
                string updatelink = null;
                try
                {
                    string page = UTF8Encoding.UTF8.GetString(data);
                    string x = "##" + updatecode.ToString() + "##";
                    x = x.ToUpper();
                    int i = page.IndexOf(x);
                    if (i == -1)
                    {
                        requestor.OnRequestCompleted += new HttpRequestor.RequestCompletedHandler(requestor_OnRequestCompleted);
                        requestor = null;
                        return;
                    }
                    page = page.Substring(i + x.Length);
                    i = page.IndexOf("##");
                    if (i == -1)
                    {
                        requestor.OnRequestCompleted += new HttpRequestor.RequestCompletedHandler(requestor_OnRequestCompleted);
                        requestor = null;
                        return;
                    }
                    string versionstr = page.Substring(0, i);
                    newversion = int.Parse(versionstr);
                    page = page.Substring(i + 2);
                    i = page.IndexOf("##");
                    if (i == -1)
                    {
                        requestor.OnRequestCompleted += new HttpRequestor.RequestCompletedHandler(requestor_OnRequestCompleted);
                        requestor = null;
                        return;
                    }
                    updatelink = page.Substring(0, i);
                }
                catch (Exception ex)
                {
                    OpenSource.Utilities.EventLogger.Log(ex);
                    requestor.OnRequestCompleted += new HttpRequestor.RequestCompletedHandler(requestor_OnRequestCompleted);
                    requestor = null;
                    return;
                }

                // Compare to existing version
                if (existingversion < newversion)
                {
                    updateform = new AutoUpdate(newversion);
                    parentform.Invoke(new System.Threading.ThreadStart(ShowUpdateForm));
                }
            }
            requestor.OnRequestCompleted += new HttpRequestor.RequestCompletedHandler(requestor_OnRequestCompleted);
            requestor = null;
        }
Ejemplo n.º 9
0
        public static void UpdateCheck(Form parent)
        {
            if (requestor != null) return;
            if (File.Exists(Application.StartupPath + "\\AutoUpdateTool.exe") == false) return;
            if (ReadUpdateSettings() == false) return;
            if (AllowAutoUpdate == false) return;

            parentform = parent;
            requestor = new HttpRequestor();
            requestor.OnRequestCompleted += new HttpRequestor.RequestCompletedHandler(requestor_OnRequestCompleted);
            requestor.LaunchProxyRequest(updatelink, null, 1);
        }
Ejemplo n.º 10
0
 void HandleIcon(HttpRequestor sender, bool success, object tag, string url, byte[] data)
 {
     InitialEventTable.Remove(sender);
     if (success)
     {
         System.Drawing.Image i = System.Drawing.Image.FromStream(new MemoryStream(data));
         if (i != null) _icon = i;
     }
 }
Ejemplo n.º 11
0
 internal void FetchIcon(Uri IconUri)
 {
     HttpRequestor httprequestor = new HttpRequestor();
     httprequestor.OnRequestCompleted += new HttpRequestor.RequestCompletedHandler(HandleIcon);
     httprequestor.LaunchRequest(IconUri.ToString(), null, null, null, null);
     InitialEventTable[httprequestor] = httprequestor;
 }
Ejemplo n.º 12
0
        private void httprequestor_OnRequestCompleted(HttpRequestor sender, bool success, object tag, string url, byte[] data)
        {
            try
            {
                if (url == null)
                {
                    OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "HTTP: Url is empty");
                    if (TempDevice != null)
                    {
                        TempDevice = null;
                    }
                    return;
                }

                if (!success)
                {
                    int checkpoint = 0;
                    try
                    {
                        OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "HTTP: Could not connect to target: " + url);
                        checkpoint = 1;
                        if (OnFailed2 != null)
                        {
                            OnFailed2(this, new Uri(url), new Exception("Could not connect to target"), expected_usn);
                        }
                        checkpoint = 2;
                        if (TempDevice != null)
                        {
                            TempDevice = null;
                        }
                        checkpoint = 3;
                    }
                    catch (Exception ex)
                    {
                        ex.Data["v-success"]  = success;
                        ex.Data["v-tag"]      = tag;
                        ex.Data["v-url"]      = url;
                        ex.Data["v-data"]     = data;
                        ex.Data["checkpoint"] = checkpoint;
                        OpenSource.UPnP.AutoUpdate.ReportCrash(System.Windows.Forms.Application.ProductName, ex);
                    }
                    return;
                }

                if (data == null)
                {
                    OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "HTTP: Data is empty");
                    if (OnFailed2 != null)
                    {
                        OnFailed2(this, new Uri(url), new Exception("Data is empty"), expected_usn);
                    }
                    if (TempDevice != null)
                    {
                        TempDevice = null;
                    }
                    return;
                }

                string html = UTF8Encoding.UTF8.GetString(data);
                if (tag != null)
                {
                    bool IsOK = false;
                    lock (CBLock)
                    {
                        try
                        {
                            ((UPnPService)tag).ParseSCPD(html);
                        }
                        catch (Exception e)
                        {
                            OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "Invalid SCPD XML on device:\r\n   Friendly: " + this.TempDevice.FriendlyName + "\r\n   Service: " + ((UPnPService)tag).ServiceURN + "\r\n   @" + TempDevice.LocationURL);
                            OpenSource.Utilities.EventLogger.Log(e);
                            // TODO: DONE Resilience case 5b - remove the faulty service from owning device, with a log message
                            ((UPnPService)tag).ParentDevice.RemoveService((UPnPService)tag);
                            OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Warning, "Dropping failed SCPD and the accompanying service from its parent device. Commencing parsing remainder of device");
                            //return;   disabled, must continue parsing after logging error
                        }

                        --ServiceNum;
                        if ((ServiceNum == 0) && (OnDevice != null))
                        {
                            IsOK = true;
                        }
                    }
                    if (IsOK == true)
                    {
                        TempDevice.descXmlLocation = new Uri(url);
                        OnDevice(this, TempDevice, new Uri(url));
                        TempDevice = null;
                    }
                    return;
                }

                try
                {
                    TempDevice = UPnPDevice.Parse(html, new Uri(url), localaddr);
                }
                catch (Exception)
                {
                    OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "Invalid Device Description XML @" + url);
                    // TODO: DONE Resilience case 7 - if root device fails, no change, keep failing.
                    // when exceptions on elements are caught, then the device will still be created, yet incomplete as it is constructed
                    // without the failed elements.
                    // TODO: should the OnFailed handler then still be called? Would it break something if it doesn't?
                    if (OnFailed2 != null)
                    {
                        OnFailed2(this, new Uri(url), new Exception("Invalid Device Description XML @" + url), expected_usn);
                    }
                    if (TempDevice != null)
                    {
                        TempDevice = null;
                    }
                    return;
                }
                if (TempDevice == null)
                {
                    OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "Invalid Device Description XML @" + url);
                    if (OnFailed2 != null)
                    {
                        OnFailed2(this, new Uri(url), new Exception("Invalid Device Description XML @" + url), expected_usn);
                    }
                    if (TempDevice != null)
                    {
                        TempDevice = null;
                    }
                    return;
                }
                if (expected_usn != null && TempDevice.UniqueDeviceName != expected_usn)
                {
                    OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, string.Format("Unique ID mismatch between SSDP packet and device description: {0} / {1} ", TempDevice.UniqueDeviceName, expected_usn));
                    if (OnFailed2 != null)
                    {
                        OnFailed2(this, new Uri(url), new Exception(string.Format("Unique ID mismatch between SSDP packet and device description: {0} / {1} ", TempDevice.UniqueDeviceName, expected_usn)), expected_usn);
                    }
                    if (TempDevice != null)
                    {
                        TempDevice = null;
                    }
                    return;
                }
                TempDevice.LocationURL       = url;
                TempDevice.ExpirationTimeout = MaxAge;
                if (TempDevice != null)
                {
                    ServiceNum = FetchServiceCount(TempDevice);
                    if (ServiceNum == 0)
                    {
                        // no service descriptions to wait for, we are complete. fire event is available
                        if (OnDevice != null)
                        {
                            OnDevice(this, TempDevice, new Uri(url));
                            TempDevice = null;
                            return;
                        }
                    }
                    FetchServiceDocuments(TempDevice);
                }
            }
            catch (NullReferenceException ex)
            {
                // This happens often, so add data to this exception.
                ex.Data["v-success"] = success;
                ex.Data["v-tag"]     = tag;
                ex.Data["v-url"]     = url;
                ex.Data["v-data"]    = data;
                OpenSource.UPnP.AutoUpdate.ReportCrash(System.Windows.Forms.Application.ProductName, ex);
            }
        }
        private void httprequestor_OnRequestCompleted(HttpRequestor sender, bool success, object tag, string url, byte[] data)
        {
            try
            {
                if (url == null)
                {
                    OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "HTTP: Url is empty");
                    if (TempDevice != null) TempDevice = null;
                    return;
                }

                if (!success)
                {
                    int checkpoint = 0;
                    try
                    {
                        OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "HTTP: Could not connect to target: " + url);
                        checkpoint = 1;
                        if (OnFailed2 != null) OnFailed2(this, new Uri(url), new Exception("Could not connect to target"), expected_usn);
                        checkpoint = 2;
                        if (TempDevice != null) TempDevice = null;
                        checkpoint = 3;
                    }
                    catch (Exception ex)
                    {
                        ex.Data["v-success"] = success;
                        ex.Data["v-tag"] = tag;
                        ex.Data["v-url"] = url;
                        ex.Data["v-data"] = data;
                        ex.Data["checkpoint"] = checkpoint;
                        OpenSource.UPnP.AutoUpdate.ReportCrash(System.Windows.Forms.Application.ProductName, ex);
                    }
                    return;
                }

                if (data == null)
                {
                    OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "HTTP: Data is empty");
                    if (OnFailed2 != null) OnFailed2(this, new Uri(url), new Exception("Data is empty"), expected_usn);
                    if (TempDevice != null) TempDevice = null;
                    return;
                }

                string html = UTF8Encoding.UTF8.GetString(data);
                if (tag != null)
                {
                    bool IsOK = false;
                    lock (CBLock)
                    {
                        try
                        {
                            ((UPnPService)tag).ParseSCPD(html);
                        }
                        catch (Exception e)
                        {
                            OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "Invalid SCPD XML on device:\r\n   Friendly: " + this.TempDevice.FriendlyName + "\r\n   Service: " + ((UPnPService)tag).ServiceURN + "\r\n   @" + TempDevice.LocationURL);
                            OpenSource.Utilities.EventLogger.Log(e);
                            // TODO: DONE Resilience case 5b - remove the faulty service from owning device, with a log message
                            ((UPnPService)tag).ParentDevice.RemoveService((UPnPService)tag);
                            OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Warning, "Dropping failed SCPD and the accompanying service from its parent device. Commencing parsing remainder of device");
                            //return;   disabled, must continue parsing after logging error
                        }

                        --ServiceNum;
                        if ((ServiceNum == 0) && (OnDevice != null)) IsOK = true;
                    }
                    if (IsOK == true)
                    {
                        TempDevice.descXmlLocation = new Uri(url);
                        OnDevice(this, TempDevice, new Uri(url));
                        TempDevice = null;
                    }
                    return;
                }

                try
                {
                    TempDevice = UPnPDevice.Parse(html, new Uri(url), localaddr);
                }
                catch (Exception)
                {
                    OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "Invalid Device Description XML @" + url);
                    // TODO: DONE Resilience case 7 - if root device fails, no change, keep failing.
                    // when exceptions on elements are caught, then the device will still be created, yet incomplete as it is constructed
                    // without the failed elements.
                    // TODO: should the OnFailed handler then still be called? Would it break something if it doesn't?
                    if (OnFailed2 != null) OnFailed2(this, new Uri(url), new Exception("Invalid Device Description XML @" + url), expected_usn);
                    if (TempDevice != null) TempDevice = null;
                    return;
                }
                if (TempDevice == null)
                {
                    OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "Invalid Device Description XML @" + url);
                    if (OnFailed2 != null) OnFailed2(this, new Uri(url), new Exception("Invalid Device Description XML @" + url), expected_usn);
                    if (TempDevice != null) TempDevice = null;
                    return;
                }
                if (expected_usn != null && TempDevice.UniqueDeviceName != expected_usn)
                {
                    OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, string.Format("Unique ID mismatch between SSDP packet and device description: {0} / {1} ", TempDevice.UniqueDeviceName, expected_usn));
                    if (OnFailed2 != null) OnFailed2(this, new Uri(url), new Exception(string.Format("Unique ID mismatch between SSDP packet and device description: {0} / {1} ", TempDevice.UniqueDeviceName, expected_usn)), expected_usn);
                    if (TempDevice != null) TempDevice = null;
                    return;
                }
                TempDevice.LocationURL = url;
                TempDevice.ExpirationTimeout = MaxAge;
                if (TempDevice != null)
                {
                    ServiceNum = FetchServiceCount(TempDevice);
                    if (ServiceNum == 0)
                    {
                        // no service descriptions to wait for, we are complete. fire event is available
                        if (OnDevice != null)
                        {
                            OnDevice(this, TempDevice, new Uri(url));
                            TempDevice = null;
                            return;
                        }
                    }
                    FetchServiceDocuments(TempDevice);
                }
            }
            catch (NullReferenceException ex)
            {
                // This happens often, so add data to this exception.
                ex.Data["v-success"] = success;
                ex.Data["v-tag"] = tag;
                ex.Data["v-url"] = url;
                ex.Data["v-data"] = data;
                OpenSource.UPnP.AutoUpdate.ReportCrash(System.Windows.Forms.Application.ProductName, ex);
            }
        }