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  */
24 const 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 
64 UniClientConn::~UniClientConn()
65 {
66  close();
67 }
68 
69 
71 {
72  if (!closed)
73  {
74  closed = true;
76  log("Closed\n");
77  }
78 }
79 
80 
81 WvString 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  {
98  if (!WvStreamClone::isok())
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 
112 void 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 
147 {
148  return wvtcl_getword(payloadbuf);
149 }
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 
183 {
185 }
186 
187 
189 {
191 }
192 
193