View Javadoc
1   /*
2    * Copyright (C) 2013 4th Line GmbH, Switzerland
3    *
4    * The contents of this file are subject to the terms of either the GNU
5    * Lesser General Public License Version 2 or later ("LGPL") or the
6    * Common Development and Distribution License Version 1 or later
7    * ("CDDL") (collectively, the "License"). You may not use this file
8    * except in compliance with the License. See LICENSE.txt for more
9    * information.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14   */
15  
16  package org.fourthline.cling.protocol.sync;
17  
18  import org.fourthline.cling.UpnpService;
19  import org.fourthline.cling.model.gena.CancelReason;
20  import org.fourthline.cling.model.gena.RemoteGENASubscription;
21  import org.fourthline.cling.model.message.StreamResponseMessage;
22  import org.fourthline.cling.model.message.gena.IncomingSubscribeResponseMessage;
23  import org.fourthline.cling.model.message.gena.OutgoingRenewalRequestMessage;
24  import org.fourthline.cling.protocol.SendingSync;
25  import org.fourthline.cling.transport.RouterException;
26  
27  import java.util.logging.Logger;
28  
29  /**
30   * Renewing a GENA event subscription with a remote host.
31   * <p>
32   * This protocol is executed periodically by the local registry, for any established GENA
33   * subscription to a remote service. If renewal failed, the subscription will be removed
34   * from the registry and the
35   * {@link org.fourthline.cling.model.gena.RemoteGENASubscription#end(org.fourthline.cling.model.gena.CancelReason, org.fourthline.cling.model.message.UpnpResponse)}
36   * method will be called. The <code>RENEWAL_FAILED</code> reason will be used, however,
37   * the response might be <code>null</code> if no response was received from the remote host.
38   * </p>
39   * @author Christian Bauer
40   */
41  public class SendingRenewal extends SendingSync<OutgoingRenewalRequestMessage, IncomingSubscribeResponseMessage> {
42  
43      final private static Logger log = Logger.getLogger(SendingRenewal.class.getName());
44  
45      final protected RemoteGENASubscription subscription;
46  
47      public SendingRenewal(UpnpService upnpService, RemoteGENASubscription subscription) {
48          super(
49              upnpService,
50              new OutgoingRenewalRequestMessage(
51                  subscription,
52                  upnpService.getConfiguration().getEventSubscriptionHeaders(subscription.getService())
53              )
54          );
55          this.subscription = subscription;
56      }
57  
58      protected IncomingSubscribeResponseMessage executeSync() throws RouterException {
59          log.fine("Sending subscription renewal request: " + getInputMessage());
60  
61          StreamResponseMessage response;
62          try {
63              response = getUpnpService().getRouter().send(getInputMessage());
64          } catch (RouterException ex) {
65              onRenewalFailure();
66              throw ex;
67          }
68  
69          if (response == null) {
70              onRenewalFailure();
71              return null;
72          }
73  
74          final IncomingSubscribeResponseMessage responseMessage = new IncomingSubscribeResponseMessage(response);
75  
76          if (response.getOperation().isFailed()) {
77              log.fine("Subscription renewal failed, response was: " + response);
78              getUpnpService().getRegistry().removeRemoteSubscription(subscription);
79              getUpnpService().getConfiguration().getRegistryListenerExecutor().execute(
80                      new Runnable() {
81                          public void run() {
82                              subscription.end(CancelReason.RENEWAL_FAILED,responseMessage.getOperation());
83                          }
84                      }
85              );
86          } else if (!responseMessage.isValidHeaders()) {
87              log.severe("Subscription renewal failed, invalid or missing (SID, Timeout) response headers");
88              getUpnpService().getConfiguration().getRegistryListenerExecutor().execute(
89                      new Runnable() {
90                          public void run() {
91                              subscription.end(CancelReason.RENEWAL_FAILED, responseMessage.getOperation());
92                          }
93                      }
94              );
95          } else {
96              log.fine("Subscription renewed, updating in registry, response was: " + response);
97              subscription.setActualSubscriptionDurationSeconds(responseMessage.getSubscriptionDurationSeconds());
98              getUpnpService().getRegistry().updateRemoteSubscription(subscription);
99          }
100 
101         return responseMessage;
102     }
103 
104     protected void onRenewalFailure() {
105         log.fine("Subscription renewal failed, removing subscription from registry");
106         getUpnpService().getRegistry().removeRemoteSubscription(subscription);
107         getUpnpService().getConfiguration().getRegistryListenerExecutor().execute(
108                 new Runnable() {
109                     public void run() {
110                         subscription.end(CancelReason.RENEWAL_FAILED, null);
111                     }
112                 }
113         );
114     }
115 }