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.test.ssdp;
17  
18  import org.fourthline.cling.UpnpService;
19  import org.fourthline.cling.model.Constants;
20  import org.fourthline.cling.model.DiscoveryOptions;
21  import org.fourthline.cling.model.Namespace;
22  import org.fourthline.cling.model.message.IncomingDatagramMessage;
23  import org.fourthline.cling.model.message.OutgoingDatagramMessage;
24  import org.fourthline.cling.model.message.UpnpMessage;
25  import org.fourthline.cling.model.message.UpnpRequest;
26  import org.fourthline.cling.model.message.discovery.IncomingSearchRequest;
27  import org.fourthline.cling.model.message.header.DeviceTypeHeader;
28  import org.fourthline.cling.model.message.header.DeviceUSNHeader;
29  import org.fourthline.cling.model.message.header.EXTHeader;
30  import org.fourthline.cling.model.message.header.HostHeader;
31  import org.fourthline.cling.model.message.header.MANHeader;
32  import org.fourthline.cling.model.message.header.MXHeader;
33  import org.fourthline.cling.model.message.header.MaxAgeHeader;
34  import org.fourthline.cling.model.message.header.RootDeviceHeader;
35  import org.fourthline.cling.model.message.header.STAllHeader;
36  import org.fourthline.cling.model.message.header.ServiceTypeHeader;
37  import org.fourthline.cling.model.message.header.ServiceUSNHeader;
38  import org.fourthline.cling.model.message.header.UDNHeader;
39  import org.fourthline.cling.model.message.header.USNRootDeviceHeader;
40  import org.fourthline.cling.model.message.header.UpnpHeader;
41  import org.fourthline.cling.model.meta.LocalDevice;
42  import org.fourthline.cling.model.meta.Service;
43  import org.fourthline.cling.model.types.NotificationSubtype;
44  import org.fourthline.cling.protocol.async.ReceivingSearch;
45  import org.fourthline.cling.mock.MockUpnpService;
46  import org.fourthline.cling.test.data.SampleData;
47  import org.fourthline.cling.test.data.SampleUSNHeaders;
48  import org.seamless.util.URIUtil;
49  import org.testng.annotations.Test;
50  
51  import java.net.InetAddress;
52  import java.net.UnknownHostException;
53  
54  import static org.testng.Assert.*;
55  
56  public class SearchReceivedTest {
57  
58      @Test
59      public void receivedSearchAll() throws Exception {
60  
61          MockUpnpService upnpService = new MockUpnpService();
62  
63          LocalDevice localDevice = SampleData.createLocalDevice();
64          LocalDevice embeddedDevice = localDevice.getEmbeddedDevices()[0];
65          upnpService.getRegistry().addDevice(localDevice);
66  
67          IncomingSearchRequest searchMsg = createRequestMessage();
68          searchMsg.getHeaders().add(UpnpHeader.Type.MAN, new MANHeader(NotificationSubtype.DISCOVER.getHeaderString()));
69          searchMsg.getHeaders().add(UpnpHeader.Type.MX, new MXHeader(1));
70          searchMsg.getHeaders().add(UpnpHeader.Type.ST, new STAllHeader());
71          searchMsg.getHeaders().add(UpnpHeader.Type.HOST, new HostHeader());
72  
73          ReceivingSearch prot = createProtocol(upnpService, searchMsg);
74          prot.run();
75  
76          assertEquals(upnpService.getRouter().getOutgoingDatagramMessages().size(), 10);
77  
78          for (OutgoingDatagramMessage msg : upnpService.getRouter().getOutgoingDatagramMessages()) {
79              //SampleData.debugMsg(msg);
80              assertSearchResponseBasics(upnpService.getConfiguration().getNamespace(), msg, localDevice);
81          }
82  
83          SampleUSNHeaders.assertUSNHeaders(upnpService.getRouter().getOutgoingDatagramMessages(), localDevice, embeddedDevice, UpnpHeader.Type.ST);
84      }
85  
86      @Test
87      public void receivedSearchRoot() throws Exception {
88  
89          MockUpnpService upnpService = new MockUpnpService();
90  
91          LocalDevice localDevice = SampleData.createLocalDevice();
92          upnpService.getRegistry().addDevice(localDevice);
93  
94          IncomingSearchRequest searchMsg = createRequestMessage();
95          searchMsg.getHeaders().add(UpnpHeader.Type.MAN, new MANHeader(NotificationSubtype.DISCOVER.getHeaderString()));
96          searchMsg.getHeaders().add(UpnpHeader.Type.MX, new MXHeader(1));
97          searchMsg.getHeaders().add(UpnpHeader.Type.ST, new RootDeviceHeader());
98          searchMsg.getHeaders().add(UpnpHeader.Type.HOST, new HostHeader());
99  
100         ReceivingSearch prot = createProtocol(upnpService, searchMsg);
101         prot.run();
102 
103         assertEquals(upnpService.getRouter().getOutgoingDatagramMessages().size(), 1);
104 
105         assertSearchResponseBasics(
106             upnpService.getConfiguration().getNamespace(),
107             upnpService.getRouter().getOutgoingDatagramMessages().get(0),
108             localDevice
109         );
110         assertEquals(
111                 upnpService.getRouter().getOutgoingDatagramMessages().get(0).getHeaders().getFirstHeader(UpnpHeader.Type.ST).getString(),
112                 new RootDeviceHeader().getString()
113         );
114         assertEquals(
115                 upnpService.getRouter().getOutgoingDatagramMessages().get(0).getHeaders().getFirstHeader(UpnpHeader.Type.USN).getString(),
116                 localDevice.getIdentity().getUdn().toString() + USNRootDeviceHeader.ROOT_DEVICE_SUFFIX
117         );
118     }
119 
120     @Test
121     public void receivedSearchUDN() throws Exception {
122 
123         MockUpnpService upnpService = new MockUpnpService();
124 
125         LocalDevice localDevice = SampleData.createLocalDevice();
126         upnpService.getRegistry().addDevice(localDevice);
127 
128         IncomingSearchRequest searchMsg = createRequestMessage();
129         searchMsg.getHeaders().add(UpnpHeader.Type.MAN, new MANHeader(NotificationSubtype.DISCOVER.getHeaderString()));
130         searchMsg.getHeaders().add(UpnpHeader.Type.MX, new MXHeader(1));
131         searchMsg.getHeaders().add(UpnpHeader.Type.ST, new UDNHeader(localDevice.getIdentity().getUdn()));
132         searchMsg.getHeaders().add(UpnpHeader.Type.HOST, new HostHeader());
133 
134         ReceivingSearch prot = createProtocol(upnpService, searchMsg);
135         prot.run();
136 
137         assertEquals(upnpService.getRouter().getOutgoingDatagramMessages().size(), 1);
138 
139         assertSearchResponseBasics(
140                 upnpService.getConfiguration().getNamespace(),
141                 upnpService.getRouter().getOutgoingDatagramMessages().get(0),
142                 localDevice
143         );
144         assertEquals(
145                 upnpService.getRouter().getOutgoingDatagramMessages().get(0).getHeaders().getFirstHeader(UpnpHeader.Type.ST).getString(),
146                 new UDNHeader(localDevice.getIdentity().getUdn()).getString()
147         );
148         assertEquals(
149                 upnpService.getRouter().getOutgoingDatagramMessages().get(0).getHeaders().getFirstHeader(UpnpHeader.Type.USN).getString(),
150                 new UDNHeader(localDevice.getIdentity().getUdn()).getString()
151         );
152     }
153 
154     @Test
155     public void receivedSearchDeviceType() throws Exception {
156 
157         MockUpnpService upnpService = new MockUpnpService();
158 
159         LocalDevice localDevice = SampleData.createLocalDevice();
160         upnpService.getRegistry().addDevice(localDevice);
161 
162         IncomingSearchRequest searchMsg = createRequestMessage();
163         searchMsg.getHeaders().add(UpnpHeader.Type.MAN, new MANHeader(NotificationSubtype.DISCOVER.getHeaderString()));
164         searchMsg.getHeaders().add(UpnpHeader.Type.MX, new MXHeader(1));
165         searchMsg.getHeaders().add(UpnpHeader.Type.ST, new DeviceTypeHeader(localDevice.getType()));
166         searchMsg.getHeaders().add(UpnpHeader.Type.HOST, new HostHeader());
167 
168         ReceivingSearch prot = createProtocol(upnpService, searchMsg);
169         prot.run();
170 
171         assertEquals(upnpService.getRouter().getOutgoingDatagramMessages().size(), 1);
172 
173         assertSearchResponseBasics(
174                 upnpService.getConfiguration().getNamespace(),
175                 upnpService.getRouter().getOutgoingDatagramMessages().get(0),
176                 localDevice
177         );
178         assertEquals(
179                 upnpService.getRouter().getOutgoingDatagramMessages().get(0).getHeaders().getFirstHeader(UpnpHeader.Type.ST).getString(),
180                 new DeviceTypeHeader(localDevice.getType()).getString()
181         );
182         assertEquals(
183                 upnpService.getRouter().getOutgoingDatagramMessages().get(0).getHeaders().getFirstHeader(UpnpHeader.Type.USN).getString(),
184                 new DeviceUSNHeader(localDevice.getIdentity().getUdn(), localDevice.getType()).getString()
185         );
186     }
187 
188     @Test
189     public void receivedSearchServiceType() throws Exception {
190 
191         MockUpnpService upnpService = new MockUpnpService();
192 
193         LocalDevice localDevice = SampleData.createLocalDevice();
194         Service service = localDevice.getServices()[0];
195         upnpService.getRegistry().addDevice(localDevice);
196 
197         IncomingSearchRequest searchMsg = createRequestMessage();
198         searchMsg.getHeaders().add(UpnpHeader.Type.MAN, new MANHeader(NotificationSubtype.DISCOVER.getHeaderString()));
199         searchMsg.getHeaders().add(UpnpHeader.Type.MX, new MXHeader(1));
200         searchMsg.getHeaders().add(UpnpHeader.Type.ST, new ServiceTypeHeader(service.getServiceType()));
201         searchMsg.getHeaders().add(UpnpHeader.Type.HOST, new HostHeader());
202 
203         ReceivingSearch prot = createProtocol(upnpService, searchMsg);
204         prot.run();
205 
206         assertEquals(upnpService.getRouter().getOutgoingDatagramMessages().size(), 1);
207 
208         assertSearchResponseBasics(
209                 upnpService.getConfiguration().getNamespace(),
210                 upnpService.getRouter().getOutgoingDatagramMessages().get(0),
211                 localDevice
212         );
213         assertEquals(
214                 upnpService.getRouter().getOutgoingDatagramMessages().get(0).getHeaders().getFirstHeader(UpnpHeader.Type.ST).getString(),
215                 new ServiceTypeHeader(service.getServiceType()).getString()
216         );
217         assertEquals(
218                 upnpService.getRouter().getOutgoingDatagramMessages().get(0).getHeaders().getFirstHeader(UpnpHeader.Type.USN).getString(),
219                 new ServiceUSNHeader(localDevice.getIdentity().getUdn(), service.getServiceType()).getString()
220         );
221     }
222 
223     @Test
224     public void receivedInvalidST() throws Exception {
225 
226         MockUpnpService upnpService = new MockUpnpService();
227 
228         IncomingSearchRequest searchMsg = createRequestMessage();
229         searchMsg.getHeaders().add(UpnpHeader.Type.MAN, new MANHeader(NotificationSubtype.DISCOVER.getHeaderString()));
230         searchMsg.getHeaders().add(UpnpHeader.Type.MX, new MXHeader(1));
231         searchMsg.getHeaders().add(UpnpHeader.Type.HOST, new HostHeader());
232 
233         ReceivingSearch prot = createProtocol(upnpService, searchMsg);
234         prot.run();
235 
236         assertEquals(upnpService.getRouter().getOutgoingDatagramMessages().size(), 0);
237     }
238 
239     @Test
240     public void receivedInvalidMX() throws Exception {
241 
242         MockUpnpService upnpService = new MockUpnpService();
243 
244         IncomingSearchRequest searchMsg = createRequestMessage();
245         searchMsg.getHeaders().add(UpnpHeader.Type.MAN, new MANHeader(NotificationSubtype.DISCOVER.getHeaderString()));
246         searchMsg.getHeaders().add(UpnpHeader.Type.ST, new STAllHeader());
247         searchMsg.getHeaders().add(UpnpHeader.Type.HOST, new HostHeader());
248 
249         ReceivingSearch prot = createProtocol(upnpService, searchMsg);
250         prot.run();
251 
252         assertEquals(upnpService.getRouter().getOutgoingDatagramMessages().size(), 0);
253     }
254 
255     @Test
256     public void receivedNonAdvertised() throws Exception {
257 
258         MockUpnpService upnpService = new MockUpnpService();
259 
260         LocalDevice localDevice = SampleData.createLocalDevice();
261 
262         // Disable advertising
263         upnpService.getRegistry().addDevice(localDevice, new DiscoveryOptions(false));
264 
265         IncomingSearchRequest searchMsg = createRequestMessage();
266         searchMsg.getHeaders().add(UpnpHeader.Type.MAN, new MANHeader(NotificationSubtype.DISCOVER.getHeaderString()));
267         searchMsg.getHeaders().add(UpnpHeader.Type.MX, new MXHeader(1));
268         searchMsg.getHeaders().add(UpnpHeader.Type.ST, new STAllHeader());
269         searchMsg.getHeaders().add(UpnpHeader.Type.HOST, new HostHeader());
270 
271         ReceivingSearch prot = createProtocol(upnpService, searchMsg);
272         prot.run();
273 
274         assertEquals(upnpService.getRouter().getOutgoingDatagramMessages().size(), 0);
275 
276         // Enable advertising
277         upnpService.getRegistry().setDiscoveryOptions(
278             localDevice.getIdentity().getUdn(),
279             new DiscoveryOptions(true)
280         );
281 
282         prot = createProtocol(upnpService, searchMsg);
283         prot.run();
284 
285         assertEquals(upnpService.getRouter().getOutgoingDatagramMessages().size(), 10);
286     }
287 
288     protected ReceivingSearch createProtocol(UpnpService upnpService, IncomingSearchRequest searchMsg) throws Exception {
289         return new ReceivingSearch(upnpService, searchMsg);
290     }
291 
292     protected void assertSearchResponseBasics(Namespace namespace, UpnpMessage msg, LocalDevice rootDevice) {
293         assertEquals(
294                 msg.getHeaders().getFirstHeader(UpnpHeader.Type.MAX_AGE).getString(),
295                 new MaxAgeHeader(rootDevice.getIdentity().getMaxAgeSeconds()).getString()
296         );
297         assertEquals(msg.getHeaders().getFirstHeader(UpnpHeader.Type.EXT).getString(), new EXTHeader().getString());
298         assertEquals(
299                 msg.getHeaders().getFirstHeader(UpnpHeader.Type.LOCATION).getString(),
300                 URIUtil.createAbsoluteURL(SampleData.getLocalBaseURL(), namespace.getDescriptorPath(rootDevice)).toString()
301         );
302         assertNotNull(msg.getHeaders().getFirstHeader(UpnpHeader.Type.SERVER).getString());
303     }
304 
305     protected IncomingSearchRequest createRequestMessage() throws UnknownHostException {
306         return new IncomingSearchRequest(
307                 new IncomingDatagramMessage<>(
308                         new UpnpRequest(UpnpRequest.Method.MSEARCH),
309                         InetAddress.getByName("127.0.0.1"),
310                         Constants.UPNP_MULTICAST_PORT,
311                         InetAddress.getByName("127.0.0.1")
312                 )
313         );
314 
315     }
316 
317 }