]> git.basschouten.com Git - openhab-addons.git/blob
a95737f14fba4cd49bfa6372eb1740137320d59c
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.magentatv.internal.network;
14
15 import static org.openhab.binding.magentatv.internal.MagentaTVBindingConstants.*;
16 import static org.openhab.binding.magentatv.internal.MagentaTVUtil.substringBetween;
17
18 import java.io.IOException;
19 import java.util.Map;
20 import java.util.Scanner;
21
22 import javax.servlet.ServletException;
23 import javax.servlet.http.HttpServlet;
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26
27 import org.eclipse.jdt.annotation.NonNullByDefault;
28 import org.eclipse.jdt.annotation.Nullable;
29 import org.openhab.binding.magentatv.internal.MagentaTVHandlerFactory;
30 import org.osgi.service.component.annotations.Activate;
31 import org.osgi.service.component.annotations.Component;
32 import org.osgi.service.component.annotations.ConfigurationPolicy;
33 import org.osgi.service.component.annotations.Reference;
34 import org.osgi.service.http.HttpService;
35 import org.osgi.service.http.NamespaceException;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * Main OSGi service and HTTP servlet for MagentaTV NOTIFY.
41  *
42  * @author Markus Michels - Initial contribution
43  */
44 @NonNullByDefault
45 @Component(service = HttpServlet.class, configurationPolicy = ConfigurationPolicy.OPTIONAL)
46 public class MagentaTVNotifyServlet extends HttpServlet {
47     private static final long serialVersionUID = 2119809008606371618L;
48     private final Logger logger = LoggerFactory.getLogger(MagentaTVNotifyServlet.class);
49
50     private final MagentaTVHandlerFactory handlerFactory;
51
52     @Activate
53     public MagentaTVNotifyServlet(@Reference MagentaTVHandlerFactory handlerFactory, @Reference HttpService httpService,
54             Map<String, Object> config) {
55         this.handlerFactory = handlerFactory;
56         try {
57             httpService.registerServlet(PAIRING_NOTIFY_URI, this, null, httpService.createDefaultHttpContext());
58             logger.debug("Servlet started at {}", PAIRING_NOTIFY_URI);
59             if (!handlerFactory.getNotifyServletStatus()) {
60                 handlerFactory.setNotifyServletStatus(true);
61             }
62         } catch (ServletException | NamespaceException e) {
63             logger.warn("Could not start MagentaTVNotifyServlet: {}", e.getMessage());
64         }
65     }
66
67     /**
68      * Notify servlet handler (will be called by jetty
69      *
70      * Format of SOAP message:
71      * <e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0"> <e:property>
72      * <uniqueDeviceID>1C18548DAF7DE9BC231249DB28D2A650</uniqueDeviceID>
73      * </e:property> <e:property> <messageBody>X-pairingCheck:5218C0AA</messageBody>
74      * </e:property> </e:propertyset>
75      *
76      * Format of event message: <?xml version="1.0"?>
77      * <e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0"> <e:property>
78      * <STB_Mac>AC6FBB61B1E5</STB_Mac> </e:property> <e:property>
79      * <STB_playContent>{&quot;new_play_mode&quot;:0,&quot;playBackState&quot;:1,&
80      * quot;mediaType&quot;:1,&quot;mediaCode&quot;:&quot;3682&quot;}</
81      * STB_playContent> </e:property> </e:propertyset>
82      *
83      * @param request
84      * @param resp
85      *
86      * @throws ServletException, IOException
87      */
88     @Override
89     protected void service(@Nullable HttpServletRequest request, @Nullable HttpServletResponse response)
90             throws ServletException, IOException {
91
92         String data = inputStreamToString(request);
93         try {
94             if ((request == null) || (response == null)) {
95                 return;
96             }
97             String ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR");
98             if (ipAddress == null) {
99                 ipAddress = request.getRemoteAddr();
100             }
101             String path = request.getRequestURI();
102             logger.trace("Reqeust from {}:{}{} ({}, {})", ipAddress, request.getRemotePort(), path,
103                     request.getRemoteHost(), request.getProtocol());
104             if (!path.equalsIgnoreCase(PAIRING_NOTIFY_URI)) {
105                 logger.debug("Invalid request received - path = {}", path);
106                 return;
107             }
108
109             if (data.contains(NOTIFY_PAIRING_CODE)) {
110                 String deviceId = data.substring(data.indexOf("<uniqueDeviceID>") + "<uniqueDeviceID>".length(),
111                         data.indexOf("</uniqueDeviceID>"));
112                 String pairingCode = data.substring(data.indexOf(NOTIFY_PAIRING_CODE) + NOTIFY_PAIRING_CODE.length(),
113                         data.indexOf("</messageBody>"));
114                 logger.debug("Pairing code {} received for deviceID {}", pairingCode, deviceId);
115                 if (!handlerFactory.notifyPairingResult(deviceId, ipAddress, pairingCode)) {
116                     logger.trace("Pairing data={}", data);
117                 }
118             } else {
119                 if (data.contains("STB_")) {
120                     data = data.replaceAll("&quot;", "\"");
121                     String stbMac = substringBetween(data, "<STB_Mac>", "</STB_Mac>");
122                     String stbEvent = "";
123                     if (data.contains("<STB_playContent>")) {
124                         stbEvent = substringBetween(data, "<STB_playContent>", "</STB_playContent>");
125                     } else if (data.contains("<STB_EitChanged>")) {
126                         stbEvent = substringBetween(data, "<STB_EitChanged>", "</STB_EitChanged>");
127                     } else {
128                         logger.debug("Unknown STB event: {}", data);
129                     }
130                     if (!stbEvent.isEmpty()) {
131                         if (!handlerFactory.notifyMREvent(stbMac, stbEvent)) {
132                             logger.debug("Event not processed, data={}", data);
133                         }
134                     }
135                 }
136             }
137         } catch (RuntimeException e) {
138             logger.debug("Unable to process http request, data={}", data != null ? data : "<empty>");
139         } finally {
140             // send response
141             if (response != null) {
142                 response.setCharacterEncoding(UTF_8);
143                 response.getWriter().write("");
144             }
145         }
146     }
147
148     @SuppressWarnings("resource")
149     private String inputStreamToString(@Nullable HttpServletRequest request) throws IOException {
150         if (request == null) {
151             return "";
152         }
153         Scanner scanner = new Scanner(request.getInputStream()).useDelimiter("\\A");
154         return scanner.hasNext() ? scanner.next() : "";
155     }
156 }