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