00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012
00013 #include <cmath>
00014
00015
00016 #include <unistd.h>
00017 #include <sys/time.h>
00018 #ifndef USING_MINGW
00019 #include <sys/utsname.h>
00020 #endif
00021
00022
00023 #include <qregexp.h>
00024 #include <qstringlist.h>
00025 #include <qtextstream.h>
00026 #include <qdatetime.h>
00027
00028
00029 #include "httpserver.h"
00030 #include "upnputil.h"
00031 #include "upnp.h"
00032 #include "compat.h"
00033
00036
00037
00038
00041
00042 QString HttpServer::g_sPlatform;
00043
00045
00047
00048 HttpServer::HttpServer( int nPort )
00049 : QServerSocket( nPort, 20 ),
00050 ThreadPool( "HTTP" )
00051 {
00052 m_extensions.setAutoDelete( true );
00053
00054 InitializeThreads();
00055
00056
00057
00058
00059
00060 #ifdef USING_MINGW
00061 g_sPlatform = QString( "Windows %1.%1" )
00062 .arg(LOBYTE(LOWORD(GetVersion())))
00063 .arg(HIBYTE(LOWORD(GetVersion())));
00064 #else
00065 struct utsname uname_info;
00066
00067 uname( &uname_info );
00068
00069 g_sPlatform = QString( "%1 %2" ).arg( uname_info.sysname )
00070 .arg( uname_info.release );
00071 #endif
00072
00073
00074
00075
00076
00077 m_sSharePath = gContext->GetShareDir();
00078 VERBOSE( VB_UPNP, QString( "HttpServer( %1 ) - SharePath = %2" )
00079 .arg( nPort ).arg( m_sSharePath ));
00080
00081
00082
00083
00084 }
00085
00087
00089
00090 HttpServer::~HttpServer()
00091 {
00092 }
00093
00095
00097
00098 WorkerThread *HttpServer::CreateWorkerThread( ThreadPool * ,
00099 const QString &sName )
00100 {
00101 return( new HttpWorkerThread( this, sName ));
00102 }
00103
00105
00107
00108 void HttpServer::newConnection(int nSocket)
00109 {
00110 HttpWorkerThread *pThread = (HttpWorkerThread *)GetWorkerThread();
00111
00112 if (pThread != NULL)
00113 pThread->StartWork( nSocket );
00114 }
00115
00117
00119
00120 void HttpServer::RegisterExtension( HttpServerExtension *pExtension )
00121 {
00122 if (pExtension != NULL )
00123 {
00124 pExtension->m_sSharePath = m_sSharePath;
00125 m_mutex.lock();
00126 m_extensions.append( pExtension );
00127 m_mutex.unlock();
00128 }
00129 }
00130
00132
00134
00135 void HttpServer::UnregisterExtension( HttpServerExtension *pExtension )
00136 {
00137 if (pExtension != NULL )
00138 {
00139 m_mutex.lock();
00140 m_extensions.remove( pExtension );
00141 m_mutex.unlock();
00142 }
00143 }
00144
00146
00148
00149 void HttpServer::DelegateRequest( HttpWorkerThread *pThread, HTTPRequest *pRequest )
00150 {
00151 bool bProcessed = false;
00152
00153 m_mutex.lock();
00154
00155 HttpServerExtension *pExtension = m_extensions.first();
00156
00157 while (( pExtension != NULL ) && !bProcessed )
00158 {
00159 try
00160 {
00161 bProcessed = pExtension->ProcessRequest( pThread, pRequest );
00162 }
00163 catch(...)
00164 {
00165 VERBOSE( VB_IMPORTANT, QString( "HttpServer::DelegateRequest - Unexpected Exception - pExtension->ProcessRequest()." ));
00166 }
00167
00168 pExtension = m_extensions.next();
00169 }
00170
00171 m_mutex.unlock();
00172
00173 if (!bProcessed)
00174 {
00175 pRequest->m_eResponseType = ResponseTypeHTML;
00176 pRequest->m_nResponseStatus = 404;
00177 }
00178 }
00179
00182
00183
00184
00187
00189
00191
00192 HttpWorkerThread::HttpWorkerThread( HttpServer *pParent, const QString &sName ) :
00193 WorkerThread( (ThreadPool *)pParent, sName )
00194 {
00195 m_pHttpServer = pParent;
00196 m_nSocket = 0;
00197 m_nSocketTimeout = UPnp::g_pConfig->GetValue( "HTTP/KeepAliveTimeoutSecs", 10 ) * 1000;
00198
00199 m_pData = NULL;
00200 }
00201
00203
00205
00206 HttpWorkerThread::~HttpWorkerThread()
00207 {
00208 if (m_pData != NULL)
00209 delete m_pData;
00210 }
00211
00213
00215
00216 void HttpWorkerThread::SetWorkerData( HttpWorkerData *pData )
00217 {
00218
00219
00220
00221 if (m_pData != NULL)
00222 delete m_pData;
00223
00224 m_pData = pData;
00225 }
00226
00228
00230
00231 void HttpWorkerThread::StartWork( int nSocket )
00232 {
00233 m_nSocket = nSocket;
00234
00235 SignalWork();
00236 }
00237
00239
00241
00242 void HttpWorkerThread::ProcessWork()
00243 {
00244
00245
00246
00247
00248 bool bTimeout = false;
00249 bool bKeepAlive = true;
00250 BufferedSocketDevice *pSocket = NULL;
00251 HTTPRequest *pRequest = NULL;
00252
00253 try
00254 {
00255 if ((pSocket = new BufferedSocketDevice( m_nSocket )) == NULL)
00256 {
00257 VERBOSE( VB_IMPORTANT, QString( "HttpWorkerThread::ProcessWork - Error Creating BufferedSocketDevice" ));
00258 return;
00259 }
00260
00261 pSocket->SocketDevice()->setBlocking( true );
00262
00263 while( !m_bTermRequested && bKeepAlive && pSocket->IsValid())
00264 {
00265 bTimeout = 0;
00266
00267 Q_LONG nBytes = pSocket->WaitForMore( m_nSocketTimeout, &bTimeout );
00268
00269 if ( nBytes > 0)
00270 {
00271
00272
00273
00274
00275 if ((pRequest = new BufferedSocketDeviceRequest( pSocket )) != NULL)
00276 {
00277 if ( pRequest->ParseRequest() )
00278 {
00279 bKeepAlive = pRequest->GetKeepAlive();
00280
00281
00282
00283
00284
00285
00286 m_pHttpServer->DelegateRequest( this, pRequest );
00287 }
00288 else
00289 {
00290 VERBOSE( VB_UPNP, QString( "HttpWorkerThread::ProcessWork - ParseRequest Failed." ));
00291
00292 pRequest->m_nResponseStatus = 501;
00293 bKeepAlive = false;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 if (pRequest->SendResponse() < 0)
00314 {
00315 bKeepAlive = false;
00316 VERBOSE( VB_UPNP, QString( "HttpWorkerThread::ProcessWork socket(%1) - Error returned from SendResponse... Closing connection" )
00317 .arg( m_nSocket ));
00318 }
00319
00320
00321
00322
00323
00324 if ( pRequest->m_pPostProcess != NULL )
00325 pRequest->m_pPostProcess->ExecutePostProcess();
00326
00327 delete pRequest;
00328 pRequest = NULL;
00329
00330
00331 }
00332 else
00333 {
00334 VERBOSE( VB_IMPORTANT, QString( "HttpWorkerThread::ProcessWork - Error Creating BufferedSocketDeviceRequest" ));
00335 bKeepAlive = false;
00336 }
00337 }
00338 else
00339 {
00340 bKeepAlive = false;
00341 }
00342 }
00343 }
00344 catch( ... )
00345 {
00346 VERBOSE( VB_IMPORTANT, QString( "HttpWorkerThread::ProcessWork - Unexpected Exception." ));
00347 }
00348
00349 if (pRequest != NULL)
00350 delete pRequest;
00351
00352 pSocket->Close();
00353
00354 delete pSocket;
00355 m_nSocket = 0;
00356
00357
00358
00359 }
00360
00361