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