make #includes consistent
[hiphop-php.git] / hphp / runtime / eval / debugger / debugger_server.cpp
blobfba6eac6127760f3a2ba3546a5bf50772bb505e6
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010- 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/eval/debugger/debugger_server.h"
18 #include "hphp/runtime/eval/debugger/debugger_client.h"
19 #include "hphp/runtime/eval/debugger/debugger.h"
20 #include "hphp/runtime/base/runtime_option.h"
21 #include "hphp/util/network.h"
22 #include "hphp/util/logger.h"
24 #define POLLING_SECONDS 1
26 namespace HPHP { namespace Eval {
27 ///////////////////////////////////////////////////////////////////////////////
28 TRACE_SET_MOD(debugger);
30 DebuggerServer DebuggerServer::s_debugger_server;
32 bool DebuggerServer::Start() {
33 TRACE(2, "DebuggerServer::Start\n");
34 if (RuntimeOption::EnableDebuggerServer) {
35 Debugger::SetTextColors();
37 // Some server commands pre-formatted texts with color for clients. Loading
38 // a set of default colors for better display.
39 Hdf hdf;
40 DebuggerClient::LoadColors(hdf);
42 return s_debugger_server.start();
44 return true;
47 void DebuggerServer::Stop() {
48 TRACE(2, "DebuggerServer::Stop\n");
49 if (RuntimeOption::EnableDebuggerServer) {
50 s_debugger_server.stop();
54 ///////////////////////////////////////////////////////////////////////////////
56 DebuggerServer::DebuggerServer()
57 : m_serverThread(this, &DebuggerServer::accept), m_stopped(false) {
58 TRACE(2, "DebuggerServer::DebuggerServer\n");
61 DebuggerServer::~DebuggerServer() {
62 TRACE(2, "DebuggerServer::~DebuggerServer\n");
63 m_stopped = true;
64 m_serverThread.waitForEnd();
67 bool DebuggerServer::start() {
68 TRACE(2, "DebuggerServer::start\n");
69 int port = RuntimeOption::DebuggerServerPort;
70 int backlog = 128;
72 Util::HostEnt result;
73 if (!Util::safe_gethostbyname("0.0.0.0", result)) {
74 return false;
76 struct sockaddr_in la;
77 memcpy((char*)&la.sin_addr, result.hostbuf.h_addr,
78 result.hostbuf.h_length);
79 la.sin_family = result.hostbuf.h_addrtype;
80 la.sin_port = htons((unsigned short)port);
82 m_sock = new Socket(socket(PF_INET, SOCK_STREAM, 0), PF_INET, "0.0.0.0",
83 port);
85 int yes = 1;
86 setsockopt(m_sock->fd(), SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
88 if (!m_sock->valid()) {
89 Logger::Error("unable to create debugger server socket");
90 return false;
92 if (bind(m_sock->fd(), (struct sockaddr *)&la, sizeof(la)) < 0) {
93 Logger::Error("unable to bind to port %d for debugger server", port);
94 return false;
96 if (listen(m_sock->fd(), backlog) < 0) {
97 Logger::Error("unable to listen on port %d for debugger server", port);
98 return false;
101 m_serverThread.start();
102 return true;
105 void DebuggerServer::stop() {
106 TRACE(2, "DebuggerServer::stop\n");
107 m_stopped = true;
108 m_serverThread.waitForEnd();
111 void DebuggerServer::accept() {
112 TRACE(2, "DebuggerServer::accept\n");
113 // server loop
114 while (!m_stopped) {
115 struct pollfd fds[1];
116 fds[0].fd = m_sock->fd();
117 fds[0].events = POLLIN|POLLERR|POLLHUP;
118 int ret = poll(fds, 1, POLLING_SECONDS * 1000);
119 if (ret > 0) {
120 bool in = (fds[0].revents & POLLIN);
121 if (in) {
122 struct sockaddr sa;
123 socklen_t salen = sizeof(sa);
124 try {
125 Socket *new_sock = new Socket(::accept(m_sock->fd(), &sa, &salen),
126 m_sock->getType());
127 SmartPtr<Socket> ret(new_sock);
128 if (new_sock->valid()) {
129 Debugger::CreateProxy(ret, false);
130 } else {
131 Logger::Error("unable to accept incoming debugger request");
133 } catch (Exception &e) {
134 Logger::Error("%s", e.getMessage().c_str());
135 } catch (std::exception &e) {
136 Logger::Error("%s", e.what());
137 } catch (...) {
138 Logger::Error("(unknown exception was thrown)");
141 } // else timed out, then we have a chance to check m_stopped bit
142 // cleanup the dummy sandbox threads it created
143 Debugger::CleanupDummySandboxThreads();
146 m_sock.reset();
149 ///////////////////////////////////////////////////////////////////////////////