Arquivos
hhvm/hphp/runtime/base/server/satellite_server.cpp
T
2013-04-22 14:43:49 -07:00

234 linhas
7.4 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include <runtime/base/server/satellite_server.h>
#include <runtime/base/server/libevent_server.h>
#include <runtime/base/server/http_request_handler.h>
#include <runtime/base/server/rpc_request_handler.h>
#include <runtime/base/server/virtual_host.h>
#include <runtime/base/runtime_option.h>
#include <runtime/base/preg.h>
#include <util/util.h>
using std::set;
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
std::set<std::string> SatelliteServerInfo::InternalURLs;
int SatelliteServerInfo::DanglingServerPort = 0;
SatelliteServerInfo::SatelliteServerInfo(Hdf hdf) {
m_name = hdf.getName();
m_port = hdf["Port"].getInt16(0);
m_threadCount = hdf["ThreadCount"].getInt32(5);
m_maxRequest = hdf["MaxRequest"].getInt32(500);
m_maxDuration = hdf["MaxDuration"].getInt32(120);
m_timeoutSeconds =
hdf["TimeoutSeconds"].getInt32(RuntimeOption::RequestTimeoutSeconds);
m_reqInitFunc = hdf["RequestInitFunction"].getString("");
m_reqInitDoc = hdf["RequestInitDocument"].getString("");
m_password = hdf["Password"].getString("");
hdf["Passwords"].get(m_passwords);
m_alwaysReset = hdf["AlwaysReset"].getBool(false);
string type = hdf["Type"].getString();
if (type == "InternalPageServer") {
m_type = SatelliteServer::KindOfInternalPageServer;
vector<string> urls;
hdf["URLs"].get(urls);
for (unsigned int i = 0; i < urls.size(); i++) {
m_urls.insert(Util::format_pattern(urls[i], true));
}
if (hdf["BlockMainServer"].getBool(true)) {
InternalURLs.insert(m_urls.begin(), m_urls.end());
}
} else if (type == "DanglingPageServer") {
m_type = SatelliteServer::KindOfDanglingPageServer;
DanglingServerPort = m_port;
} else if (type == "RPCServer") {
m_type = SatelliteServer::KindOfRPCServer;
} else {
m_type = SatelliteServer::UnknownType;
}
}
///////////////////////////////////////////////////////////////////////////////
// InternalPageServer: LibEventServer + allowed URL checking
DECLARE_BOOST_TYPES(InternalPageServerImpl);
class InternalPageServerImpl : public LibEventServer {
public:
InternalPageServerImpl(const std::string &address, int port, int thread,
int timeoutSeconds) :
LibEventServer(address, port, thread, timeoutSeconds) {
}
void create(const std::set<std::string> &urls) {
m_allowedURLs = urls;
}
virtual bool shouldHandle(const std::string &cmd) {
String url(cmd.c_str(), cmd.size(), AttachLiteral);
for (set<string>::const_iterator iter = m_allowedURLs.begin();
iter != m_allowedURLs.end(); ++iter) {
Variant ret = preg_match
(String(iter->c_str(), iter->size(), AttachLiteral), url);
if (ret.toInt64() > 0) {
return true;
}
}
return false;
}
private:
std::set<std::string> m_allowedURLs;
};
class InternalPageServer : public SatelliteServer {
public:
explicit InternalPageServer(SatelliteServerInfoPtr info) {
InternalPageServerImplPtr server
(new TypedServer<InternalPageServerImpl, HttpRequestHandler>
(RuntimeOption::ServerIP, info->getPort(), info->getThreadCount(),
info->getTimeoutSeconds()));
server->create(info->getURLs());
m_server = server;
}
virtual void start() {
m_server->start();
}
virtual void stop() {
m_server->stop();
m_server->waitForEnd();
}
private:
ServerPtr m_server;
};
///////////////////////////////////////////////////////////////////////////////
// DanglingPageServer: same as LibEventServer
class DanglingPageServer : public SatelliteServer {
public:
explicit DanglingPageServer(SatelliteServerInfoPtr info) {
m_server = ServerPtr
(new TypedServer<LibEventServer, HttpRequestHandler>
(RuntimeOption::ServerIP, info->getPort(), info->getThreadCount(),
info->getTimeoutSeconds()));
}
virtual void start() {
m_server->start();
}
virtual void stop() {
m_server->stop();
m_server->waitForEnd();
}
private:
ServerPtr m_server;
};
///////////////////////////////////////////////////////////////////////////////
// RPCServer: LibEventServer + RPCRequestHandler
static IMPLEMENT_THREAD_LOCAL(RPCRequestHandler, s_rpc_request_handler);
class RPCServerImpl : public LibEventServer {
public:
RPCServerImpl(const std::string &address, SatelliteServerInfoPtr info)
: LibEventServer(address, info->getPort(), info->getThreadCount(),
info->getTimeoutSeconds()),
m_serverInfo(info) {
}
virtual RequestHandler *createRequestHandler() {
if (s_rpc_request_handler.isNull()) {
s_rpc_request_handler->setServerInfo(m_serverInfo);
return s_rpc_request_handler.get();
}
if (s_rpc_request_handler->needReset() ||
s_rpc_request_handler->incRequest() > m_serverInfo->getMaxRequest()) {
s_rpc_request_handler.destroy();
s_rpc_request_handler->setServerInfo(m_serverInfo);
s_rpc_request_handler->incRequest();
}
return s_rpc_request_handler.get();
}
virtual void releaseRequestHandler(RequestHandler *handler) {
// do nothing
}
virtual void onThreadExit(RequestHandler *handler) {
s_rpc_request_handler.destroy();
}
virtual bool supportReset() { return true; }
private:
SatelliteServerInfoPtr m_serverInfo;
};
class RPCServer : public SatelliteServer {
public:
explicit RPCServer(SatelliteServerInfoPtr info) {
m_server = ServerPtr(new RPCServerImpl(RuntimeOption::ServerIP, info));
}
virtual void start() {
m_server->start();
}
virtual void stop() {
m_server->stop();
m_server->waitForEnd();
}
private:
ServerPtr m_server;
};
///////////////////////////////////////////////////////////////////////////////
// SatelliteServer
SatelliteServerPtr SatelliteServer::Create(SatelliteServerInfoPtr info) {
SatelliteServerPtr satellite;
if (info->getPort()) {
switch (info->getType()) {
case KindOfInternalPageServer:
satellite = SatelliteServerPtr(new InternalPageServer(info));
break;
case KindOfDanglingPageServer:
satellite = SatelliteServerPtr(new DanglingPageServer(info));
break;
case KindOfRPCServer:
satellite = SatelliteServerPtr(new RPCServer(info));
break;
case KindOfXboxServer:
satellite = SatelliteServerPtr(new RPCServer(info));
break;
default:
assert(false);
}
if (satellite) {
satellite->setName(info->getName());
}
}
return satellite;
}
///////////////////////////////////////////////////////////////////////////////
}