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(WvUnixAddr unix_addr,
00054 AuthCallback _auth_cb,
00055 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 if (true)
00064 {
00065 unix_listener = new WvUnixListener(unix_addr, 0700);
00066 unix_listener->set_wsname("wsd listener on %s", unix_addr);
00067 unix_listener->setcallback(WvStreamCallback(this,
00068 &WvStreamsDebuggerServer::unix_listener_cb), NULL);
00069 unix_listener->setclosecallback(IWvStreamCallback(this,
00070 &WvStreamsDebuggerServer::unix_listener_close_cb));
00071 streams.append(unix_listener, true);
00072 log("Listening on %s\n", unix_addr);
00073 }
00074
00075 if (tcp_addr != WvIPPortAddr())
00076 {
00077 tcp_listener = new WvTCPListener(tcp_addr);
00078 tcp_listener->set_wsname("wsd listener on %s", tcp_addr);
00079 tcp_listener->setcallback(WvStreamCallback(this,
00080 &WvStreamsDebuggerServer::tcp_listener_cb), NULL);
00081 tcp_listener->setclosecallback(IWvStreamCallback(this,
00082 &WvStreamsDebuggerServer::tcp_listener_close_cb));
00083 streams.append(tcp_listener, true);
00084 log("Listening on %s\n", tcp_addr);
00085 }
00086 }
00087
00088
00089 WvStreamsDebuggerServer::~WvStreamsDebuggerServer()
00090 {
00091 WvIStreamList::globallist.unlink(&streams);
00092 }
00093
00094
00095 void WvStreamsDebuggerServer::unix_listener_cb(WvStream &, void *)
00096 {
00097 WvUnixConn *unix_conn = unix_listener->accept();
00098 if (!unix_conn)
00099 return;
00100 log("Accepted connection from %s\n", *unix_conn->src());
00101 Connection *conn = new Connection(unix_conn);
00102 conn->setcallback(WvStreamCallback(this,
00103 &WvStreamsDebuggerServer::ready_cb), NULL);
00104 streams.append(conn, true);
00105 }
00106
00107
00108 void WvStreamsDebuggerServer::unix_listener_close_cb(WvStream &)
00109 {
00110 log("Listener on %s closing\n", *unix_listener->src());
00111 }
00112
00113
00114 void WvStreamsDebuggerServer::tcp_listener_cb(WvStream &, void *)
00115 {
00116 WvTCPConn *tcp_conn = tcp_listener->accept();
00117 if (!tcp_conn)
00118 return;
00119 log("Accepted connection from %s\n", *tcp_conn->src());
00120 Connection *conn = new Connection(tcp_conn);
00121 conn->setcallback(WvStreamCallback(this,
00122 &WvStreamsDebuggerServer::ready_cb), NULL);
00123 streams.append(conn, true);
00124 }
00125
00126
00127 void WvStreamsDebuggerServer::tcp_listener_close_cb(WvStream &)
00128 {
00129 log("Listener on %s closing\n", *tcp_listener->src());
00130 }
00131
00132
00133 void WvStreamsDebuggerServer::auth_request_cb(WvStream &_s, void *)
00134 {
00135 Connection &s = static_cast<Connection &>(_s);
00136
00137 s.choose_salt();
00138 s.send("AUTH", s.salt);
00139
00140 s.setcallback(WvStreamCallback(this,
00141 &WvStreamsDebuggerServer::auth_response_cb), NULL);
00142 }
00143
00144
00145 void WvStreamsDebuggerServer::auth_response_cb(WvStream &_s, void *)
00146 {
00147 Connection &s = static_cast<Connection &>(_s);
00148 const char *line = s.getline();
00149 if (line == NULL)
00150 return;
00151
00152 WvStringList args;
00153 wvtcl_decode(args, line);
00154
00155 WvString username = args.popstr();
00156 WvString encoded_salted_password = args.popstr();
00157
00158 if (!auth_cb || !username || !encoded_salted_password
00159 || !auth_cb(username, s.salt, encoded_salted_password))
00160 {
00161 s.send("ERROR", "Authentication failure");
00162 s.setcallback(WvStreamCallback(this,
00163 &WvStreamsDebuggerServer::auth_request_cb), NULL);
00164 }
00165 else
00166 {
00167 s.send("OK", "Authenticated");
00168 s.setcallback(WvStreamCallback(this,
00169 &WvStreamsDebuggerServer::ready_cb), NULL);
00170 }
00171 }
00172
00173
00174 void WvStreamsDebuggerServer::ready_cb(WvStream &_s, void *)
00175 {
00176 Connection &s = static_cast<Connection &>(_s);
00177 const char *line = s.getline();
00178 if (line == NULL)
00179 return;
00180
00181 WvStringList args;
00182 wvtcl_decode(args, line);
00183
00184 WvString cmd = args.popstr();
00185 if (!cmd)
00186 {
00187 s.send("ERROR", "Empty command");
00188 return;
00189 }
00190
00191 WvString result = s.debugger.run(cmd, args,
00192 WvStreamsDebugger::ResultCallback(&s, &Connection::result_cb));
00193 if (!!result)
00194 s.send("ERROR", result);
00195 else
00196 s.send("OK", "Command successful");
00197 }
00198
00199
00200 void WvStreamsDebuggerServer::close_cb(WvStream &_s)
00201 {
00202 streams.unlink(&_s);
00203 }