00001
00002
00003
00004
00005
00006
00007
00008
#include "uniclientgen.h"
00009
#include "wvtclstring.h"
00010
#include "wvtcp.h"
00011
#include "wvaddr.h"
00012
#include "wvresolver.h"
00013
#include "wvmoniker.h"
00014
#include "wvsslstream.h"
00015
00016
#ifndef _WIN32
00017
#include "wvunixsocket.h"
00018 static UniConfGen *
unixcreator(
WvStringParm s,
IObject *,
void *)
00019 {
00020
return new UniClientGen(
new WvUnixConn(s));
00021 }
00022
static WvMoniker<UniConfGen> unixreg(
"unix", unixcreator);
00023
#endif
00024
00025 static UniConfGen *
tcpcreator(
WvStringParm _s,
IObject *,
void *)
00026 {
00027
WvString s(_s);
00028
char *cptr = s.
edit();
00029
00030
if (!strchr(cptr,
':'))
00031 s.
append(
":%s",
DEFAULT_UNICONF_DAEMON_TCP_PORT);
00032
00033
return new UniClientGen(
new WvTCPConn(s), _s);
00034 }
00035
00036 static UniConfGen *
sslcreator(
WvStringParm _s,
IObject *,
void *)
00037 {
00038
WvString s(_s);
00039
char *cptr = s.
edit();
00040
00041
if (!strchr(cptr,
':'))
00042 s.
append(
":%s",
DEFAULT_UNICONF_DAEMON_SSL_PORT);
00043
00044
return new UniClientGen(
new WvSSLStream(
new WvTCPConn(s), NULL,
true), _s);
00045 }
00046
00047
00048
00049 static UniConfGen *
wvstreamcreator(
WvStringParm s,
IObject *obj,
void *)
00050 {
00051
IWvStream *stream = NULL;
00052
if (obj)
00053 stream = mutate<IWvStream>(obj);
00054
if (!stream)
00055 stream = wvcreate<IWvStream>(s);
00056
return new UniClientGen(stream);
00057 }
00058
00059
static WvMoniker<UniConfGen> tcpreg(
"tcp", tcpcreator);
00060
static WvMoniker<UniConfGen> sslreg(
"ssl", sslcreator);
00061
static WvMoniker<UniConfGen> wvstreamreg(
"wvstream", wvstreamcreator);
00062
00063
00064
00065
00066
00067 UniClientGen::UniClientGen(
IWvStream *stream,
WvStringParm dst) :
00068 conn(NULL),
log(
WvString("
UniClientGen to %s",
00069 dst.isnull() ? *stream->src() :
WvString(dst))),
00070 cmdinprogress(false), cmdsuccess(false)
00071 {
00072 conn =
new UniClientConn(stream, dst);
00073 conn->
setcallback(
WvStreamCallback(
this,
00074 &
UniClientGen::conncallback), NULL);
00075
00076 deltastream.
setcallback(
WvStreamCallback(
this, &
UniClientGen::deltacb), 0);
00077 WvIStreamList::globallist.append(&deltastream,
false);
00078 }
00079
00080
00081 UniClientGen::~UniClientGen()
00082 {
00083 WvIStreamList::globallist.
unlink(&deltastream);
00084
00085 conn->
writecmd(UniClientConn::REQ_QUIT,
"");
00086
delete conn;
00087 }
00088
00089
00090 bool UniClientGen::isok()
00091 {
00092
return (conn && conn->
isok());
00093 }
00094
00095
00096 bool UniClientGen::refresh()
00097 {
00098
00099
return true;
00100 }
00101
00102
00103 WvString UniClientGen::get(
const UniConfKey &key)
00104 {
00105
WvString value;
00106 conn->
writecmd(UniClientConn::REQ_GET,
wvtcl_escape(key));
00107
00108
if (
do_select())
00109 {
00110
if (result_key == key)
00111 value = result;
00112
else
00113 seterror(
"Error: server sent wrong key pair.");
00114 }
00115
return value;
00116 }
00117
00118
00119 void UniClientGen::set(
const UniConfKey &key,
WvStringParm newvalue)
00120 {
00121
00122
hold_delta();
00123
00124
if (newvalue.
isnull())
00125 conn->
writecmd(UniClientConn::REQ_REMOVE,
wvtcl_escape(key));
00126
else
00127 conn->
writecmd(UniClientConn::REQ_SET,
00128
WvString(
"%s %s",
wvtcl_escape(key),
wvtcl_escape(newvalue)));
00129
00130
unhold_delta();
00131 }
00132
00133
00134 bool UniClientGen::haschildren(
const UniConfKey &key)
00135 {
00136 conn->
writecmd(UniClientConn::REQ_HASCHILDREN,
wvtcl_escape(key));
00137
00138
if (
do_select())
00139 {
00140
if (result_key == key && result ==
"TRUE")
00141
return true;
00142 }
00143
00144
return false;
00145 }
00146
00147
00148 UniClientGen::Iter *
UniClientGen::iterator(
const UniConfKey &key)
00149 {
00150 result_list =
new WvStringList();
00151 conn->
writecmd(UniClientConn::REQ_SUBTREE,
wvtcl_escape(key));
00152
00153
if (
do_select())
00154
return new RemoteKeyIter(result_list);
00155
00156
delete result_list;
00157
return new UniConfGen::NullIter();
00158 }
00159
00160
00161 void UniClientGen::conncallback(
WvStream &stream,
void *userdata)
00162 {
00163
if (conn->
alarm_was_ticking)
00164 {
00165
00166
log(WvLog::Error,
"Command timeout; connection closed.\n");
00167 cmdinprogress =
false;
00168 cmdsuccess =
false;
00169 conn->
close();
00170
00171
return;
00172 }
00173
00174 UniClientConn::Command command = conn->
readcmd();
00175
00176
switch (command)
00177 {
00178
case UniClientConn::NONE:
00179
00180
break;
00181
00182
case UniClientConn::REPLY_OK:
00183 cmdsuccess =
true;
00184 cmdinprogress =
false;
00185
break;
00186
00187
case UniClientConn::REPLY_FAIL:
00188 result_key = WvString::null;
00189 cmdsuccess =
false;
00190 cmdinprogress =
false;
00191
break;
00192
00193
case UniClientConn::REPLY_CHILD:
00194 {
00195
WvString key(
wvtcl_getword(conn->
payloadbuf,
" "));
00196
WvString value(
wvtcl_getword(conn->
payloadbuf,
" "));
00197
00198
if (!key.
isnull() && !value.
isnull())
00199 {
00200 result_key = key;
00201 result = value;
00202 cmdsuccess =
true;
00203 }
00204 cmdinprogress =
false;
00205
break;
00206
00207 }
00208
00209
case UniClientConn::REPLY_ONEVAL:
00210 {
00211
WvString key(
wvtcl_getword(conn->
payloadbuf,
" "));
00212
WvString value(
wvtcl_getword(conn->
payloadbuf,
" "));
00213
00214
if (!key.
isnull() && !value.
isnull())
00215 {
00216 result_key = key;
00217 result = value;
00218 cmdsuccess =
true;
00219 }
00220
00221 cmdinprogress =
false;
00222
break;
00223 }
00224
00225
case UniClientConn::PART_VALUE:
00226 {
00227
WvString key(
wvtcl_getword(conn->
payloadbuf,
" "));
00228
WvString value(
wvtcl_getword(conn->
payloadbuf,
" "));
00229
00230
if (!key.
isnull() && !value.
isnull())
00231 {
00232
if (result_list)
00233 result_list->append(
new WvString(key),
true);
00234 }
00235
break;
00236 }
00237
00238
case UniClientConn::EVENT_HELLO:
00239 {
00240
WvString server(
wvtcl_getword(conn->
payloadbuf,
" "));
00241
00242
if (server.
isnull() || strncmp(server,
"UniConf", 7))
00243 {
00244
00245
log(WvLog::Error,
"Connected to a non-UniConf serer!\n");
00246
00247 cmdinprogress =
false;
00248 cmdsuccess =
false;
00249 conn->
close();
00250 }
00251
break;
00252 }
00253
00254
case UniClientConn::EVENT_NOTICE:
00255 {
00256
WvString key(
wvtcl_getword(conn->
payloadbuf,
" "));
00257
WvString value(
wvtcl_getword(conn->
payloadbuf,
" "));
00258
clientdelta(key, value);
00259 }
00260
00261
default:
00262
00263
break;
00264 }
00265 }
00266
00267
00268 bool UniClientGen::do_select()
00269 {
00270 cmdinprogress =
true;
00271 cmdsuccess =
false;
00272
00273 conn->
alarm(TIMEOUT);
00274
while (conn->
isok() && cmdinprogress)
00275 {
00276
if (conn->
select(-1))
00277 {
00278 conn->
callback();
00279 conn->
alarm(TIMEOUT);
00280 }
00281 }
00282 conn->
alarm(-1);
00283
00284
if (!cmdsuccess)
00285 seterror(
"Error: server timed out on response.");
00286
00287
return cmdsuccess;
00288 }
00289
00290
00291
00292
00293
00294 void UniClientGen::RemoteKeyIter::rewind()
00295 {
00296
i.rewind();
00297 }
00298
00299
00300 bool UniClientGen::RemoteKeyIter::next()
00301 {
00302
return i.next();
00303 }
00304
00305
00306 UniConfKey UniClientGen::RemoteKeyIter::key()
const
00307
{
00308
return UniConfKey(*i).
last();
00309 }
00310
00311 void UniClientGen::clientdelta(
const UniConfKey &key,
WvStringParm value)
00312 {
00313 deltas.append(
new UniConfPair(key, value),
true);
00314 deltastream.
alarm(0);
00315 }
00316
00317 void UniClientGen::deltacb(
WvStream &,
void *)
00318 {
00319
hold_delta();
00320 UniConfPairList::Iter i(deltas);
00321
00322
for (i.rewind(); i.next(); )
00323 delta(i->key(), i->value());
00324
00325 deltas.zap();
00326
unhold_delta();
00327 }