Merge pull request #26220 from 78andyp/blurayfixes
[xbmc.git] / lib / libUPnP / Platinum / Source / Extras / PltFrameServer.cpp
blobd01d414317d92388494b8df368c1262932b80112
1 /*****************************************************************
3 | Platinum - Frame Server
5 | Copyright (c) 2004-2010, Plutinosoft, LLC.
6 | All rights reserved.
7 | http://www.plutinosoft.com
9 | This program is free software; you can redistribute it and/or
10 | modify it under the terms of the GNU General Public License
11 | as published by the Free Software Foundation; either version 2
12 | of the License, or (at your option) any later version.
14 | OEMs, ISVs, VARs and other distributors that combine and
15 | distribute commercially licensed software with Platinum software
16 | and do not wish to distribute the source code for the commercially
17 | licensed software under version 2, or (at your option) any later
18 | version, of the GNU General Public License (the "GPL") must enter
19 | into a commercial license agreement with Plutinosoft, LLC.
20 | licensing@plutinosoft.com
22 | This program is distributed in the hope that it will be useful,
23 | but WITHOUT ANY WARRANTY; without even the implied warranty of
24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 | GNU General Public License for more details.
27 | You should have received a copy of the GNU General Public License
28 | along with this program; see the file LICENSE.txt. If not, write to
29 | the Free Software Foundation, Inc.,
30 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
31 | http://www.gnu.org/licenses/gpl-2.0.html
33 ****************************************************************/
35 /*----------------------------------------------------------------------
36 | includes
37 +---------------------------------------------------------------------*/
38 #include "PltFrameStream.h"
39 #include "PltFrameServer.h"
40 #include "PltUtilities.h"
42 NPT_SET_LOCAL_LOGGER("platinum.media.server.frame")
44 /*----------------------------------------------------------------------
45 | constants
46 +---------------------------------------------------------------------*/
47 #define BOUNDARY "BOUNDARYGOAWAY"
49 /*----------------------------------------------------------------------
50 | PLT_SocketPolicyServer
51 +---------------------------------------------------------------------*/
52 class PLT_SocketPolicyServer : public NPT_Thread
54 public:
55 PLT_SocketPolicyServer(const char* policy,
56 NPT_IpPort port = 0,
57 const char* authorized_ports = "5900") :
58 m_Socket(NPT_SOCKET_FLAG_CANCELLABLE),
59 m_Policy(policy),
60 m_Port(port),
61 m_AuthorizedPorts(authorized_ports),
62 m_Aborted(false) {}
64 ~PLT_SocketPolicyServer() {
65 Stop();
68 NPT_Result Start() {
69 NPT_Result result = NPT_FAILURE;
71 // bind
72 // randomly try a port for our http server
73 int retries = 100;
74 do {
75 int random = NPT_System::GetRandomInteger();
76 NPT_IpPort port = (unsigned short)(50000 + (random % 15000));
78 result = m_Socket.Bind(
79 NPT_SocketAddress(NPT_IpAddress::Any, m_Port?m_Port:port),
80 false);
82 if (NPT_SUCCEEDED(result) || m_Port)
83 break;
84 } while (--retries > 0);
86 if (NPT_FAILED(result) || retries == 0) return NPT_FAILURE;
88 // remember that we're bound
89 NPT_SocketInfo info;
90 m_Socket.GetInfo(info);
91 m_Port = info.local_address.GetPort();
93 return NPT_Thread::Start();
96 NPT_Result Stop() {
97 m_Aborted = true;
98 m_Socket.Cancel();
100 return Wait();
103 void Run() {
104 do {
105 // wait for a connection
106 NPT_Socket* client = NULL;
107 NPT_LOG_FINE_1("waiting for connection on port %d...", m_Port);
108 NPT_Result result = m_Socket.WaitForNewClient(client, NPT_TIMEOUT_INFINITE);
109 if (NPT_FAILED(result) || client == NULL) return;
111 NPT_SocketInfo client_info;
112 client->GetInfo(client_info);
113 NPT_LOG_FINE_2("client connected (%s -> %s)",
114 client_info.local_address.ToString().GetChars(),
115 client_info.remote_address.ToString().GetChars());
117 // get the output stream
118 NPT_OutputStreamReference output;
119 client->GetOutputStream(output);
121 // generate policy based on our current IP
122 NPT_String policy = "<cross-domain-policy>";
123 policy += "<allow-access-from domain=\""+client_info.local_address.GetIpAddress().ToString()+"\" to-ports=\""+m_AuthorizedPorts+"\"/>";
124 policy += "<allow-access-from domain=\""+client_info.remote_address.GetIpAddress().ToString()+"\" to-ports=\""+m_AuthorizedPorts+"\"/>";
125 policy += "</cross-domain-policy>";
127 NPT_MemoryStream* mem_input = new NPT_MemoryStream();
128 mem_input->Write(policy.GetChars(), policy.GetLength());
129 NPT_InputStreamReference input(mem_input);
131 NPT_StreamToStreamCopy(*input, *output);
134 delete client;
135 } while (!m_Aborted);
138 NPT_TcpServerSocket m_Socket;
139 NPT_String m_Policy;
140 NPT_IpPort m_Port;
141 NPT_String m_AuthorizedPorts;
142 bool m_Aborted;
145 /*----------------------------------------------------------------------
146 | PLT_HttpStreamRequestHandler::SetupResponse
147 +---------------------------------------------------------------------*/
148 NPT_Result
149 PLT_HttpStreamRequestHandler::SetupResponse(NPT_HttpRequest& request,
150 const NPT_HttpRequestContext& context,
151 NPT_HttpResponse& response)
153 PLT_LOG_HTTP_REQUEST(NPT_LOG_LEVEL_FINE, "PLT_HttpStreamRequestHandler::SetupResponse:", &request);
155 if (request.GetMethod().Compare("GET") &&
156 request.GetMethod().Compare("HEAD")) {
157 return NPT_FAILURE;
160 NPT_Reference<PLT_FrameBuffer> buffer;
161 if (!m_StreamValidator.OnNewRequestAccept(request, context, response, buffer)) {
162 return NPT_ERROR_NO_SUCH_ITEM;
165 response.SetProtocol(NPT_HTTP_PROTOCOL_1_0);
166 response.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONNECTION, "close");
167 response.GetHeaders().SetHeader("Cache-Control", "no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0");
168 response.GetHeaders().SetHeader("Pragma", "no-cache");
169 response.GetHeaders().SetHeader("Expires", "Tue, 4 Jan 2000 02:43:05 GMT");
171 // HEAD request has no entity or if status code is not 2xx
172 if (!request.GetMethod().Compare("HEAD") || response.GetStatusCode()/100 != 2)
173 return NPT_SUCCESS;
175 NPT_HttpEntity* entity = response.GetEntity();
176 NPT_CHECK_POINTER_FATAL(entity);
177 entity->SetContentType("multipart/x-mixed-replace;boundary=" BOUNDARY);
179 NPT_InputStreamReference body(new PLT_InputFrameStream(buffer, BOUNDARY));
180 entity->SetInputStream(body, false);
182 return NPT_SUCCESS;
185 /*----------------------------------------------------------------------
186 | PLT_FrameServer::PLT_FrameServer
187 +---------------------------------------------------------------------*/
188 PLT_FrameServer::PLT_FrameServer(const char* resource_name,
189 PLT_StreamValidator& stream_validator,
190 NPT_IpAddress address,
191 NPT_UInt16 port,
192 bool policy_server_enabled) :
193 PLT_HttpServer(address, port, false),
194 m_PolicyServer(NULL),
195 m_StreamValidator(stream_validator),
196 m_PolicyServerEnabled(policy_server_enabled)
198 NPT_String resource(resource_name);
199 resource.Trim("/\\");
200 AddRequestHandler(
201 new PLT_HttpStreamRequestHandler(stream_validator),
202 "/" + resource,
203 true,
204 true);
207 /*----------------------------------------------------------------------
208 | PLT_FrameServer::~PLT_FrameServer
209 +---------------------------------------------------------------------*/
210 PLT_FrameServer::~PLT_FrameServer()
212 delete m_PolicyServer;
215 /*----------------------------------------------------------------------
216 | PLT_FrameServer::Start
217 +---------------------------------------------------------------------*/
218 NPT_Result
219 PLT_FrameServer::Start()
221 // start main server so we can get the listening port
222 NPT_CHECK_SEVERE(PLT_HttpServer::Start());
224 // start the xml socket policy server for flash
225 if (m_PolicyServerEnabled) {
226 m_PolicyServer = new PLT_SocketPolicyServer(
227 "",
228 8989,
229 "5900,"+NPT_String::FromInteger(GetPort()));
230 NPT_CHECK_SEVERE(m_PolicyServer->Start());
233 return NPT_SUCCESS;