WvStreams
uniclientconn.cc
1/*
2 * Worldvisions Tunnel Vision Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4 *
5 * Manages a connection between the UniConf client and daemon.
6 */
7#include "uniclientconn.h"
8#include "wvaddr.h"
9#include "wvtclstring.h"
10#include "strutils.h"
11
12/***** UniClientConn *****/
13
14/* This table is _very_ important!!!
15 *
16 * With UniConf, we promise to never remove or modify the behaviour of
17 * any of the commands listed here. If you want to modify anything,
18 * you'd better just add a new command instead. We keep track of the
19 * version of the UniConf protocol by the number of commands supported
20 * by the server.
21 *
22 * @see UniClientConn::Commands
23 */
24const UniClientConn::CommandInfo UniClientConn::cmdinfos[
25 UniClientConn::NUM_COMMANDS] = {
26 // requests
27 { "noop", "noop: verify that the connection is active" },
28 { "get", "get <key>: get the value of a key" },
29 { "set", "set <key> <value>: sets the value of a key" },
30 { "setv", "setv <key> <value> ...: set multiple key-value pairs" },
31 { "del", "del <key>: deletes the key" },
32 { "subt", "subt <key> <recurse?>: enumerates the children of a key" },
33 { "hchild", "hchild <key>: returns whether a key has children" },
34 { "commit", "commit: commits changes to disk" },
35 { "refresh", "refresh: refresh contents from disk" },
36 { "quit", "quit: kills the session nicely" },
37 { "help", "help: returns this help text" },
38
39 // command completion replies
40 { "OK", "OK <payload>: reply on command success" },
41 { "FAIL", "FAIL <payload>: reply on command failure" },
42 { "CHILD", "CHILD <key> TRUE / FALSE: key has children or not" },
43 { "ONEVAL", "ONEVAL <key> <value>: reply to a get" },
44
45 // partial replies
46 { "VAL", "VAL <key> <value>: intermediate reply value of a key" },
47 { "TEXT", "TEXT <text>: intermediate reply of a text message" },
48
49 // events
50 { "HELLO", "HELLO <version> <message>: sent by server on connection" },
51 { "NOTICE", "NOTICE <key> <oldval> <newval>: forget key and its children" },
52};
53
54
56 WvStreamClone(_s),
57 log(WvString("UniConf to %s", dst.isnull() && _s->src() ? *_s->src() : WvString(dst)),
58 WvLog::Debug5), closed(false), version(-1), payloadbuf("")
59{
60 log("Opened\n");
61}
62
63
64UniClientConn::~UniClientConn()
65{
66 close();
67}
68
69
71{
72 if (!closed)
73 {
74 closed = true;
76 log("Closed\n");
77 }
78}
79
80
81WvString UniClientConn::readmsg()
82{
83 WvString word;
84 while ((word = wvtcl_getword(msgbuf,
85 WVTCL_NASTY_NEWLINES,
86 false)).isnull())
87 {
88 // use lots of readahead to prevent unnecessary runs through select()
89 // during heavy data transfers.
90 char *line = getline(0, '\n', 20480);
91 if (line)
92 {
93 msgbuf.putstr(line);
94 msgbuf.put('\n');
95 }
96 else
97 {
99 {
100 // possibly left some incomplete command behind
101 msgbuf.zap();
102 }
103 return WvString::null;
104 }
105 }
106 if (!!word && 0)
107 log("Read: %s\n", word);
108 return word;
109}
110
111
112void UniClientConn::writemsg(WvStringParm msg)
113{
114 write(msg);
115 write("\n");
116 // log("Wrote: %s\n", msg);
117}
118
119
121{
122 WvString buf;
123 return readcmd(buf);
124}
125
127{
128 WvString msg(readmsg());
129 if (msg.isnull())
130 return NONE;
131
132 // extract command, leaving the remainder in payloadbuf
133 payloadbuf.reset(msg);
134 command = readarg();
135
136 if (command.isnull())
137 return NONE;
138
139 for (int i = 0; i < NUM_COMMANDS; ++i)
140 if (strcasecmp(cmdinfos[i].name, command.cstr()) == 0)
141 return Command(i);
142 return INVALID;
143}
144
145
150
151
153{
154 if (msg)
155 write(WvString("%s %s\n", cmdinfos[cmd].name, msg));
156 else
157 write(WvString("%s\n", cmdinfos[cmd].name));
158}
159
160
162{
163 writecmd(REPLY_OK, payload);
164}
165
166
168{
169 writecmd(REPLY_FAIL, payload);
170}
171
172
174{
175 if (value == WvString::null)
177 else
179}
180
181
186
187
192
193
void writeonevalue(const UniConfKey &key, WvStringParm value)
Writes a PART_VALUE message.
virtual void close()
Close this stream.
Command readcmd()
Reads a command from the connection.
void writetext(WvStringParm text)
Writes a PART_TEXT message.
void writecmd(Command command, WvStringParm payload=WvString::null)
Writes a command to the connection.
UniClientConn(IWvStream *_s, WvStringParm dst=WvString::null)
Create a wrapper around the supplied WvStream.
void writefail(WvStringParm payload="")
Writes a REPLY_FAIL message.
WvString readarg()
Reads the next argument from the command payload.
void writeok(WvStringParm payload="")
Writes a REPLY_OK message.
void writevalue(const UniConfKey &key, WvStringParm value)
Writes a PART_VALUE message.
Represents a UniConf key which is a path in a hierarchy structured much like the traditional Unix fil...
void put(const T *data, size_t count)
Writes the specified number of elements from the specified storage location into the buffer at its ta...
void reset(WvStringParm _str)
Resets the buffer contents to a new string.
Definition wvbuffer.cc:111
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
bool isnull() const
returns true if this string is null
const char * cstr() const
return a (const char *) for this string.
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.
virtual void close()
Close this stream.
virtual bool isok() const
return true if the stream is actually usable right now
virtual size_t write(const void *buf, size_t count)
Write data to the stream.
Definition wvstream.cc:532
char * getline(time_t wait_msec=0, char separator='\n', int readahead=1024)
Read up to one line of data from the stream and return a pointer to the internal buffer containing th...
WvString is an implementation of a simple and efficient printable-string class.
WvString spacecat(WvStringParm a, WvStringParm b, char sep=' ', bool onesep=false)
return the string formed by concatenating string 'a' and string 'b' with the 'sep' character between ...
Definition strutils.cc:114
WvString wvtcl_escape(WvStringParm s, const WvStringMask &nasties=WVTCL_NASTY_SPACES)
tcl-escape a string.
WvString wvtcl_getword(WvBuf &buf, const WvStringMask &splitchars=WVTCL_SPLITCHARS, bool do_unescape=true)
Get a single tcl word from an input buffer, and return the rest of the buffer untouched.