00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <eyedbconfig.h>
00026 #include <fcntl.h>
00027 #ifdef HAVE_SYS_STAT_H
00028 #include <sys/stat.h>
00029 #endif
00030
00031 #include "eyedb_p.h"
00032
00033 namespace eyedb {
00034
00035 const char Connection::LocalHost[] = "-idb-local-host";
00036 const char Connection::DefaultHost[] = "-idb-default-host";
00037 const char Connection::DefaultIDBPort[] = "-idb-default-idb-port";
00038
00039 const char Connection::DefaultIDBPortValue[] = "6123";
00040
00041 #ifdef HAVE_UNISTD_H
00042 #include <unistd.h>
00043 #endif
00044
00045 Connection::Connection()
00046 {
00047 host = 0;
00048 port = 0;
00049 connh = 0;
00050 oql_info = 0;
00051 user_data = 0;
00052 }
00053
00054 Connection::Connection(bool opening, const char *_host, const char *_port)
00055 {
00056 host = 0;
00057 port = 0;
00058 connh = 0;
00059 oql_info = 0;
00060 user_data = 0;
00061
00062 if (opening) {
00063 Status status = open(_host, _port);
00064 if (status)
00065 throw *status;
00066 }
00067 }
00068
00069 const char *Connection::getHost(void) const
00070 {
00071 return host;
00072 }
00073
00074 const char *Connection::getIDBPort(void) const
00075 {
00076 return port;
00077 }
00078
00079 int Connection::getServerPid(void) const
00080 {
00081 return sv_pid;
00082 }
00083
00084 int Connection::getServerUid(void) const
00085 {
00086 return sv_uid;
00087 }
00088
00089 extern char *prog_name;
00090
00091 #include <pwd.h>
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 static const char *
00107 getUserName()
00108 {
00109 struct passwd *p = getpwuid(getuid());
00110 if (!p)
00111 return "<unknown>";
00112 return p->pw_name;
00113 }
00114
00115 Status Connection::open(const char *_host, const char *_port)
00116 {
00117 if (connh)
00118 return Exception::make(IDB_CONNECTION_FAILURE, "connection already made");
00119
00120 if (!_host)
00121 return Exception::make(IDB_CONNECTION_FAILURE, "cannot connect on not specified host");
00122 if (!_port)
00123 return Exception::make(IDB_CONNECTION_FAILURE, "cannot connect on not specified eyedb port");
00124
00125 if (!strcmp(_host, LocalHost))
00126 _host = "localhost";
00127 else if (!strcmp(_host, DefaultHost))
00128 _host = getDefaultHost();
00129
00130 if (!_host)
00131 return Exception::make(IDB_CONNECTION_FAILURE, "default host is not set for connection");
00132
00133 if (!strcmp(_port, DefaultIDBPort))
00134 _port = getDefaultIDBPort();
00135
00136 if (!_port)
00137 return Exception::make(IDB_CONNECTION_FAILURE, "default eyedb port is not set for connection");
00138
00139 std::string errmsg;
00140 if ((connOpen(_host, _port, &connh, 0, errmsg)) == RPCSuccess)
00141 {
00142 if (_host)
00143 host = strdup(_host);
00144 else
00145 host = strdup("localhost");
00146
00147 port = strdup(_port);
00148
00149 char hostname[256];
00150 gethostname(hostname, sizeof(hostname)-1);
00151 char *challenge;
00152 RPCStatus rpc_status =
00153 set_conn_info(connh, (std::string(host) + ":" + port).c_str(),
00154 0 , getUserName(), prog_name,
00155 &sv_pid, &sv_uid, getVersionNumber(),
00156 &challenge);
00157 if (!rpc_status && strlen(challenge) > 0) {
00158
00159
00160 std::string file = std::string("/tmp/") +
00161 (strrchr(challenge, '.') + 1);
00162 int fd = creat(file.c_str(), 0664);
00163 if (fd >= 0) {
00164 fchmod(fd, 0664);
00165 write(fd, challenge, strlen(challenge));
00166 rpc_status = checkAuth(connh, file.c_str());
00167 ftruncate(fd, 0);
00168 ::close(fd);
00169 unlink(file.c_str());
00170 }
00171 }
00172
00173 if (rpc_status)
00174 return Exception::make(IDB_CONNECTION_FAILURE, rpc_status->err_msg);
00175
00176 if (getenv("EYEDBWAIT")) {
00177 printf("### Connection Established for PID %d ###\n", getpid());
00178 printf("Continue? ");
00179 getchar();
00180 }
00181
00182
00183
00184 return Success;
00185 }
00186
00187 return Exception::make(IDB_CONNECTION_FAILURE,
00188 errmsg.c_str());
00189
00190
00191 }
00192
00193 Status Connection::close(void)
00194 {
00195 if (!connh)
00196 return Exception::make(IDB_CONNECTION_FAILURE, "connection not opened");
00197
00198 Status status = StatusMake(connClose(connh));
00199 if (status)
00200 return status;
00201
00202 connh = 0;
00203 return Success;
00204 }
00205
00206 Status
00207 Connection::sendInterrupt()
00208 {
00209 return StatusMake(backendInterrupt(connh, 0));
00210 }
00211
00212 Connection::~Connection()
00213 {
00214 if (connh)
00215 close();
00216 free(host);
00217 free(port);
00218 free(connh);
00219 }
00220
00221 char *Connection::default_host;
00222 char *Connection::default_port;
00223 char *Connection::default_user;
00224 char *Connection::default_passwd;
00225
00226 Bool Connection::set_auth_required = False;
00227
00228 void Connection::init()
00229 {
00230 #if 0
00231 std::string value;
00232 if (!default_host) {
00233 value = ClientConfig::getCValue("host");
00234 if (value != Config::UNKNOWN_VALUE) {
00235 default_host = strdup(value.c_str());
00236 }
00237 else
00238 default_host = strdup("localhost");
00239 }
00240
00241 if (!default_port) {
00242 value = ClientConfig::getCValue("port");
00243 if (value != Config::UNKNOWN_VALUE) {
00244 default_port = strdup(value.c_str());
00245 }
00246 else {
00247 default_port = strdup(DefaultIDBPortValue);
00248 }
00249 }
00250
00251 if (!set_auth_required) {
00252 if (!default_user) {
00253 value = ClientConfig::getCValue("user");
00254 if (value != Config::UNKNOWN_VALUE) {
00255 setDefaultUser(strdup(value.c_str()));
00256 }
00257 else {
00258 setDefaultUser(strdup(""));
00259 }
00260 }
00261
00262 if (!default_passwd) {
00263 value = ClientConfig::getCValue("passwd");
00264 if (value != Config::UNKNOWN_VALUE) {
00265 setDefaultPasswd(strdup(value.c_str()));
00266 }
00267 else {
00268 setDefaultPasswd(strdup(""));
00269 }
00270 }
00271 }
00272 #else
00273 const char *s;
00274
00275 if (!default_host)
00276 default_host = strdup( (s = ClientConfig::getCValue("host")) ?
00277 s : "localhost" );
00278 if (!default_port)
00279 default_port = strdup( (s = ClientConfig::getCValue("port")) ?
00280 s : DefaultIDBPortValue);
00281
00282 if (!set_auth_required)
00283 {
00284 if (!default_user)
00285 setDefaultUser(((s = ClientConfig::getCValue("user")) ?
00286 strdup(s) : strdup("")));
00287 if (!default_passwd)
00288 setDefaultPasswd(((s = ClientConfig::getCValue("passwd")) ?
00289 strdup(s) : strdup("")));
00290 }
00291 #endif
00292 }
00293
00294 void Connection::_release()
00295 {
00296 free(default_host);
00297 free(default_port);
00298
00299 free(default_user);
00300 free(default_passwd);
00301 }
00302
00303 void Connection::setAuthRequired(Bool _set_auth_required)
00304 {
00305 set_auth_required = _set_auth_required;
00306 }
00307
00308 void Connection::setDefaultHost(const char *_host)
00309 {
00310 free(default_host);
00311 default_host = strdup(_host);
00312 }
00313
00314 const char *Connection::getDefaultHost()
00315 {
00316 return default_host;
00317 }
00318
00319 void Connection::setDefaultIDBPort(const char *_port)
00320 {
00321 free(default_port);
00322 default_port = strdup(_port);
00323 }
00324
00325 const char *Connection::getDefaultIDBPort()
00326 {
00327 return default_port;
00328 }
00329
00330 std::string Connection::makeUser(const char *user)
00331 {
00332 if (!strcmp(user, "@")) {
00333 struct passwd *pwd = getpwuid(getuid());
00334 if (pwd)
00335 return pwd->pw_name;
00336 }
00337 return user;
00338 }
00339
00340 void Connection::setDefaultUser(const char *_user)
00341 {
00342 std::string u = makeUser(_user);
00343 free(default_user);
00344 default_user = strdup(u.c_str());
00345 }
00346
00347 const char *Connection::getDefaultUser()
00348 {
00349 return default_user;
00350 }
00351
00352 void Connection::setDefaultPasswd(const char *_passwd)
00353 {
00354 free(default_passwd);
00355 default_passwd = strdup(_passwd);
00356 }
00357
00358 const char *Connection::getDefaultPasswd()
00359 {
00360 return default_passwd;
00361 }
00362
00363 void *Connection::setUserData(void *ud)
00364 {
00365 void *oud = user_data;
00366 user_data = ud;
00367 return oud;
00368 }
00369
00370 void *Connection::getUserData()
00371 {
00372 return user_data;
00373 }
00374
00375 const void *Connection::getUserData() const
00376 {
00377 return user_data;
00378 }
00379
00380 void *Connection::setOQLInfo(void *noql_info)
00381 {
00382 void *x = oql_info;
00383 oql_info = noql_info;
00384 return x;
00385 }
00386
00387 void *Connection::getOQLInfo()
00388 {
00389 return oql_info;
00390 }
00391
00392
00393
00394
00395
00396 eyedblib::Thread *srv_msg_thr;
00397
00398 struct Connection::ServerMessageContext {
00399 ConnHandle *connh;
00400 const ServerMessageDisplayer &dsp;
00401
00402 ServerMessageContext(ConnHandle *_connh,
00403 const ServerMessageDisplayer &_dsp) :
00404 connh(_connh), dsp(_dsp)
00405 {
00406 }
00407 };
00408
00409 static void *
00410 srv_msg_listen(void *x)
00411 {
00412 Connection::ServerMessageContext *srv_msg_ctx = (Connection::ServerMessageContext *)x;
00413
00414 ConnHandle *connh = srv_msg_ctx->connh;
00415
00416 for (;;) {
00417 int type = IDB_SERVER_MESSAGE;
00418 unsigned int size;
00419 Data data = (Data)0x111;
00420 RPCStatus rpc_status = getServerOutOfBandData(connh, &type, &data,
00421 &size);
00422 if (rpc_status) {
00423 std::string msg =
00424 std::string("Thread for echoing server messages got an "
00425 "unexepected error: #") + str_convert((long)rpc_status->err) +
00426 rpc_status->err_msg + "\n";
00427 srv_msg_ctx->dsp.display(msg.c_str());
00428 break;
00429 }
00430
00431 assert(type == IDB_SERVER_MESSAGE);
00432 if (data) {
00433 srv_msg_ctx->dsp.display((const char *)data);
00434 free(data);
00435 }
00436 }
00437 return 0;
00438 }
00439
00440 Status
00441 Connection::echoServerMessages(const ServerMessageDisplayer &dsp) const
00442 {
00443 if (srv_msg_thr)
00444 return Exception::make(IDB_ERROR,
00445 "a thread is already echoing server messages");
00446
00447
00448 ServerMessageContext *srv_msg_ctx = new ServerMessageContext(connh, dsp);
00449 srv_msg_thr = new eyedblib::Thread();
00450 srv_msg_thr->execute(srv_msg_listen, srv_msg_ctx);
00451
00452
00453 srv_msg_ctx = new ServerMessageContext(0, dsp);
00454 srv_msg_thr = new eyedblib::Thread();
00455 srv_msg_thr->execute(srv_msg_listen, srv_msg_ctx);
00456 return Success;
00457 }
00458
00459 void
00460 Connection::setServerMessage(const char *msg)
00461 {
00462 eyedb::setServerMessage(msg);
00463 }
00464
00465 void
00466 Connection::setOutOfBandData(unsigned int type, unsigned char *data,
00467 unsigned int len)
00468 {
00469 setServerOutOfBandData(type, data, len);
00470 }
00471
00472 Bool
00473 Connection::isBackendInterrupted()
00474 {
00475 return isBackendInterrupted();
00476 }
00477
00478 StdServerMessageDisplayer::StdServerMessageDisplayer(FILE *_fd)
00479 {
00480 fd = _fd;
00481 os = 0;
00482 }
00483
00484 StdServerMessageDisplayer::StdServerMessageDisplayer(std::ostream &_os)
00485 {
00486 fd = 0;
00487 os = &_os;
00488 }
00489
00490 void StdServerMessageDisplayer::display(const char *msg) const
00491 {
00492 if (fd) {
00493 write(fileno(fd), msg, strlen(msg));
00494 return;
00495 }
00496 (*os) << msg << std::flush;
00497 }
00498 }