00001
00002
00003
00004
00005
00006 #include "wvstreamsdebuggerserver.h"
00007 #include "wvunixsocket.h"
00008 #include "wvtcplistener.h"
00009 #include "wvunixlistener.h"
00010
00011 void WvStreamsDebuggerServer::Connection::choose_salt()
00012 {
00013 const int salt_size = 8;
00014 const int salt_alphabet_size = 26+26+10;
00015 const char salt_chars[salt_alphabet_size+1] =
00016 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
00017
00018 salt.setsize(salt_size+1);
00019 for (int i=0; i<salt_size; ++i)
00020 salt.edit()[i] = salt_chars[rand() % salt_alphabet_size];
00021 salt.edit()[salt_size] = '\0';
00022 }
00023
00024
00025 WvStreamsDebuggerServer::Connection::Connection(IWvStream *s) :
00026 WvStreamClone(s)
00027 {
00028 }
00029
00030
00031 void WvStreamsDebuggerServer::Connection::result_cb(WvStringParm,
00032 WvStringList &results)
00033 {
00034 send("-", results);
00035 }
00036
00037
00038 void WvStreamsDebuggerServer::Connection::send(WvStringParm code,
00039 WvStringParm result)
00040 {
00041 WvStringList results;
00042 results.append(result);
00043 send(code, results);
00044 }
00045
00046
00047 void WvStreamsDebuggerServer::Connection::send(WvStringParm code,
00048 WvStringList &results)
00049 {
00050 print("%s %s\n", wvtcl_escape(code), wvtcl_encode(results));
00051 }
00052
00053
00054 WvStreamsDebuggerServer::WvStreamsDebuggerServer(const WvUnixAddr &unix_addr,
00055 AuthCallback _auth_cb,
00056 const WvIPPortAddr &tcp_addr) :
00057 log("WvStreamsDebuggerServer", WvLog::Debug3),
00058 unix_listener(NULL),
00059 tcp_listener(NULL),
00060 auth_cb(_auth_cb)
00061 {
00062 WvIStreamList::globallist.append(&streams, false, "debugger streams");
00063
00064 #ifndef _WIN32
00065 if (true)
00066 {
00067 unix_listener = new WvUnixListener(unix_addr, 0700);
00068 unix_listener->set_wsname("wsd listener on %s", unix_addr);
00069 unix_listener->onaccept(
00070 wv::bind(&WvStreamsDebuggerServer::unix_listener_cb, this, _1));
00071 unix_listener->setclosecallback(
00072 wv::bind(&WvStreamsDebuggerServer::unix_listener_close_cb, this));
00073 streams.append(unix_listener, true, "debugger unix listener");
00074 log("Listening on %s\n", unix_addr);
00075 }
00076 #endif
00077
00078 if (tcp_addr != WvIPPortAddr())
00079 {
00080 tcp_listener = new WvTCPListener(tcp_addr);
00081 tcp_listener->set_wsname("wsd listener on %s", tcp_addr);
00082 tcp_listener->onaccept(
00083 wv::bind(&WvStreamsDebuggerServer::tcp_listener_cb, this, _1));
00084 tcp_listener->setclosecallback(
00085 wv::bind(&WvStreamsDebuggerServer::tcp_listener_close_cb, this));
00086 streams.append(tcp_listener, true, "debugger tcp listener");
00087 log("Listening on %s\n", tcp_addr);
00088 }
00089 }
00090
00091
00092 WvStreamsDebuggerServer::~WvStreamsDebuggerServer()
00093 {
00094 WvIStreamList::globallist.unlink(&streams);
00095 }
00096
00097
00098 #ifndef _WIN32
00099 void WvStreamsDebuggerServer::unix_listener_cb(IWvStream *unix_conn)
00100 {
00101 log("Accepted connection from %s\n", *unix_conn->src());
00102 Connection *conn = new Connection(unix_conn);
00103 conn->setcallback(wv::bind(&WvStreamsDebuggerServer::ready_cb, this,
00104 wv::ref(*conn)));
00105 streams.append(conn, true, "debugger unix connection");
00106 }
00107
00108
00109 void WvStreamsDebuggerServer::unix_listener_close_cb()
00110 {
00111 log("Listener on %s closing\n", *unix_listener->src());
00112 }
00113 #endif
00114
00115 void WvStreamsDebuggerServer::tcp_listener_cb(IWvStream *tcp_conn)
00116 {
00117 log("Accepted connection from %s\n", *tcp_conn->src());
00118 Connection *conn = new Connection(tcp_conn);
00119 conn->setcallback(wv::bind(&WvStreamsDebuggerServer::ready_cb, this,
00120 wv::ref(*conn)));
00121 streams.append(conn, true, "debugger tcp connection");
00122 }
00123
00124
00125 void WvStreamsDebuggerServer::tcp_listener_close_cb()
00126 {
00127 log("Listener on %s closing\n", *tcp_listener->src());
00128 }
00129
00130
00131 void WvStreamsDebuggerServer::auth_request_cb(Connection &s)
00132 {
00133 s.choose_salt();
00134 s.send("AUTH", s.salt);
00135
00136 s.setcallback(wv::bind(&WvStreamsDebuggerServer::auth_response_cb, this,
00137 wv::ref(s)));
00138 }
00139
00140
00141 void WvStreamsDebuggerServer::auth_response_cb(Connection &s)
00142 {
00143 const char *line = s.getline();
00144 if (line == NULL)
00145 return;
00146
00147 WvStringList args;
00148 wvtcl_decode(args, line);
00149
00150 WvString username = args.popstr();
00151 WvString encoded_salted_password = args.popstr();
00152
00153 if (!auth_cb || !username || !encoded_salted_password
00154 || !auth_cb(username, s.salt, encoded_salted_password))
00155 {
00156 s.send("ERROR", "Authentication failure");
00157 s.setcallback(wv::bind(&WvStreamsDebuggerServer::auth_request_cb,
00158 this, wv::ref(s)));
00159 }
00160 else
00161 {
00162 s.send("OK", "Authenticated");
00163 s.setcallback(wv::bind(&WvStreamsDebuggerServer::ready_cb, this,
00164 wv::ref(s)));
00165 }
00166 }
00167
00168
00169 void WvStreamsDebuggerServer::ready_cb(Connection &s)
00170 {
00171 const char *line = s.getline();
00172 if (line == NULL)
00173 return;
00174
00175 WvStringList args;
00176 wvtcl_decode(args, line);
00177
00178 WvString cmd = args.popstr();
00179 if (!cmd)
00180 {
00181 s.send("ERROR", "Empty command");
00182 return;
00183 }
00184
00185 WvString result = s.debugger.run(cmd, args,
00186 wv::bind(&Connection::result_cb, &s,
00187 _1, _2));
00188 if (!!result)
00189 s.send("ERROR", result);
00190 else
00191 s.send("OK", "Command successful");
00192 }
00193
00194