private void OnSubscribeOrRenewSubscriptionResponseReceived(IAsyncResult ar) { ChangeEventSubscriptionState state = (ChangeEventSubscriptionState)ar.AsyncState; lock (_cpData.SyncObj) _pendingCalls.Remove(state); CpService service = state.Service; try { HttpWebResponse response = (HttpWebResponse)state.Request.EndGetResponse(ar); try { if (response.StatusCode != HttpStatusCode.OK) { service.InvokeEventSubscriptionFailed(new UPnPError((uint)response.StatusCode, response.StatusDescription)); return; } string dateStr = response.Headers.Get("DATE"); string sid = response.Headers.Get("SID"); string timeoutStr = response.Headers.Get("TIMEOUT"); DateTime date = DateTime.ParseExact(dateStr, "R", CultureInfo.InvariantCulture).ToLocalTime(); int timeout; if (string.IsNullOrEmpty(timeoutStr) || (!timeoutStr.StartsWith("Second-") || !int.TryParse(timeoutStr.Substring("Second-".Length).Trim(), out timeout))) { service.InvokeEventSubscriptionFailed(new UPnPError((int)HttpStatusCode.BadRequest, "Invalid answer from UPnP device")); return; } DateTime expiration = date.AddSeconds(timeout); EventSubscription subscription; lock (_cpData.SyncObj) { if (_subscriptions.TryGetValue(sid, out subscription)) { subscription.Expiration = expiration; } else { _subscriptions.Add(sid, new EventSubscription(sid, state.ServiceDescriptor, service, expiration)); } CheckSubscriptionRenewalTimer(_subscriptions.Values); } } finally { response.Close(); } } catch (WebException e) { HttpWebResponse response = (HttpWebResponse)e.Response; service.InvokeEventSubscriptionFailed(new UPnPError(response == null ? 503 : (uint)response.StatusCode, "Cannot complete event subscription")); if (response != null) { response.Close(); } return; } }
private void OnSubscribeOrRenewSubscriptionResponseReceived(IAsyncResult ar) { ChangeEventSubscriptionState state = (ChangeEventSubscriptionState)ar.AsyncState; lock (_cpData.SyncObj) _pendingCalls.Remove(state); CpService service = state.Service; try { HttpWebResponse response = (HttpWebResponse)state.Request.EndGetResponse(ar); try { if (response.StatusCode != HttpStatusCode.OK) { service.InvokeEventSubscriptionFailed(new UPnPError((uint)response.StatusCode, response.StatusDescription)); return; } string dateStr = response.Headers.Get("DATE"); string sid = response.Headers.Get("SID"); string timeoutStr = response.Headers.Get("TIMEOUT"); int timeout; if (string.IsNullOrEmpty(timeoutStr) || (!timeoutStr.StartsWith("Second-") || !int.TryParse(timeoutStr.Substring("Second-".Length).Trim(), out timeout))) { service.InvokeEventSubscriptionFailed(new UPnPError((int)HttpStatusCode.BadRequest, "Invalid answer from UPnP device")); return; } // The date header is not always available, and it is not always accurate either. DateTime date = DateTime.Now; try { date = DateTime.ParseExact(dateStr, "R", CultureInfo.InvariantCulture).ToLocalTime(); } catch { } DateTime expiration = date.AddSeconds(timeout); if (expiration < DateTime.Now) { // If the timeout is in the past already, assume it is invalid and estimate // the timeout timestamp. This workaround is necessary for devices that do // not have their date set correctly (so the DATE header is unusable). expiration = DateTime.Now.AddSeconds(timeout); } EventSubscription subscription; lock (_cpData.SyncObj) { if (_subscriptions.TryGetValue(sid, out subscription)) { subscription.Expiration = expiration; } else { _subscriptions.Add(sid, new EventSubscription(sid, state.ServiceDescriptor, service, expiration)); } CheckSubscriptionRenewalTimer(_subscriptions.Values); } } finally { response.Close(); } } catch (WebException e) { HttpWebResponse response = (HttpWebResponse)e.Response; service.InvokeEventSubscriptionFailed(new UPnPError(response == null ? 503 : (uint)response.StatusCode, "Cannot complete event subscription")); if (response != null) { response.Close(); } } }