1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.fourthline.cling.transport.impl;
17
18 import com.sun.net.httpserver.HttpExchange;
19 import org.fourthline.cling.model.message.Connection;
20 import org.fourthline.cling.model.message.StreamRequestMessage;
21 import org.fourthline.cling.model.message.StreamResponseMessage;
22 import org.fourthline.cling.model.message.UpnpHeaders;
23 import org.fourthline.cling.model.message.UpnpMessage;
24 import org.fourthline.cling.model.message.UpnpRequest;
25 import org.fourthline.cling.protocol.ProtocolFactory;
26 import org.fourthline.cling.transport.spi.UpnpStream;
27 import org.seamless.util.Exceptions;
28 import org.seamless.util.io.IO;
29
30 import java.io.IOException;
31 import java.io.InputStream;
32 import java.io.OutputStream;
33 import java.net.HttpURLConnection;
34 import java.util.Locale;
35 import java.util.logging.Level;
36 import java.util.logging.Logger;
37
38
39
40
41
42
43
44
45
46 public abstract class HttpExchangeUpnpStream extends UpnpStream {
47
48 private static Logger log = Logger.getLogger(UpnpStream.class.getName());
49
50 private HttpExchange httpExchange;
51
52 public HttpExchangeUpnpStream(ProtocolFactory protocolFactory, HttpExchange httpExchange) {
53 super(protocolFactory);
54 this.httpExchange = httpExchange;
55 }
56
57 public HttpExchange getHttpExchange() {
58 return httpExchange;
59 }
60
61 public void run() {
62
63 try {
64 log.fine("Processing HTTP request: " + getHttpExchange().getRequestMethod() + " " + getHttpExchange().getRequestURI());
65
66
67 StreamRequestMessage requestMessage =
68 new StreamRequestMessage(
69 UpnpRequest.Method.getByHttpName(getHttpExchange().getRequestMethod()),
70 getHttpExchange().getRequestURI()
71 );
72
73 if (requestMessage.getOperation().getMethod().equals(UpnpRequest.Method.UNKNOWN)) {
74 log.fine("Method not supported by UPnP stack: " + getHttpExchange().getRequestMethod());
75 throw new RuntimeException("Method not supported: " + getHttpExchange().getRequestMethod());
76 }
77
78
79 requestMessage.getOperation().setHttpMinorVersion(
80 getHttpExchange().getProtocol().toUpperCase(Locale.ROOT).equals("HTTP/1.1") ? 1 : 0
81 );
82
83 log.fine("Created new request message: " + requestMessage);
84
85
86 requestMessage.setConnection(createConnection());
87
88
89 requestMessage.setHeaders(new UpnpHeaders(getHttpExchange().getRequestHeaders()));
90
91
92 byte[] bodyBytes;
93 InputStream is = null;
94 try {
95 is = getHttpExchange().getRequestBody();
96 bodyBytes = IO.readBytes(is);
97 } finally {
98 if (is != null)
99 is.close();
100 }
101
102 log.fine("Reading request body bytes: " + bodyBytes.length);
103
104 if (bodyBytes.length > 0 && requestMessage.isContentTypeMissingOrText()) {
105
106 log.fine("Request contains textual entity body, converting then setting string on message");
107 requestMessage.setBodyCharacters(bodyBytes);
108
109 } else if (bodyBytes.length > 0) {
110
111 log.fine("Request contains binary entity body, setting bytes on message");
112 requestMessage.setBody(UpnpMessage.BodyType.BYTES, bodyBytes);
113
114 } else {
115 log.fine("Request did not contain entity body");
116 }
117
118
119 StreamResponseMessage responseMessage = process(requestMessage);
120
121
122 if (responseMessage != null) {
123 log.fine("Preparing HTTP response message: " + responseMessage);
124
125
126 getHttpExchange().getResponseHeaders().putAll(
127 responseMessage.getHeaders()
128 );
129
130
131 byte[] responseBodyBytes = responseMessage.hasBody() ? responseMessage.getBodyBytes() : null;
132 int contentLength = responseBodyBytes != null ? responseBodyBytes.length : -1;
133
134 log.fine("Sending HTTP response message: " + responseMessage + " with content length: " + contentLength);
135 getHttpExchange().sendResponseHeaders(responseMessage.getOperation().getStatusCode(), contentLength);
136
137 if (contentLength > 0) {
138 log.fine("Response message has body, writing bytes to stream...");
139 OutputStream os = null;
140 try {
141 os = getHttpExchange().getResponseBody();
142 IO.writeBytes(os, responseBodyBytes);
143 os.flush();
144 } finally {
145 if (os != null)
146 os.close();
147 }
148 }
149
150 } else {
151
152 log.fine("Sending HTTP response status: " + HttpURLConnection.HTTP_NOT_FOUND);
153 getHttpExchange().sendResponseHeaders(HttpURLConnection.HTTP_NOT_FOUND, -1);
154 }
155
156 responseSent(responseMessage);
157
158 } catch (Throwable t) {
159
160
161
162
163
164
165
166
167
168
169 log.fine("Exception occured during UPnP stream processing: " + t);
170 if (log.isLoggable(Level.FINE)) {
171 log.log(Level.FINE, "Cause: " + Exceptions.unwrap(t), Exceptions.unwrap(t));
172 }
173 try {
174 httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_INTERNAL_ERROR, -1);
175 } catch (IOException ex) {
176 log.warning("Couldn't send error response: " + ex);
177 }
178
179 responseException(t);
180 }
181 }
182
183 abstract protected Connection createConnection();
184
185 }