Arquivos
hhvm/hphp/runtime/ext/ext_server.cpp
T
smith c646a30002 Litstr must die, episode III.
Many callsites of Array.set(litstr, ...)
2013-04-23 12:57:40 -07:00

251 linhas
8.0 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 1997-2010 The PHP Group |
+----------------------------------------------------------------------+
| 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/ext/ext_server.h>
#include <runtime/base/server/satellite_server.h>
#include <runtime/base/server/pagelet_server.h>
#include <runtime/base/server/xbox_server.h>
#include <runtime/base/server/http_protocol.h>
#include <runtime/base/runtime_option.h>
#include <runtime/base/util/string_buffer.h>
#include <runtime/base/server/rpc_request_handler.h>
#define DANGLING_HEADER "HPHP_DANGLING"
namespace HPHP {
IMPLEMENT_DEFAULT_EXTENSION(server);
///////////////////////////////////////////////////////////////////////////////
// dangling server
bool f_dangling_server_proxy_old_request() {
static bool s_detected_dangling_server = true;
if (!s_detected_dangling_server ||
SatelliteServerInfo::DanglingServerPort == 0) {
return false;
}
Transport *transport = g_context->getTransport();
if (transport == NULL) {
return false;
}
if (!transport->getHeader(DANGLING_HEADER).empty()) {
// if we are processing a dangling server request, do not do it again
return false;
}
string url = "http://localhost:" +
lexical_cast<string>(SatelliteServerInfo::DanglingServerPort) +
transport->getServerObject();
int code = 0;
std::string error;
StringBuffer response;
HeaderMap headers;
headers[DANGLING_HEADER].push_back("1");
if (!HttpProtocol::ProxyRequest(transport, false, url, code, error,
response, &headers)) {
s_detected_dangling_server = false;
return false;
}
transport->setResponse(code, "dangling_server_proxy_old_request");
echo(response.detach());
return true;
}
bool f_dangling_server_proxy_new_request(CStrRef host) {
if (host.empty()) {
raise_warning("proxy new request needs host name");
return false;
}
Transport *transport = g_context->getTransport();
if (transport == NULL) {
return false;
}
if (!transport->getHeader(DANGLING_HEADER).empty()) {
// if we are processing a dangling server request, do not do it again
return false;
}
string url = string("http://") + host.data() + ":" +
lexical_cast<string>(RuntimeOption::ServerPort) +
transport->getServerObject();
int code = 0;
std::string error;
StringBuffer response;
HeaderMap headers;
headers[DANGLING_HEADER].push_back("1");
if (!HttpProtocol::ProxyRequest(transport, false, url, code, error,
response, &headers)) {
return false;
}
transport->setResponse(code, "dangling_server_proxy_new_request");
echo(response.detach());
return true;
}
///////////////////////////////////////////////////////////////////////////////
// Pagelet Server
const int64_t k_PAGELET_NOT_READY = PAGELET_NOT_READY;
const int64_t k_PAGELET_READY = PAGELET_READY;
const int64_t k_PAGELET_DONE = PAGELET_DONE;
bool f_pagelet_server_is_enabled() {
return PageletServer::Enabled();
}
static const StaticString s_Host("Host");
Object f_pagelet_server_task_start(CStrRef url,
CArrRef headers /* = null_array */,
CStrRef post_data /* = null_string */,
CArrRef files /* = null_array */) {
String remote_host;
Transport *transport = g_context->getTransport();
if (transport) {
remote_host = transport->getRemoteHost();
if (!headers.exists(s_Host) && RuntimeOption::SandboxMode) {
Array tmp = headers;
tmp.set(s_Host, transport->getHeader("Host"));
return PageletServer::TaskStart(url, tmp, remote_host, post_data, files);
}
}
return PageletServer::TaskStart(url, headers, remote_host, post_data);
}
int64_t f_pagelet_server_task_status(CObjRef task) {
return PageletServer::TaskStatus(task);
}
String f_pagelet_server_task_result(CObjRef task, VRefParam headers,
VRefParam code, int64_t timeout_ms /* = 0 */) {
Array rheaders;
int rcode;
String response = PageletServer::TaskResult(task, rheaders, rcode,
timeout_ms);
headers = rheaders;
code = rcode;
return response;
}
void f_pagelet_server_flush() {
ExecutionContext *context = g_context.getNoCheck();
Transport *transport = context->getTransport();
if (transport && transport->getThreadType() == Transport::PageletThread) {
// this method is only meaningful in a pagelet thread
context->obFlushAll();
String content = context->obDetachContents();
string s(content.data(), content.size());
if (!s.empty()) {
PageletServer::AddToPipeline(s);
}
}
}
///////////////////////////////////////////////////////////////////////////////
// xbox
bool f_xbox_send_message(CStrRef msg, VRefParam ret, int64_t timeout_ms,
CStrRef host /* = "localhost" */) {
return XboxServer::SendMessage(msg, ret, timeout_ms, host);
}
bool f_xbox_post_message(CStrRef msg, CStrRef host /* = "localhost" */) {
return XboxServer::PostMessage(msg, host);
}
Object f_xbox_task_start(CStrRef message) {
return XboxServer::TaskStart(message);
}
bool f_xbox_task_status(CObjRef task) {
return XboxServer::TaskStatus(task);
}
int64_t f_xbox_task_result(CObjRef task, int64_t timeout_ms, VRefParam ret) {
return XboxServer::TaskResult(task, timeout_ms, ret);
}
Variant f_xbox_process_call_message(CStrRef msg) {
Variant v = unserialize_from_string(msg);
if (!v.isArray()) {
raise_error("Error decoding xbox call message");
}
Array arr = v.toArray();
if (arr.size() != 2 || !arr.exists(0) || !arr.exists(1)) {
raise_error("Error decoding xbox call message");
}
Variant fn = arr.rvalAt(0);
if (fn.isArray()) {
Array farr = fn.toArray();
if (!array_is_valid_callback(farr)) {
raise_error("Error decoding xbox call message");
}
} else if (!fn.isString()) {
raise_error("Error decoding xbox call message");
}
Variant args = arr.rvalAt(1);
if (!args.isArray()) {
raise_error("Error decoding xbox call message");
}
return vm_call_user_func(fn, args.toArray());
}
int64_t f_xbox_get_thread_timeout() {
XboxServerInfoPtr server_info = XboxServer::GetServerInfo();
if (server_info) {
return server_info->getMaxDuration();
}
throw Exception("Not an xbox worker!");
}
void f_xbox_set_thread_timeout(int timeout) {
if (timeout < 0) {
raise_warning("Cannot set timeout/duration to a negative number.");
return;
}
XboxServerInfoPtr server_info = XboxServer::GetServerInfo();
if (server_info) {
server_info->setMaxDuration(timeout);
} else {
throw Exception("Not an xbox worker!");
}
}
void f_xbox_schedule_thread_reset() {
RPCRequestHandler *handler = XboxServer::GetRequestHandler();
if (handler) {
handler->setReset();
} else {
throw Exception("Not an xbox worker!");
}
}
int64_t f_xbox_get_thread_time() {
RPCRequestHandler *handler = XboxServer::GetRequestHandler();
if (handler) {
return time(NULL) - handler->getCreationTime();
}
throw Exception("Not an xbox worker!");
}
///////////////////////////////////////////////////////////////////////////////
}