WvStreams
wvstreamsdebuggerserver.cc
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
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