2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 #include "hphp/runtime/server/replay-transport.h"
17 #include <folly/Conv.h>
19 #include "hphp/runtime/base/string-util.h"
20 #include "hphp/runtime/base/zend-functions.h"
21 #include "hphp/runtime/base/zend-string.h"
22 #include "hphp/runtime/base/config.h"
23 #include "hphp/runtime/server/http-protocol.h"
24 #include "hphp/util/process.h"
25 #include "hphp/util/safe-cast.h"
28 ///////////////////////////////////////////////////////////////////////////////
30 void ReplayTransport::recordInput(Transport
* transport
, const char *filename
) {
36 snprintf(buf
, sizeof(buf
), "%" PRId64
, (int64_t)getpid());
37 hdf
["pid"] = std::string(buf
);
38 snprintf(buf
, sizeof(buf
), "%" PRIx64
, (int64_t)Process::GetThreadId());
39 hdf
["tid"] = std::string(buf
);
40 snprintf(buf
, sizeof(buf
), "%u", Process::GetThreadPid());
41 hdf
["tpid"] = std::string(buf
);
43 hdf
["cmd"] = static_cast<int>(transport
->getMethod());
44 hdf
["url"] = transport
->getUrl();
45 hdf
["remote_host"] = transport
->getRemoteHost();
46 hdf
["remote_port"] = transport
->getRemotePort();
48 auto const& headers
= transport
->getHeaders();
49 for (auto const& pair
: headers
) {
50 m_requestHeaders
[pair
.first
] = pair
.second
;
53 for (HeaderMap::const_iterator iter
= m_requestHeaders
.begin();
54 iter
!= m_requestHeaders
.end(); ++iter
) {
55 for (unsigned int i
= 0; i
< iter
->second
.size(); i
++) {
56 Hdf header
= hdf
["headers"][index
++];
57 header
["name"] = iter
->first
;
58 header
["value"] = iter
->second
[i
];
63 const void *data
= transport
->getPostData(size
);
65 String encoded
= string_uuencode((const char *)data
, safe_cast
<int>(size
));
66 hdf
["post"] = encoded
.get()->data();
74 void ReplayTransport::replayInput(const char *filename
) {
75 std::string fname
= filename
;
76 Config::ParseConfigFile(fname
, m_ini
, m_hdf
);
80 void ReplayTransport::replayInput(Hdf hdf
) {
85 void ReplayTransport::replayInputImpl() {
86 String postData
= StringUtil::UUDecode(Config::GetString(m_ini
, m_hdf
, "post",
88 m_postData
= std::string(postData
.data(), postData
.size());
89 m_requestHeaders
.clear();
90 auto headers_callback
= [&](const IniSetting::Map
& ini_h
, const Hdf
& hdf_h
,
91 const std::string
& /*ini_h_key*/) {
92 m_requestHeaders
[Config::GetString(ini_h
, hdf_h
, "name",
93 "", false)].push_back(
94 Config::GetString(ini_h
, hdf_h
, "value", "", false)
97 Config::Iterate(headers_callback
, m_ini
, m_hdf
, "headers", false);
100 const char *ReplayTransport::getUrl() {
101 return Config::Get(m_ini
, m_hdf
, "url", "", false);
104 const char *ReplayTransport::getRemoteHost() {
105 return Config::Get(m_ini
, m_hdf
, "remote_host", "", false);
107 uint16_t ReplayTransport::getRemotePort() {
108 return Config::GetUInt16(m_ini
, m_hdf
, "remote_port", 0, false);
111 const void *ReplayTransport::getPostData(size_t &size
) {
112 size
= m_postData
.size();
113 return m_postData
.data();
116 Transport::Method
ReplayTransport::getMethod() {
117 return (Transport::Method
)Config::GetInt32(m_ini
, m_hdf
, "cmd", false);
120 std::string
ReplayTransport::getHeader(const char *name
) {
122 if (m_requestHeaders
.find(name
) != m_requestHeaders
.end()) {
123 assertx(!m_requestHeaders
[name
].empty());
124 return m_requestHeaders
[name
][0];
129 const HeaderMap
& ReplayTransport::getHeaders() {
130 return m_requestHeaders
;
133 void ReplayTransport::addHeaderImpl(const char *name
, const char *value
) {
134 assertx(name
&& value
);
135 m_responseHeaders
[name
].push_back(value
);
138 void ReplayTransport::removeHeaderImpl(const char *name
) {
140 m_responseHeaders
.erase(name
);
143 void ReplayTransport::sendImpl(const void* data
, int size
, int code
,
144 bool /*chunked*/, bool eom
) {
147 m_response
= "HTTP/1.1 ";
148 m_response
+= folly::to
<std::string
>(code
);
150 m_response
+= HttpProtocol::GetReasonString(m_code
);
151 m_response
+= "\r\n";
153 for (HeaderMap::const_iterator iter
= m_responseHeaders
.begin();
154 iter
!= m_responseHeaders
.end(); ++iter
) {
155 for (unsigned int i
= 0; i
< iter
->second
.size(); i
++) {
156 m_response
+= iter
->first
;
158 m_response
+= iter
->second
[i
];
159 m_response
+= "\r\n";
163 m_response
+= "\r\n";
164 m_response
.append((const char *)data
, size
);
165 m_response
+= "\r\n";
171 ///////////////////////////////////////////////////////////////////////////////