private void OnUnsubscribeResponseReceived(IAsyncResult ar) { ChangeEventSubscriptionState state = (ChangeEventSubscriptionState)ar.AsyncState; EventSubscription subscription = FindEventSubscriptionByService(state.Service); try { HttpWebResponse response = (HttpWebResponse)state.Request.EndGetResponse(ar); response.Close(); } catch (WebException e) { if (e.Response != null) { e.Response.Close(); } } lock (_cpData.SyncObj) { _pendingCalls.Remove(state); if (subscription != null) { // As we are asynchronous, the subscription might have gone already (maybe as a result of a duplicate unsubscribe event // or as a result of a disposal of this instance) _subscriptions.Remove(subscription.Sid); CheckSubscriptionRenewalTimer(_subscriptions.Values); } } }
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; } }
internal void UnsubscribeEvents(EventSubscription subscription) { lock (_cpData.SyncObj) { HttpWebRequest request = CreateEventUnsubscribeRequest(subscription); ChangeEventSubscriptionState state = new ChangeEventSubscriptionState(subscription.ServiceDescriptor, subscription.Service, request); _pendingCalls.Add(state); IAsyncResult result = state.Request.BeginGetResponse(OnUnsubscribeResponseReceived, state); NetworkHelper.AddTimeout(request, result, EVENT_UNSUBSCRIPTION_CALL_TIMEOUT * 1000); } }
internal void SubscribeEvents(CpService service, ServiceDescriptor serviceDescriptor) { using (_cpData.Lock.EnterWrite()) { HttpWebRequest request = CreateEventSubscribeRequest(serviceDescriptor); ChangeEventSubscriptionState state = new ChangeEventSubscriptionState(serviceDescriptor, service, request); _pendingCalls.Add(state); IAsyncResult result = state.Request.BeginGetResponse(OnSubscribeOrRenewSubscriptionResponseReceived, state); NetworkHelper.AddTimeout(request, result, EVENT_SUBSCRIPTION_CALL_TIMEOUT * 1000); } }
protected void RenewEventSubscription(EventSubscription subscription) { if (!subscription.Service.IsConnected) { throw new IllegalCallException("Service '{0}' is not connected to a UPnP network service", subscription.Service.FullQualifiedName); } lock (_cpData.SyncObj) { HttpWebRequest request = CreateRenewEventSubscribeRequest(subscription); ChangeEventSubscriptionState state = new ChangeEventSubscriptionState(subscription.ServiceDescriptor, subscription.Service, request); _pendingCalls.Add(state); IAsyncResult result = state.Request.BeginGetResponse(OnSubscribeOrRenewSubscriptionResponseReceived, state); NetworkHelper.AddTimeout(request, result, EVENT_SUBSCRIPTION_CALL_TIMEOUT * 1000); } }
protected void RenewEventSubscription(EventSubscription subscription) { if (!subscription.Service.IsConnected) throw new IllegalCallException("Service '{0}' is not connected to a UPnP network service", subscription.Service.FullQualifiedName); lock (_cpData.SyncObj) { HttpWebRequest request = CreateRenewEventSubscribeRequest(subscription); ChangeEventSubscriptionState state = new ChangeEventSubscriptionState(subscription.ServiceDescriptor, subscription.Service, request); _pendingCalls.Add(state); IAsyncResult result = state.Request.BeginGetResponse(OnSubscribeOrRenewSubscriptionResponseReceived, state); NetworkHelper.AddTimeout(request, result, EVENT_SUBSCRIPTION_CALL_TIMEOUT * 1000); } }
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(); } } }