00001
00002
00003
00004
00005
00006
00007 #include "uniclientconn.h"
00008 #include "wvaddr.h"
00009 #include "wvtclstring.h"
00010 #include "strutils.h"
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 const UniClientConn::CommandInfo UniClientConn::cmdinfos[
00025 UniClientConn::NUM_COMMANDS] = {
00026
00027 { "noop", "noop: verify that the connection is active" },
00028 { "get", "get <key>: get the value of a key" },
00029 { "set", "set <key> <value>: sets the value of a key" },
00030 { "setv", "setv <key> <value> ...: set multiple key-value pairs" },
00031 { "del", "del <key>: deletes the key" },
00032 { "subt", "subt <key> <recurse?>: enumerates the children of a key" },
00033 { "hchild", "hchild <key>: returns whether a key has children" },
00034 { "commit", "commit: commits changes to disk" },
00035 { "refresh", "refresh: refresh contents from disk" },
00036 { "quit", "quit: kills the session nicely" },
00037 { "help", "help: returns this help text" },
00038
00039
00040 { "OK", "OK <payload>: reply on command success" },
00041 { "FAIL", "FAIL <payload>: reply on command failure" },
00042 { "CHILD", "CHILD <key> TRUE / FALSE: key has children or not" },
00043 { "ONEVAL", "ONEVAL <key> <value>: reply to a get" },
00044
00045
00046 { "VAL", "VAL <key> <value>: intermediate reply value of a key" },
00047 { "TEXT", "TEXT <text>: intermediate reply of a text message" },
00048
00049
00050 { "HELLO", "HELLO <version> <message>: sent by server on connection" },
00051 { "NOTICE", "NOTICE <key> <oldval> <newval>: forget key and its children" },
00052 };
00053
00054
00055 UniClientConn::UniClientConn(IWvStream *_s, WvStringParm dst) :
00056 WvStreamClone(_s),
00057 log(WvString("UniConf to %s", dst.isnull() && _s->src() ? *_s->src() : WvString(dst)),
00058 WvLog::Debug5), closed(false), version(-1), payloadbuf("")
00059 {
00060 log("Opened\n");
00061 }
00062
00063
00064 UniClientConn::~UniClientConn()
00065 {
00066 close();
00067 }
00068
00069
00070 void UniClientConn::close()
00071 {
00072 if (!closed)
00073 {
00074 closed = true;
00075 WvStreamClone::close();
00076 log("Closed\n");
00077 }
00078 }
00079
00080
00081 WvString UniClientConn::readmsg()
00082 {
00083 WvString word;
00084 while ((word = wvtcl_getword(msgbuf,
00085 WVTCL_NASTY_NEWLINES,
00086 false)).isnull())
00087 {
00088
00089
00090 char *line = getline(0, '\n', 20480);
00091 if (line)
00092 {
00093 msgbuf.putstr(line);
00094 msgbuf.put('\n');
00095 }
00096 else
00097 {
00098 if (!WvStreamClone::isok())
00099 {
00100
00101 msgbuf.zap();
00102 }
00103 return WvString::null;
00104 }
00105 }
00106 if (!!word && 0)
00107 log("Read: %s\n", word);
00108 return word;
00109 }
00110
00111
00112 void UniClientConn::writemsg(WvStringParm msg)
00113 {
00114 write(msg);
00115 write("\n");
00116
00117 }
00118
00119
00120 UniClientConn::Command UniClientConn::readcmd()
00121 {
00122 WvString buf;
00123 return readcmd(buf);
00124 }
00125
00126 UniClientConn::Command UniClientConn::readcmd(WvString &command)
00127 {
00128 WvString msg(readmsg());
00129 if (msg.isnull())
00130 return NONE;
00131
00132
00133 payloadbuf.reset(msg);
00134 command = readarg();
00135
00136 if (command.isnull())
00137 return NONE;
00138
00139 for (int i = 0; i < NUM_COMMANDS; ++i)
00140 if (strcasecmp(cmdinfos[i].name, command.cstr()) == 0)
00141 return Command(i);
00142 return INVALID;
00143 }
00144
00145
00146 WvString UniClientConn::readarg()
00147 {
00148 return wvtcl_getword(payloadbuf);
00149 }
00150
00151
00152 void UniClientConn::writecmd(UniClientConn::Command cmd, WvStringParm msg)
00153 {
00154 write(cmdinfos[cmd].name);
00155 if (msg)
00156 {
00157 write(" ");
00158 write(msg);
00159 }
00160 write("\n");
00161 }
00162
00163
00164 void UniClientConn::writeok(WvStringParm payload)
00165 {
00166 writecmd(REPLY_OK, payload);
00167 }
00168
00169
00170 void UniClientConn::writefail(WvStringParm payload)
00171 {
00172 writecmd(REPLY_FAIL, payload);
00173 }
00174
00175
00176 void UniClientConn::writevalue(const UniConfKey &key, WvStringParm value)
00177 {
00178 if (value == WvString::null)
00179 writecmd(PART_VALUE, wvtcl_escape(key));
00180 else
00181 writecmd(PART_VALUE, spacecat(wvtcl_escape(key), wvtcl_escape(value)));
00182 }
00183
00184
00185 void UniClientConn::writeonevalue(const UniConfKey &key, WvStringParm value)
00186 {
00187 writecmd(REPLY_ONEVAL, spacecat(wvtcl_escape(key), wvtcl_escape(value)));
00188 }
00189
00190
00191 void UniClientConn::writetext(WvStringParm text)
00192 {
00193 writecmd(PART_TEXT, wvtcl_escape(text));
00194 }