1 /*****************************************************************
3 | Platinum - Frame Server
5 | Copyright (c) 2004-2010, Plutinosoft, LLC.
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 /*----------------------------------------------------------------------
37 +---------------------------------------------------------------------*/
38 #include "PltFrameStream.h"
39 #include "PltFrameServer.h"
40 #include "PltUtilities.h"
42 NPT_SET_LOCAL_LOGGER("platinum.media.server.frame")
44 /*----------------------------------------------------------------------
46 +---------------------------------------------------------------------*/
47 #define BOUNDARY "BOUNDARYGOAWAY"
49 /*----------------------------------------------------------------------
50 | PLT_SocketPolicyServer
51 +---------------------------------------------------------------------*/
52 class PLT_SocketPolicyServer
: public NPT_Thread
55 PLT_SocketPolicyServer(const char* policy
,
57 const char* authorized_ports
= "5900") :
58 m_Socket(NPT_SOCKET_FLAG_CANCELLABLE
),
61 m_AuthorizedPorts(authorized_ports
),
64 ~PLT_SocketPolicyServer() {
69 NPT_Result result
= NPT_FAILURE
;
72 // randomly try a port for our http server
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
),
82 if (NPT_SUCCEEDED(result
) || m_Port
)
84 } while (--retries
> 0);
86 if (NPT_FAILED(result
) || retries
== 0) return NPT_FAILURE
;
88 // remember that we're bound
90 m_Socket
.GetInfo(info
);
91 m_Port
= info
.local_address
.GetPort();
93 return NPT_Thread::Start();
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
);
135 } while (!m_Aborted
);
138 NPT_TcpServerSocket m_Socket
;
141 NPT_String m_AuthorizedPorts
;
145 /*----------------------------------------------------------------------
146 | PLT_HttpStreamRequestHandler::SetupResponse
147 +---------------------------------------------------------------------*/
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")) {
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)
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);
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
,
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("/\\");
201 new PLT_HttpStreamRequestHandler(stream_validator
),
207 /*----------------------------------------------------------------------
208 | PLT_FrameServer::~PLT_FrameServer
209 +---------------------------------------------------------------------*/
210 PLT_FrameServer::~PLT_FrameServer()
212 delete m_PolicyServer
;
215 /*----------------------------------------------------------------------
216 | PLT_FrameServer::Start
217 +---------------------------------------------------------------------*/
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(
229 "5900,"+NPT_String::FromInteger(GetPort()));
230 NPT_CHECK_SEVERE(m_PolicyServer
->Start());