WvStreams
|
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