WvStreams
wvstreamsdebuggerserver.cc
1/*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4 *
5 */
6#include "wvstreamsdebuggerserver.h"
7#include "wvunixsocket.h"
8#include "wvtcplistener.h"
9#include "wvunixlistener.h"
10
11void WvStreamsDebuggerServer::Connection::choose_salt()
12{
13 const int salt_size = 8;
14 const int salt_alphabet_size = 26+26+10;
15 const char salt_chars[salt_alphabet_size+1] =
16 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
17
18 salt.setsize(salt_size+1);
19 for (int i=0; i<salt_size; ++i)
20 salt.edit()[i] = salt_chars[rand() % salt_alphabet_size];
21 salt.edit()[salt_size] = '\0';
22}
23
24
25WvStreamsDebuggerServer::Connection::Connection(IWvStream *s) :
27{
28}
29
30
31void WvStreamsDebuggerServer::Connection::result_cb(WvStringParm,
32 WvStringList &results)
33{
34 send("-", results);
35}
36
37
38void WvStreamsDebuggerServer::Connection::send(WvStringParm code,
39 WvStringParm result)
40{
41 WvStringList results;
42 results.append(result);
43 send(code, results);
44}
45
46
47void WvStreamsDebuggerServer::Connection::send(WvStringParm code,
48 WvStringList &results)
49{
50 print("%s %s\n", wvtcl_escape(code), wvtcl_encode(results));
51}
52
53
54WvStreamsDebuggerServer::WvStreamsDebuggerServer(const WvUnixAddr &unix_addr,
55 AuthCallback _auth_cb,
56 const WvIPPortAddr &tcp_addr) :
57 log("WvStreamsDebuggerServer", WvLog::Debug3),
58 unix_listener(NULL),
59 tcp_listener(NULL),
60 auth_cb(_auth_cb)
61{
62 WvIStreamList::globallist.append(&streams, false, "debugger streams");
63
64#ifndef _WIN32
65 if (true)
66 {
67 unix_listener = new WvUnixListener(unix_addr, 0700);
68 unix_listener->set_wsname("wsd listener on %s", unix_addr);
69 unix_listener->onaccept(
70 wv::bind(&WvStreamsDebuggerServer::unix_listener_cb, this, _1));
71 unix_listener->setclosecallback(
72 wv::bind(&WvStreamsDebuggerServer::unix_listener_close_cb, this));
73 streams.append(unix_listener, true, "debugger unix listener");
74 log("Listening on %s\n", unix_addr);
75 }
76#endif
77
78 if (tcp_addr != WvIPPortAddr())
79 {
80 tcp_listener = new WvTCPListener(tcp_addr);
81 tcp_listener->set_wsname("wsd listener on %s", tcp_addr);
82 tcp_listener->onaccept(
83 wv::bind(&WvStreamsDebuggerServer::tcp_listener_cb, this, _1));
84 tcp_listener->setclosecallback(
85 wv::bind(&WvStreamsDebuggerServer::tcp_listener_close_cb, this));
86 streams.append(tcp_listener, true, "debugger tcp listener");
87 log("Listening on %s\n", tcp_addr);
88 }
89}
90
91
92WvStreamsDebuggerServer::~WvStreamsDebuggerServer()
93{
94 WvIStreamList::globallist.unlink(&streams);
95}
96
97
98#ifndef _WIN32
99void WvStreamsDebuggerServer::unix_listener_cb(IWvStream *unix_conn)
100{
101 log("Accepted connection from %s\n", *unix_conn->src());
102 Connection *conn = new Connection(unix_conn);
103 conn->setcallback(wv::bind(&WvStreamsDebuggerServer::ready_cb, this,
104 wv::ref(*conn)));
105 streams.append(conn, true, "debugger unix connection");
106}
107
108
109void WvStreamsDebuggerServer::unix_listener_close_cb()
110{
111 log("Listener on %s closing\n", *unix_listener->src());
112}
113#endif
114
115void WvStreamsDebuggerServer::tcp_listener_cb(IWvStream *tcp_conn)
116{
117 log("Accepted connection from %s\n", *tcp_conn->src());
118 Connection *conn = new Connection(tcp_conn);
119 conn->setcallback(wv::bind(&WvStreamsDebuggerServer::ready_cb, this,
120 wv::ref(*conn)));
121 streams.append(conn, true, "debugger tcp connection");
122}
123
124
125void WvStreamsDebuggerServer::tcp_listener_close_cb()
126{
127 log("Listener on %s closing\n", *tcp_listener->src());
128}
129
130
131void WvStreamsDebuggerServer::auth_request_cb(Connection &s)
132{
133 s.choose_salt();
134 s.send("AUTH", s.salt);
135
136 s.setcallback(wv::bind(&WvStreamsDebuggerServer::auth_response_cb, this,
137 wv::ref(s)));
138}
139
140
141void WvStreamsDebuggerServer::auth_response_cb(Connection &s)
142{
143 const char *line = s.getline();
144 if (line == NULL)
145 return;
146
147 WvStringList args;
148 wvtcl_decode(args, line);
149
150 WvString username = args.popstr();
151 WvString encoded_salted_password = args.popstr();
152
153 if (!auth_cb || !username || !encoded_salted_password
154 || !auth_cb(username, s.salt, encoded_salted_password))
155 {
156 s.send("ERROR", "Authentication failure");
157 s.setcallback(wv::bind(&WvStreamsDebuggerServer::auth_request_cb,
158 this, wv::ref(s)));
159 }
160 else
161 {
162 s.send("OK", "Authenticated");
163 s.setcallback(wv::bind(&WvStreamsDebuggerServer::ready_cb, this,
164 wv::ref(s)));
165 }
166}
167
168
169void WvStreamsDebuggerServer::ready_cb(Connection &s)
170{
171 const char *line = s.getline();
172 if (line == NULL)
173 return;
174
175 WvStringList args;
176 wvtcl_decode(args, line);
177
178 WvString cmd = args.popstr();
179 if (!cmd)
180 {
181 s.send("ERROR", "Empty command");
182 return;
183 }
184
185 WvString result = s.debugger.run(cmd, args,
186 wv::bind(&Connection::result_cb, &s,
187 _1, _2));
188 if (!!result)
189 s.send("ERROR", result);
190 else
191 s.send("OK", "Command successful");
192}
193
194
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
An IP+Port address also includes a port number, with the resulting form www.xxx.yyy....
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
WvStreamClone simply forwards all requests to the "cloned" stream.
This is a WvList of WvStrings, and is a really handy way to parse strings.
WvString popstr()
get the first string in the list, or an empty string if the list is empty.
WvString is an implementation of a simple and efficient printable-string class.
Class to easily create the Server side of a WvTCPConn.
virtual const WvIPPortAddr * src() const
src() is a bit of a misnomer, but it returns the listener port.
Definition wvtcp.cc:462
A Unix domain socket address is really just a filename.
virtual const WvUnixAddr * src() const
src() is a bit of a misnomer, but it returns the socket address.
WvString wvtcl_encode(WvList< WvString > &l, const WvStringMask &nasties=WVTCL_NASTY_SPACES, const WvStringMask &splitchars=WVTCL_SPLITCHARS)
encode a tcl-style list.
WvString wvtcl_escape(WvStringParm s, const WvStringMask &nasties=WVTCL_NASTY_SPACES)
tcl-escape a string.
void wvtcl_decode(WvList< WvString > &l, WvStringParm _s, const WvStringMask &splitchars=WVTCL_SPLITCHARS, bool do_unescape=true)
split a tcl-style list.