1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.fourthline.cling.test.control;
17
18 import org.fourthline.cling.UpnpService;
19 import org.fourthline.cling.mock.MockUpnpService;
20 import org.fourthline.cling.model.action.ActionException;
21 import org.fourthline.cling.model.action.ActionInvocation;
22 import org.fourthline.cling.model.message.Connection;
23 import org.fourthline.cling.model.message.StreamRequestMessage;
24 import org.fourthline.cling.model.message.StreamResponseMessage;
25 import org.fourthline.cling.model.message.UpnpMessage;
26 import org.fourthline.cling.model.message.UpnpRequest;
27 import org.fourthline.cling.model.message.UpnpResponse;
28 import org.fourthline.cling.model.message.control.IncomingActionResponseMessage;
29 import org.fourthline.cling.model.message.header.ContentTypeHeader;
30 import org.fourthline.cling.model.message.header.EXTHeader;
31 import org.fourthline.cling.model.message.header.ServerHeader;
32 import org.fourthline.cling.model.message.header.SoapActionHeader;
33 import org.fourthline.cling.model.message.header.UpnpHeader;
34 import org.fourthline.cling.model.message.header.UserAgentHeader;
35 import org.fourthline.cling.model.meta.Action;
36 import org.fourthline.cling.model.meta.LocalDevice;
37 import org.fourthline.cling.model.meta.LocalService;
38 import org.fourthline.cling.model.meta.QueryStateVariableAction;
39 import org.fourthline.cling.model.meta.Service;
40 import org.fourthline.cling.model.types.ErrorCode;
41 import org.fourthline.cling.model.types.SoapActionType;
42 import org.fourthline.cling.protocol.sync.ReceivingAction;
43 import org.seamless.util.MimeType;
44 import org.testng.annotations.Test;
45
46 import java.net.InetAddress;
47 import java.net.URI;
48 import java.net.UnknownHostException;
49
50 import static org.testng.Assert.*;
51
52
53
54
55 public class ActionInvokeIncomingTest {
56
57 public static final String SET_REQUEST = "<?xml version=\"1.0\"?>\n" +
58 " <s:Envelope\n" +
59 " xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
60 " s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" +
61 " <s:Body>\n" +
62 " <u:SetTarget xmlns:u=\"urn:schemas-upnp-org:service:SwitchPower:1\">\n" +
63 " <NewTargetValue>1</NewTargetValue>\n" +
64 " </u:SetTarget>\n" +
65 " </s:Body>\n" +
66 " </s:Envelope>";
67
68 public static final String GET_REQUEST = "<?xml version=\"1.0\"?>\n" +
69 " <s:Envelope\n" +
70 " xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
71 " s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" +
72 " <s:Body>\n" +
73 " <u:GetTarget xmlns:u=\"urn:schemas-upnp-org:service:SwitchPower:1\"/>\n" +
74 " </s:Body>\n" +
75 " </s:Envelope>";
76
77 public static final String QUERY_STATE_VARIABLE_REQUEST = "<?xml version=\"1.0\"?>\n" +
78 " <s:Envelope\n" +
79 " xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
80 " s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" +
81 " <s:Body>\n" +
82 " <u:QueryStateVariable xmlns:u=\"urn:schemas-upnp-org:control-1-0\">\n" +
83 " <varName>Status</varName>\n" +
84 " </u:QueryStateVariable>\n" +
85 " </s:Body>\n" +
86 " </s:Envelope>";
87
88 @Test
89 public void incomingRemoteCallGet() throws Exception {
90 incomingRemoteCallGet(ActionSampleData.createTestDevice());
91 }
92
93 @Test
94 public void incomingRemoteCallClientInfo() throws Exception {
95 UpnpMessage response =
96 incomingRemoteCallGet(ActionSampleData.createTestDevice(ActionSampleData.LocalTestServiceWithClientInfo.class));
97
98 assertEquals(response.getHeaders().size(), 4);
99 assertEquals(response.getHeaders().getFirstHeader("X-MY-HEADER"), "foobar");
100 }
101
102 public IncomingActionResponseMessage incomingRemoteCallGet(LocalDevice ld) throws Exception {
103
104 MockUpnpService upnpService = new MockUpnpService();
105 LocalService service = ld.getServices()[0];
106 upnpService.getRegistry().addDevice(ld);
107
108 Action action = service.getAction("GetTarget");
109
110 URI controlURI = upnpService.getConfiguration().getNamespace().getControlPath(service);
111 StreamRequestMessage request = new StreamRequestMessage(UpnpRequest.Method.POST, controlURI);
112 request.setConnection(new Connection() {
113 @Override
114 public boolean isOpen() {
115 return true;
116 }
117
118 @Override
119 public InetAddress getRemoteAddress() {
120 try {
121 return InetAddress.getByName("10.0.0.1");
122 } catch (UnknownHostException ex) {
123 throw new RuntimeException(ex);
124 }
125 }
126
127 @Override
128 public InetAddress getLocalAddress() {
129 try {
130 return InetAddress.getByName("10.0.0.2");
131 } catch (UnknownHostException ex) {
132 throw new RuntimeException(ex);
133 }
134 }
135 });
136 addMandatoryRequestHeaders(service, action, request);
137 request.setBody(UpnpMessage.BodyType.STRING, GET_REQUEST);
138
139 ReceivingAction prot = new ReceivingAction(upnpService, request);
140
141 prot.run();
142
143 StreamResponseMessage response = prot.getOutputMessage();
144
145 assertNotNull(response);
146 assertFalse(response.getOperation().isFailed());
147 assertTrue(response.getHeaders().getFirstHeader(UpnpHeader.Type.CONTENT_TYPE, ContentTypeHeader.class).isUDACompliantXML());
148 assertNotNull(response.getHeaders().getFirstHeader(UpnpHeader.Type.EXT, EXTHeader.class));
149 assertEquals(
150 response.getHeaders().getFirstHeader(UpnpHeader.Type.SERVER, ServerHeader.class).getValue(),
151 new ServerHeader().getValue()
152 );
153
154 IncomingActionResponseMessage responseMessage = new IncomingActionResponseMessage(response);
155 ActionInvocation responseInvocation = new ActionInvocation(action);
156 upnpService.getConfiguration().getSoapActionProcessor().readBody(responseMessage, responseInvocation);
157
158 assertNotNull(responseInvocation.getOutput("RetTargetValue"));
159 return responseMessage;
160 }
161
162 @Test
163 public void incomingRemoteCallGetConcurrent() throws Exception {
164
165
166 MockUpnpService upnpService = new MockUpnpService(false, false, true);
167 LocalDevice ld = ActionSampleData.createTestDevice(ActionSampleData.LocalTestServiceThrowsException.class);
168 LocalService service = ld.getServices()[0];
169 upnpService.getRegistry().addDevice(ld);
170
171
172 int i = 0;
173 while (i < 10) {
174 new Thread(new ConcurrentGetTest(upnpService, service)).start();
175 i++;
176 }
177
178
179 Thread.sleep(2000);
180 }
181
182 static class ConcurrentGetTest implements Runnable {
183 private UpnpService upnpService;
184 private LocalService service;
185
186 ConcurrentGetTest(UpnpService upnpService, LocalService service) {
187 this.upnpService = upnpService;
188 this.service = service;
189 }
190
191 public void run() {
192 Action action = service.getAction("GetTarget");
193
194 URI controlURI = upnpService.getConfiguration().getNamespace().getControlPath(service);
195 StreamRequestMessage request = new StreamRequestMessage(UpnpRequest.Method.POST, controlURI);
196 request.getHeaders().add(
197 UpnpHeader.Type.CONTENT_TYPE,
198 new ContentTypeHeader(ContentTypeHeader.DEFAULT_CONTENT_TYPE_UTF8)
199 );
200
201 SoapActionType actionType = new SoapActionType(service.getServiceType(), action.getName());
202 request.getHeaders().add(UpnpHeader.Type.SOAPACTION, new SoapActionHeader(actionType));
203 request.setBody(UpnpMessage.BodyType.STRING, GET_REQUEST);
204
205 ReceivingAction prot = new ReceivingAction(upnpService, request);
206
207 prot.run();
208
209 StreamResponseMessage response = prot.getOutputMessage();
210
211 assertNotNull(response);
212 assertFalse(response.getOperation().isFailed());
213 assertTrue(response.getHeaders().getFirstHeader(UpnpHeader.Type.CONTENT_TYPE, ContentTypeHeader.class).isUDACompliantXML());
214 assertNotNull(response.getHeaders().getFirstHeader(UpnpHeader.Type.EXT, EXTHeader.class));
215 assertEquals(
216 response.getHeaders().getFirstHeader(UpnpHeader.Type.SERVER, ServerHeader.class).getValue(),
217 new ServerHeader().getValue()
218 );
219
220 IncomingActionResponseMessage responseMessage = new IncomingActionResponseMessage(response);
221 ActionInvocation responseInvocation = new ActionInvocation(action);
222 upnpService.getConfiguration().getSoapActionProcessor().readBody(responseMessage, responseInvocation);
223
224 assertNotNull(responseInvocation.getOutput("RetTargetValue"));
225 }
226 }
227
228
229 @Test
230 public void incomingRemoteCallSet() throws Exception {
231
232
233 MockUpnpService upnpService = new MockUpnpService();
234 LocalDevice ld = ActionSampleData.createTestDevice();
235 LocalService service = ld.getServices()[0];
236 upnpService.getRegistry().addDevice(ld);
237
238 Action action = service.getAction("SetTarget");
239
240 URI controlURI = upnpService.getConfiguration().getNamespace().getControlPath(service);
241 StreamRequestMessage request = new StreamRequestMessage(UpnpRequest.Method.POST, controlURI);
242 addMandatoryRequestHeaders(service, action, request);
243 request.setBody(UpnpMessage.BodyType.STRING, SET_REQUEST);
244
245 ReceivingAction prot = new ReceivingAction(upnpService, request);
246
247 prot.run();
248
249 StreamResponseMessage response = prot.getOutputMessage();
250
251 assertNotNull(response);
252 assertFalse(response.getOperation().isFailed());
253 assertTrue(response.getHeaders().getFirstHeader(UpnpHeader.Type.CONTENT_TYPE, ContentTypeHeader.class).isUDACompliantXML());
254 assertNotNull(response.getHeaders().getFirstHeader(UpnpHeader.Type.EXT, EXTHeader.class));
255 assertEquals(
256 response.getHeaders().getFirstHeader(UpnpHeader.Type.SERVER, ServerHeader.class).getValue(),
257 new ServerHeader().getValue()
258 );
259
260 IncomingActionResponseMessage responseMessage = new IncomingActionResponseMessage(response);
261 ActionInvocation responseInvocation = new ActionInvocation(action);
262 upnpService.getConfiguration().getSoapActionProcessor().readBody(responseMessage, responseInvocation);
263
264 assertEquals(responseInvocation.getOutput().length, 0);
265
266 }
267
268 @Test
269 public void incomingRemoteCallControlURINotFound() throws Exception {
270
271
272 MockUpnpService upnpService = new MockUpnpService();
273 LocalDevice ld = ActionSampleData.createTestDevice();
274 LocalService service = ld.getServices()[0];
275 upnpService.getRegistry().addDevice(ld);
276
277 Action action = service.getAction("SetTarget");
278
279 StreamRequestMessage request = new StreamRequestMessage(UpnpRequest.Method.POST, URI.create("/some/random/123/uri"));
280 addMandatoryRequestHeaders(service, action, request);
281 request.setBody(UpnpMessage.BodyType.STRING, SET_REQUEST);
282
283 ReceivingAction prot = new ReceivingAction(upnpService, request);
284
285 prot.run();
286
287 UpnpMessage response = prot.getOutputMessage();
288
289 assertNull(response);
290
291 }
292
293 @Test
294 public void incomingRemoteCallMethodException() throws Exception {
295
296
297 MockUpnpService upnpService = new MockUpnpService();
298 LocalDevice ld = ActionSampleData.createTestDevice(ActionSampleData.LocalTestServiceThrowsException.class);
299 LocalService service = ld.getServices()[0];
300 upnpService.getRegistry().addDevice(ld);
301
302 Action action = service.getAction("SetTarget");
303
304 URI controlURI = upnpService.getConfiguration().getNamespace().getControlPath(service);
305 StreamRequestMessage request = new StreamRequestMessage(UpnpRequest.Method.POST, controlURI);
306 addMandatoryRequestHeaders(service, action, request);
307
308 request.setBody(UpnpMessage.BodyType.STRING, SET_REQUEST);
309
310 ReceivingAction prot = new ReceivingAction(upnpService, request);
311
312 prot.run();
313
314 StreamResponseMessage response = prot.getOutputMessage();
315
316 assertNotNull(response);
317 assertTrue(response.getOperation().isFailed());
318 assertTrue(response.getHeaders().getFirstHeader(UpnpHeader.Type.CONTENT_TYPE, ContentTypeHeader.class).isUDACompliantXML());
319 assertNotNull(response.getHeaders().getFirstHeader(UpnpHeader.Type.EXT, EXTHeader.class));
320 assertEquals(
321 response.getHeaders().getFirstHeader(UpnpHeader.Type.SERVER, ServerHeader.class).getValue(),
322 new ServerHeader().getValue()
323 );
324
325 IncomingActionResponseMessage responseMessage = new IncomingActionResponseMessage(response);
326 ActionInvocation responseInvocation = new ActionInvocation(action);
327 upnpService.getConfiguration().getSoapActionProcessor().readBody(responseMessage, responseInvocation);
328
329 ActionException ex = responseInvocation.getFailure();
330 assertNotNull(ex);
331
332 assertEquals(ex.getMessage(), ErrorCode.ACTION_FAILED.getDescription() + ". Something is wrong.");
333
334 }
335
336 @Test
337 public void incomingRemoteCallNoContentType() throws Exception {
338
339
340 MockUpnpService upnpService = new MockUpnpService();
341 LocalDevice ld = ActionSampleData.createTestDevice();
342 LocalService service = ld.getServices()[0];
343 upnpService.getRegistry().addDevice(ld);
344
345 Action action = service.getAction("GetTarget");
346
347 URI controlURI = upnpService.getConfiguration().getNamespace().getControlPath(service);
348 StreamRequestMessage request = new StreamRequestMessage(UpnpRequest.Method.POST, controlURI);
349 SoapActionType actionType = new SoapActionType(service.getServiceType(), action.getName());
350 request.getHeaders().add(UpnpHeader.Type.SOAPACTION, new SoapActionHeader(actionType));
351
352 request.setBody(UpnpMessage.BodyType.STRING, GET_REQUEST);
353
354 ReceivingAction prot = new ReceivingAction(upnpService, request);
355
356 prot.run();
357
358 StreamResponseMessage response = prot.getOutputMessage();
359
360 assertNotNull(response);
361 assertFalse(response.getOperation().isFailed());
362 assertTrue(response.getHeaders().getFirstHeader(UpnpHeader.Type.CONTENT_TYPE, ContentTypeHeader.class).isUDACompliantXML());
363 assertNotNull(response.getHeaders().getFirstHeader(UpnpHeader.Type.EXT, EXTHeader.class));
364 assertEquals(
365 response.getHeaders().getFirstHeader(UpnpHeader.Type.SERVER, ServerHeader.class).getValue(),
366 new ServerHeader().getValue()
367 );
368
369 IncomingActionResponseMessage responseMessage = new IncomingActionResponseMessage(response);
370 ActionInvocation responseInvocation = new ActionInvocation(action);
371 upnpService.getConfiguration().getSoapActionProcessor().readBody(responseMessage, responseInvocation);
372
373 assertNotNull(responseInvocation.getOutput("RetTargetValue"));
374
375 }
376
377 @Test
378 public void incomingRemoteCallWrongContentType() throws Exception {
379
380 MockUpnpService upnpService = new MockUpnpService();
381
382 StreamRequestMessage request = new StreamRequestMessage(UpnpRequest.Method.POST, URI.create("/some/random/123/uri"));
383 request.getHeaders().add(
384 UpnpHeader.Type.CONTENT_TYPE,
385 new ContentTypeHeader(MimeType.valueOf("some/randomtype"))
386 );
387 request.setBody(UpnpMessage.BodyType.STRING, SET_REQUEST);
388
389 ReceivingAction prot = new ReceivingAction(upnpService, request);
390
391 prot.run();
392
393 StreamResponseMessage response = prot.getOutputMessage();
394
395 assertNotNull(response);
396 assertEquals(response.getOperation().getStatusCode(), UpnpResponse.Status.UNSUPPORTED_MEDIA_TYPE.getStatusCode());
397 }
398
399 @Test
400 public void incomingRemoteCallQueryStateVariable() throws Exception {
401
402
403 MockUpnpService upnpService = new MockUpnpService();
404 LocalDevice ld = ActionSampleData.createTestDevice();
405 LocalService service = ld.getServices()[0];
406 upnpService.getRegistry().addDevice(ld);
407
408 Action action = service.getAction(QueryStateVariableAction.ACTION_NAME);
409
410 URI controlURI = upnpService.getConfiguration().getNamespace().getControlPath(service);
411 StreamRequestMessage request = new StreamRequestMessage(UpnpRequest.Method.POST, controlURI);
412 request.getHeaders().add(
413 UpnpHeader.Type.CONTENT_TYPE,
414 new ContentTypeHeader(ContentTypeHeader.DEFAULT_CONTENT_TYPE_UTF8)
415 );
416 request.getHeaders().add(
417 UpnpHeader.Type.SOAPACTION,
418 new SoapActionHeader(
419 new SoapActionType(
420 SoapActionType.MAGIC_CONTROL_NS, SoapActionType.MAGIC_CONTROL_TYPE, null, action.getName()
421 )
422 )
423
424 );
425 request.setBody(UpnpMessage.BodyType.STRING, QUERY_STATE_VARIABLE_REQUEST);
426
427 ReceivingAction prot = new ReceivingAction(upnpService, request);
428
429 prot.run();
430
431 StreamResponseMessage response = prot.getOutputMessage();
432
433 assertNotNull(response);
434 assertFalse(response.getOperation().isFailed());
435 assertTrue(response.getHeaders().getFirstHeader(UpnpHeader.Type.CONTENT_TYPE, ContentTypeHeader.class).isUDACompliantXML());
436 assertNotNull(response.getHeaders().getFirstHeader(UpnpHeader.Type.EXT, EXTHeader.class));
437 assertEquals(
438 response.getHeaders().getFirstHeader(UpnpHeader.Type.SERVER, ServerHeader.class).getValue(),
439 new ServerHeader().getValue()
440 );
441
442 IncomingActionResponseMessage responseMessage = new IncomingActionResponseMessage(response);
443 ActionInvocation responseInvocation = new ActionInvocation(action);
444 upnpService.getConfiguration().getSoapActionProcessor().readBody(responseMessage, responseInvocation);
445
446 assertEquals(responseInvocation.getOutput()[0].getArgument().getName(), "return");
447 assertEquals(responseInvocation.getOutput()[0].toString(), "0");
448 }
449
450
451 protected void addMandatoryRequestHeaders(Service service, Action action, StreamRequestMessage request) {
452 request.getHeaders().add(
453 UpnpHeader.Type.CONTENT_TYPE,
454 new ContentTypeHeader(ContentTypeHeader.DEFAULT_CONTENT_TYPE_UTF8)
455 );
456
457 SoapActionType actionType = new SoapActionType(service.getServiceType(), action.getName());
458 request.getHeaders().add(UpnpHeader.Type.SOAPACTION, new SoapActionHeader(actionType));
459
460 request.getHeaders().add(UpnpHeader.Type.USER_AGENT, new UserAgentHeader("foo/bar"));
461 }
462
463 }