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 
11 void 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 
25 WvStreamsDebuggerServer::Connection::Connection(IWvStream *s) :
26  WvStreamClone(s)
27 {
28 }
29 
30 
31 void WvStreamsDebuggerServer::Connection::result_cb(WvStringParm,
32  WvStringList &results)
33 {
34  send("-", results);
35 }
36 
37 
38 void WvStreamsDebuggerServer::Connection::send(WvStringParm code,
39  WvStringParm result)
40 {
41  WvStringList results;
42  results.append(result);
43  send(code, results);
44 }
45 
46 
47 void WvStreamsDebuggerServer::Connection::send(WvStringParm code,
48  WvStringList &results)
49 {
50  print("%s %s\n", wvtcl_escape(code), wvtcl_encode(results));
51 }
52 
53 
54 WvStreamsDebuggerServer::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 
92 WvStreamsDebuggerServer::~WvStreamsDebuggerServer()
93 {
94  WvIStreamList::globallist.unlink(&streams);
95 }
96 
97 
98 #ifndef _WIN32
99 void 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 
109 void WvStreamsDebuggerServer::unix_listener_close_cb()
110 {
111  log("Listener on %s closing\n", *unix_listener->src());
112 }
113 #endif
114 
115 void 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 
125 void WvStreamsDebuggerServer::tcp_listener_close_cb()
126 {
127  log("Listener on %s closing\n", *tcp_listener->src());
128 }
129 
130 
131 void 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 
141 void 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 
169 void 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 
WvStringList::popstr
WvString popstr()
get the first string in the list, or an empty string if the list is empty.
Definition: wvstringlist.cc:55
IWvStream
Definition: iwvstream.h:24
WvTCPListener
Class to easily create the Server side of a WvTCPConn.
Definition: wvtcplistener.h:16
WvString
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:329
WvLog
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
Definition: wvlog.h:56
wvtcl_escape
WvString wvtcl_escape(WvStringParm s, const WvStringMask &nasties=WVTCL_NASTY_SPACES)
tcl-escape a string.
Definition: wvtclstring.cc:128
wvtcl_encode
WvString wvtcl_encode(WvList< WvString > &l, const WvStringMask &nasties=WVTCL_NASTY_SPACES, const WvStringMask &splitchars=WVTCL_SPLITCHARS)
encode a tcl-style list.
Definition: wvtclstring.cc:221
WvIPPortAddr
An IP+Port address also includes a port number, with the resulting form www.xxx.yyy....
Definition: wvaddr.h:393
WvStreamClone
WvStreamClone simply forwards all requests to the "cloned" stream.
Definition: wvstreamclone.h:23
WvUnixListener
Server end of a Unix Sockets stream.
Definition: wvunixlistener.h:15
WvUnixListener::src
virtual const WvUnixAddr * src() const
src() is a bit of a misnomer, but it returns the socket address.
Definition: wvunixsocket.cc:244
WvUnixAddr
A Unix domain socket address is really just a filename.
Definition: wvaddr.h:429
WvStringList
This is a WvList of WvStrings, and is a really handy way to parse strings.
Definition: wvstringlist.h:27
WvTCPListener::src
virtual const WvIPPortAddr * src() const
src() is a bit of a misnomer, but it returns the listener port.
Definition: wvtcp.cc:462
wvtcl_decode
void wvtcl_decode(WvList< WvString > &l, WvStringParm _s, const WvStringMask &splitchars=WVTCL_SPLITCHARS, bool do_unescape=true)
split a tcl-style list.
Definition: wvtclstring.cc:386