2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 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 +----------------------------------------------------------------------+
17 #include "hphp/runtime/server/replay_transport.h"
18 #include "hphp/runtime/base/string_util.h"
19 #include "hphp/runtime/base/zend-functions.h"
20 #include "hphp/runtime/base/zend-string.h"
21 #include "hphp/util/process.h"
24 ///////////////////////////////////////////////////////////////////////////////
26 void ReplayTransport::recordInput(Transport
* transport
, const char *filename
) {
32 snprintf(buf
, sizeof(buf
), "%u", Process::GetProcessId());
33 hdf
["pid"] = string(buf
);
34 snprintf(buf
, sizeof(buf
), "%" PRIx64
, (int64_t)Process::GetThreadId());
35 hdf
["tid"] = string(buf
);
36 snprintf(buf
, sizeof(buf
), "%u", Process::GetThreadPid());
37 hdf
["tpid"] = string(buf
);
39 hdf
["cmd"] = static_cast<int>(transport
->getMethod());
40 hdf
["url"] = transport
->getUrl();
41 hdf
["remote_host"] = transport
->getRemoteHost();
42 hdf
["remote_port"] = transport
->getRemotePort();
44 transport
->getHeaders(m_requestHeaders
);
46 for (HeaderMap::const_iterator iter
= m_requestHeaders
.begin();
47 iter
!= m_requestHeaders
.end(); ++iter
) {
48 for (unsigned int i
= 0; i
< iter
->second
.size(); i
++) {
49 Hdf header
= hdf
["headers"][index
++];
50 header
["name"] = iter
->first
;
51 header
["value"] = iter
->second
[i
];
56 const void *data
= transport
->getPostData(size
);
59 char *encoded
= string_uuencode((const char *)data
, size
, len
);
60 hdf
["post"] = encoded
;
69 void ReplayTransport::replayInput(const char *filename
) {
74 void ReplayTransport::replayInput(Hdf hdf
) {
79 void ReplayTransport::replayInputImpl() {
80 String postData
= StringUtil::UUDecode(m_hdf
["post"].get(""));
81 m_postData
= string(postData
.data(), postData
.size());
82 m_requestHeaders
.clear();
83 for (Hdf hdf
= m_hdf
["headers"].firstChild(); hdf
.exists();
85 m_requestHeaders
[hdf
["name"].get("")].push_back(hdf
["value"].get(""));
89 const char *ReplayTransport::getUrl() {
90 return m_hdf
["url"].get("");
93 const char *ReplayTransport::getRemoteHost() {
94 return m_hdf
["remote_host"].get("");
96 uint16_t ReplayTransport::getRemotePort() {
97 return m_hdf
["remote_port"].getUInt16(0);
100 const void *ReplayTransport::getPostData(int &size
) {
101 size
= m_postData
.size();
102 return m_postData
.data();
105 Transport::Method
ReplayTransport::getMethod() {
106 return (Transport::Method
)m_hdf
["cmd"].getInt32();
109 std::string
ReplayTransport::getHeader(const char *name
) {
111 if (m_requestHeaders
.find(name
) != m_requestHeaders
.end()) {
112 assert(!m_requestHeaders
[name
].empty());
113 return m_requestHeaders
[name
][0];
118 void ReplayTransport::getHeaders(HeaderMap
&headers
) {
119 headers
= m_requestHeaders
;
122 void ReplayTransport::addHeaderImpl(const char *name
, const char *value
) {
123 assert(name
&& value
);
124 m_responseHeaders
[name
].push_back(value
);
127 void ReplayTransport::removeHeaderImpl(const char *name
) {
129 m_responseHeaders
.erase(name
);
132 void ReplayTransport::sendImpl(const void *data
, int size
, int code
,
136 m_response
= "HTTP/1.1 ";
137 m_response
+= boost::lexical_cast
<string
>(code
);
139 m_response
+= (m_code
== 200 ? "OK" : "Internal Server Error");
140 m_response
+= "\r\n";
142 for (HeaderMap::const_iterator iter
= m_responseHeaders
.begin();
143 iter
!= m_responseHeaders
.end(); ++iter
) {
144 for (unsigned int i
= 0; i
< iter
->second
.size(); i
++) {
145 m_response
+= iter
->first
;
147 m_response
+= iter
->second
[i
];
148 m_response
+= "\r\n";
152 m_response
+= "\r\n";
153 m_response
.append((const char *)data
, size
);
154 m_response
+= "\r\n";
157 ///////////////////////////////////////////////////////////////////////////////