00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00013
00014
00015 #include <cmath>
00016
00017
00018 #include <compat.h>
00019 #ifndef USING_MINGW
00020 #include <sys/utsname.h>
00021 #endif
00022
00023
00024 #include <QScriptEngine>
00025
00026
00027 #include "httpserver.h"
00028 #include "upnputil.h"
00029 #include "upnp.h"
00030 #include "compat.h"
00031 #include "mythdirs.h"
00032 #include "mythlogging.h"
00033 #include "htmlserver.h"
00034
00037
00038
00039
00042
00043 QMutex HttpServer::s_platformLock;
00044 QString HttpServer::s_platform;
00045
00047
00049
00050 HttpServer::HttpServer(const QString sApplicationPrefix) :
00051 ServerPool(), m_sSharePath(GetShareDir()),
00052 m_pHtmlServer(new HtmlServerExtension(m_sSharePath, sApplicationPrefix)),
00053 m_threadPool("HttpServerPool"), m_running(true)
00054 {
00055 setMaxPendingConnections(20);
00056
00057
00058
00059
00060 {
00061 QMutexLocker locker(&s_platformLock);
00062 #ifdef USING_MINGW
00063 s_platform = QString("Windows %1.%2")
00064 .arg(LOBYTE(LOWORD(GetVersion())))
00065 .arg(HIBYTE(LOWORD(GetVersion())));
00066 #else
00067 struct utsname uname_info;
00068 uname( &uname_info );
00069 s_platform = QString("%1 %2")
00070 .arg(uname_info.sysname).arg(uname_info.release);
00071 #endif
00072 }
00073
00074 LOG(VB_UPNP, LOG_INFO, QString("HttpServer() - SharePath = %1")
00075 .arg(m_sSharePath));
00076
00077
00078
00079 }
00080
00082
00084
00085 HttpServer::~HttpServer()
00086 {
00087 m_rwlock.lockForWrite();
00088 m_running = false;
00089 m_rwlock.unlock();
00090
00091 m_threadPool.Stop();
00092
00093 while (!m_extensions.empty())
00094 {
00095 delete m_extensions.takeFirst();
00096 }
00097
00098 if (m_pHtmlServer != NULL)
00099 delete m_pHtmlServer;
00100 }
00101
00103
00105
00106 QString HttpServer::GetPlatform(void)
00107 {
00108 QMutexLocker locker(&s_platformLock);
00109 return s_platform;
00110 }
00111
00113
00115
00116 QScriptEngine* HttpServer::ScriptEngine()
00117 {
00118 return ((HtmlServerExtension *)m_pHtmlServer)->ScriptEngine();
00119 }
00120
00122
00124
00125 void HttpServer::newTcpConnection(int nSocket)
00126 {
00127 m_threadPool.startReserved(
00128 new HttpWorker(*this, nSocket),
00129 QString("HttpServer%1").arg(nSocket));
00130 }
00131
00133
00135
00136 void HttpServer::RegisterExtension( HttpServerExtension *pExtension )
00137 {
00138 if (pExtension != NULL )
00139 {
00140 m_rwlock.lockForWrite();
00141 m_extensions.append( pExtension );
00142
00143
00144
00145 QStringList list = pExtension->GetBasePaths();
00146
00147 for( int nIdx = 0; nIdx < list.size(); nIdx++)
00148 m_basePaths.insert( list[ nIdx ], pExtension );
00149
00150 m_rwlock.unlock();
00151 }
00152 }
00153
00155
00157
00158 void HttpServer::UnregisterExtension( HttpServerExtension *pExtension )
00159 {
00160 if (pExtension != NULL )
00161 {
00162 m_rwlock.lockForWrite();
00163
00164 QStringList list = pExtension->GetBasePaths();
00165
00166 for( int nIdx = 0; nIdx < list.size(); nIdx++)
00167 m_basePaths.remove( list[ nIdx ], pExtension );
00168
00169 m_extensions.removeAll(pExtension);
00170
00171 delete pExtension;
00172
00173 m_rwlock.unlock();
00174 }
00175 }
00176
00178
00180
00181 void HttpServer::DelegateRequest(HTTPRequest *pRequest)
00182 {
00183 bool bProcessed = false;
00184
00185 m_rwlock.lockForRead();
00186
00187 QList< HttpServerExtension* > list = m_basePaths.values( pRequest->m_sBaseUrl );
00188
00189 for (int nIdx=0; nIdx < list.size() && !bProcessed; nIdx++ )
00190 {
00191 try
00192 {
00193 bProcessed = list[ nIdx ]->ProcessRequest(pRequest);
00194 }
00195 catch(...)
00196 {
00197 LOG(VB_GENERAL, LOG_ERR, QString("HttpServer::DelegateRequest - "
00198 "Unexpected Exception - "
00199 "pExtension->ProcessRequest()."));
00200 }
00201 }
00202
00203 #if 0
00204 HttpServerExtensionList::iterator it = m_extensions.begin();
00205
00206 for (; (it != m_extensions.end()) && !bProcessed; ++it)
00207 {
00208 try
00209 {
00210 bProcessed = (*it)->ProcessRequest(pRequest);
00211 }
00212 catch(...)
00213 {
00214 LOG(VB_GENERAL, LOG_ERR, QString("HttpServer::DelegateRequest - "
00215 "Unexpected Exception - "
00216 "pExtension->ProcessRequest()."));
00217 }
00218 }
00219 #endif
00220 m_rwlock.unlock();
00221
00222 if (!bProcessed)
00223 bProcessed = m_pHtmlServer->ProcessRequest(pRequest);
00224
00225 if (!bProcessed)
00226 {
00227 pRequest->m_eResponseType = ResponseTypeHTML;
00228 pRequest->m_nResponseStatus = 404;
00229 }
00230 }
00231
00234
00235
00236
00239
00240 HttpWorker::HttpWorker(HttpServer &httpServer, int sock) :
00241 m_httpServer(httpServer), m_socket(sock), m_socketTimeout(10000)
00242 {
00243 m_socketTimeout = 1000 *
00244 UPnp::GetConfiguration()->GetValue("HTTP/KeepAliveTimeoutSecs", 10);
00245 }
00246
00248
00250
00251 void HttpWorker::run(void)
00252 {
00253 #if 0
00254 LOG(VB_UPNP, LOG_DEBUG,
00255 QString("HttpWorker::run() socket=%1 -- begin").arg(m_socket));
00256 #endif
00257
00258 bool bTimeout = false;
00259 bool bKeepAlive = true;
00260 BufferedSocketDevice *pSocket = NULL;
00261 HTTPRequest *pRequest = NULL;
00262
00263 try
00264 {
00265 if ((pSocket = new BufferedSocketDevice( m_socket )) == NULL)
00266 {
00267 LOG(VB_GENERAL, LOG_ERR, "Error Creating BufferedSocketDevice");
00268 return;
00269 }
00270
00271 pSocket->SocketDevice()->setBlocking( true );
00272
00273 while (m_httpServer.IsRunning() && bKeepAlive && pSocket->IsValid())
00274 {
00275 bTimeout = false;
00276
00277 int64_t nBytes = pSocket->WaitForMore(m_socketTimeout, &bTimeout);
00278 if (!m_httpServer.IsRunning())
00279 break;
00280
00281 if ( nBytes > 0)
00282 {
00283
00284
00285
00286
00287 pRequest = new BufferedSocketDeviceRequest( pSocket );
00288 if (pRequest != NULL)
00289 {
00290 if ( pRequest->ParseRequest() )
00291 {
00292 bKeepAlive = pRequest->GetKeepAlive();
00293
00294
00295
00296
00297
00298
00299 if (pRequest->m_nResponseStatus != 401)
00300 m_httpServer.DelegateRequest(pRequest);
00301 }
00302 else
00303 {
00304 LOG(VB_UPNP, LOG_ERR, "ParseRequest Failed.");
00305
00306 pRequest->m_nResponseStatus = 501;
00307 bKeepAlive = false;
00308 }
00309
00310 #if 0
00311
00312 if (!bKeepAlive )
00313 {
00314 for ( QStringMap::iterator it = pRequest->m_mapHeaders.begin();
00315 it != pRequest->m_mapHeaders.end();
00316 ++it )
00317 {
00318 LOG(VB_GENERAL, LOG_DEBUG, QString("%1: %2")
00319 .arg(it.key()) .arg(it.data()));
00320 }
00321 }
00322 #endif
00323
00324
00325
00326
00327
00328 if (pRequest->SendResponse() < 0)
00329 {
00330 bKeepAlive = false;
00331 LOG(VB_UPNP, LOG_ERR,
00332 QString("socket(%1) - Error returned from "
00333 "SendResponse... Closing connection")
00334 .arg(m_socket));
00335 }
00336
00337
00338
00339
00340
00341 if ( pRequest->m_pPostProcess != NULL )
00342 pRequest->m_pPostProcess->ExecutePostProcess();
00343
00344 delete pRequest;
00345 pRequest = NULL;
00346 }
00347 else
00348 {
00349 LOG(VB_GENERAL, LOG_ERR,
00350 "Error Creating BufferedSocketDeviceRequest");
00351 bKeepAlive = false;
00352 }
00353 }
00354 else
00355 {
00356 bKeepAlive = false;
00357 }
00358 }
00359 }
00360 catch(...)
00361 {
00362 LOG(VB_GENERAL, LOG_ERR,
00363 "HttpWorkerThread::ProcessWork - Unexpected Exception.");
00364 }
00365
00366 if (pRequest != NULL)
00367 delete pRequest;
00368
00369 pSocket->Close();
00370
00371 delete pSocket;
00372 m_socket = 0;
00373
00374 #if 0
00375 LOG(VB_UPNP, LOG_DEBUG, "HttpWorkerThread::run() -- end");
00376 #endif
00377 }
00378
00379