2 * Worldvisions Tunnel Vision Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
5 * Manages a connection between the UniConf client and daemon.
7 #include "uniclientconn.h"
9 #include "wvtclstring.h"
12 /***** UniClientConn *****/
14 /* This table is _very_ important!!!
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
22 * @see UniClientConn::Commands
24 const UniClientConn::CommandInfo
UniClientConn::cmdinfos
[
25 UniClientConn::NUM_COMMANDS
] = {
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" },
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" },
46 { "VAL", "VAL <key> <value>: intermediate reply value of a key" },
47 { "TEXT", "TEXT <text>: intermediate reply of a text message" },
50 { "HELLO", "HELLO <version> <message>: sent by server on connection" },
51 { "NOTICE", "NOTICE <key> <oldval> <newval>: forget key and its children" },
55 UniClientConn::UniClientConn(IWvStream
*_s
, WvStringParm dst
) :
57 log(WvString("UniConf to %s", dst
.isnull() && _s
->src() ? *_s
->src() : WvString(dst
)),
58 WvLog::Debug5
), closed(false), version(-1), payloadbuf("")
64 UniClientConn::~UniClientConn()
70 void UniClientConn::close()
75 WvStreamClone::close();
81 WvString
UniClientConn::readmsg()
84 while ((word
= wvtcl_getword(msgbuf
,
88 // use lots of readahead to prevent unnecessary runs through select()
89 // during heavy data transfers.
90 char *line
= getline(0, '\n', 20480);
98 if (!WvStreamClone::isok())
100 // possibly left some incomplete command behind
103 return WvString::null
;
107 log("Read: %s\n", word
);
112 void UniClientConn::writemsg(WvStringParm msg
)
116 // log("Wrote: %s\n", msg);
120 UniClientConn::Command
UniClientConn::readcmd()
126 UniClientConn::Command
UniClientConn::readcmd(WvString
&command
)
128 WvString
msg(readmsg());
132 // extract command, leaving the remainder in payloadbuf
133 payloadbuf
.reset(msg
);
136 if (command
.isnull())
139 for (int i
= 0; i
< NUM_COMMANDS
; ++i
)
140 if (strcasecmp(cmdinfos
[i
].name
, command
.cstr()) == 0)
146 WvString
UniClientConn::readarg()
148 return wvtcl_getword(payloadbuf
);
152 void UniClientConn::writecmd(UniClientConn::Command cmd
, WvStringParm msg
)
155 write(WvString("%s %s\n", cmdinfos
[cmd
].name
, msg
));
157 write(WvString("%s\n", cmdinfos
[cmd
].name
));
161 void UniClientConn::writeok(WvStringParm payload
)
163 writecmd(REPLY_OK
, payload
);
167 void UniClientConn::writefail(WvStringParm payload
)
169 writecmd(REPLY_FAIL
, payload
);
173 void UniClientConn::writevalue(const UniConfKey
&key
, WvStringParm value
)
175 if (value
== WvString::null
)
176 writecmd(PART_VALUE
, wvtcl_escape(key
));
178 writecmd(PART_VALUE
, spacecat(wvtcl_escape(key
), wvtcl_escape(value
)));
182 void UniClientConn::writeonevalue(const UniConfKey
&key
, WvStringParm value
)
184 writecmd(REPLY_ONEVAL
, spacecat(wvtcl_escape(key
), wvtcl_escape(value
)));
188 void UniClientConn::writetext(WvStringParm text
)
190 writecmd(PART_TEXT
, wvtcl_escape(text
));