00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "site.hh"
00025 #include "remotesocketsite.hh"
00026 #include "message.hh"
00027 #include "messageblock.hh"
00028
00029 using namespace VOS;
00030
00031 #include <stdio.h>
00032 #include <string>
00033 #include <map>
00034 #include <iterator>
00035 #include <queue>
00036 #include <algorithm>
00037
00038
00039 #if !defined(HAVE_SOCKLEN_T) && !defined(__socklen_t_defined)
00040
00041 typedef int socklen_t;
00042 #define __socklen_t_defined 1
00043 #endif
00044
00045
00046
00047
00048
00049
00050 map<string, Site*> Site::siteTable;
00051 boost::mutex Site::siteTable_mutex;
00052 LocalSite* Site::defaultPeer = 0;
00053 set<int> Site::allOpenSockets;
00054
00055 Site::Site()
00056 : MetaObject(0)
00057 {
00058 }
00059
00060 Site::~Site()
00061 {
00062 for(map<string, MessageBlock*>::iterator i = messageBlockTable.begin();
00063 i != messageBlockTable.end();
00064 i++) {
00065 (*i).second->release();
00066 }
00067 for(map<string, Message*>::iterator i = outgoingTraps.begin();
00068 i != outgoingTraps.end();
00069 i++) {
00070 (*i).second->release();
00071 }
00072 }
00073
00074 void Site::addHostAlias(const string& h)
00075 {
00076 if(! hasHostAlias(h)) {
00077 boost::mutex::scoped_lock lock(hostnames_mutex);
00078 boost::mutex::scoped_lock lock2(siteTable_mutex);
00079
00080 hostnames.insert(h);
00081 acquire();
00082 siteTable[h]=this;
00083 }
00084 LOG("refcount", 5, "addHostAlias: count is " << getCount());
00085 }
00086
00087 void Site::removeHostAlias(const string& h)
00088 {
00089 if(hasHostAlias(h)) {
00090 boost::mutex::scoped_lock lock(hostnames_mutex);
00091
00092 hostnames.erase(h);
00093 release();
00094 }
00095 LOG("refcount", 5, "removeHostAlias: count is " << getCount());
00096 }
00097
00098 bool Site::hasHostAlias(const string& h)
00099 {
00100 boost::mutex::scoped_lock lock(hostnames_mutex);
00101 return (hostnames.count(h) > 0);
00102 }
00103
00104 set<string>& Site::getHostAliases()
00105 {
00106 boost::mutex::scoped_lock lock(hostnames_mutex);
00107 return hostnames;
00108 }
00109
00110 void Site::addSite(Site* s)
00111 {
00112 removeSite(*s);
00113
00114 set<string>& v=s->getHostAliases();
00115
00116 boost::mutex::scoped_lock lock(siteTable_mutex);
00117
00118 for(set<string>::iterator i=v.begin(); i != v.end(); i++) {
00119 LOG("addSite", 3, "adding " << *i << " to site table");
00120 s->acquire();
00121 siteTable[*i]=s;
00122 }
00123 LOG("refcount", 5, "addSite: count is " << s->getCount());
00124 }
00125
00126 void Site::removeSite(Site& s)
00127 {
00128 set<string>& v=s.getHostAliases();
00129
00130 boost::mutex::scoped_lock lock(siteTable_mutex);
00131
00132 for(set<string>::iterator i=v.begin(); i != v.end(); i++) {
00133 if(siteTable.count(*i)) {
00134 siteTable.erase(*i);
00135 s.release();
00136 }
00137 }
00138 LOG("refcount", 5, "removeSite: count is " << s.getCount());
00139 }
00140
00141 struct hostent* Site::hostent_deepcopy(struct hostent* hp)
00142 {
00143 struct hostent* ret = (struct hostent*)malloc(sizeof(struct hostent));
00144
00145 ret->h_name = strdup(hp->h_name);
00146 int i = 0;
00147 while(hp->h_aliases[i]) i++;
00148 ret->h_aliases = (char**)malloc((i+1) * sizeof(char*));
00149 int n;
00150 for(n = 0; n < i; n++) {
00151 ret->h_aliases[n] = strdup(hp->h_aliases[n]);
00152 }
00153 ret->h_aliases[n] = 0;
00154
00155 ret->h_addrtype = hp->h_addrtype;
00156 ret->h_length = hp->h_length;
00157
00158 i=0;
00159 while(hp->h_addr_list[i]) i++;
00160 ret->h_addr_list = (char**)malloc((i+1) * sizeof(char*));
00161 for(n = 0; n < i; n++) {
00162 ret->h_addr_list[n] = (char*)malloc(hp->h_length);
00163 memcpy(ret->h_addr_list[n], hp->h_addr_list[n], hp->h_length);
00164 }
00165 ret->h_addr_list[n] = 0;
00166
00167 return ret;
00168 }
00169
00170 struct hostent* Site::gethostbyaddr_locked(const char *addr, int len, int type)
00171 {
00172 static boost::mutex ghba_mutex;
00173
00174 boost::mutex::scoped_lock lock(ghba_mutex);
00175
00176 struct hostent* hp = gethostbyaddr(addr, len, type);
00177
00178 if(! hp) return 0;
00179
00180 return hostent_deepcopy(hp);
00181 }
00182
00183 struct hostent* Site::gethostbyname_locked(const char *addr)
00184 {
00185 static boost::mutex ghbn_mutex;
00186
00187 boost::mutex::scoped_lock lock(ghbn_mutex);
00188
00189 struct hostent* hp = gethostbyname(addr);
00190
00191 if(! hp) return 0;
00192
00193 return hostent_deepcopy(hp);
00194 }
00195
00196
00197 void Site::freeHostEnt(struct hostent* hp)
00198 {
00199 free(hp->h_name);
00200 for(int i = 0; hp->h_aliases[i]; i++) free(hp->h_aliases[i]);
00201 free(hp->h_aliases);
00202 for(int i = 0; hp->h_addr_list[i]; i++) free(hp->h_addr_list[i]);
00203 free(hp->h_addr_list);
00204 free(hp);
00205 }
00206
00207 string Site::detectHostname(int fd, unsigned char ipaddr[4])
00208 {
00209 struct sockaddr_in sa;
00210 socklen_t socklen = sizeof(struct sockaddr_in);
00211 getsockname(fd, (struct sockaddr *)&sa, &socklen);
00212
00213 long addr = ntohl(sa.sin_addr.s_addr);
00214 char dottedquad[64];
00215 ipaddr[0] = (unsigned int)(addr >> 24) & 0xFF;
00216 ipaddr[1] = (unsigned int)(addr >> 16) & 0xFF;
00217 ipaddr[2] = (unsigned int)(addr >> 8) & 0xFF;
00218 ipaddr[3] = (unsigned int)(addr & 0xFF);
00219 sprintf(dottedquad, "%u.%u.%u.%u", (unsigned int)ipaddr[0], (unsigned int)ipaddr[1],
00220 (unsigned int)ipaddr[2], (unsigned int)ipaddr[3]);
00221
00222 struct hostent* hp;
00223 int err = 0;
00224 #ifdef HAVE_GETIPNODEBYNAME
00225 hp = getipnodebyaddr((const char*)&sa.sin_addr.s_addr, sizeof(addr), AF_INET, &err);
00226 #else
00227 hp = gethostbyaddr_locked((const char*)&sa.sin_addr.s_addr, sizeof(addr), AF_INET);
00228 err = h_errno;
00229 #endif
00230 if(hp) {
00231 struct hostent* hp2;
00232 #ifdef HAVE_GETIPNODEBYNAME
00233 hp2 = getipnodebyname(hp->h_name, AF_INET, 0, &err);
00234 #else
00235 hp2 = gethostbyname_locked(hp->h_name);
00236 err = h_errno;
00237 #endif
00238
00239 #ifdef HAVE_GETIPNODEBYNAME
00240 freehostent(hp);
00241 #else
00242 freeHostEnt(hp);
00243 #endif
00244 string ret;
00245 if(hp2) {
00246 return ret = string(hp2->h_name);
00247 } else {
00248 LOG("site", 1, "Warning: gethostbyaddr failed for " << hp->h_name << ". Using address " << dottedquad << " instead.");
00249 ret = dottedquad;
00250 }
00251 #ifdef HAVE_GETIPNODEBYNAME
00252 freehostent(hp2);
00253 #else
00254 freeHostEnt(hp2);
00255 #endif
00256 return ret;
00257 } else {
00258 LOG("Site", 1, "Warning: gethostbyaddr failed for " << dottedquad << ". Using that address as it is.");
00259 return dottedquad;
00260 }
00261 }
00262
00263 Site& Site::findSite(const string& s) throw (NoSuchSiteError)
00264 {
00265 map<string,Site*>::iterator i = siteTable.find(s);
00266 if(i == siteTable.end()) {
00267 char t[256];
00268 snprintf(t, sizeof(t), "%s:%i", s.c_str(), VOS_DEFAULT_PORT);
00269 i=siteTable.find(string(t));
00270 if(i == siteTable.end()) {
00271 try {
00272 unsigned int c = (unsigned int)s.find(":");
00273 if(c==string::npos) throw NoSuchSiteError("Bad site name: must be in the form \"host:port\"");
00274 string h=s.substr(0, c);
00275 int p=atoi(s.substr(c+1).c_str());
00276
00277 RemoteSocketSite* rs = AsyncConnect::connect(h, p, defaultPeer, false);
00278 rs->getTypes();
00279
00280 return *rs;
00281 } catch(RemoteSite::SiteConnectionError x) {
00282 LOG("site", 3, "cannot connect to site " << x.what());
00283 throw NoSuchSiteError(string("Cannot connect to site: ")+x.what());
00284 } catch(TimeoutError) {
00285 throw NoSuchSiteError(string("Site doesn't want to talk to us (timeout)"));
00286 } catch(runtime_error e) {
00287 LOG("site", 3, "cannot connect to site " << e.what());
00288 throw NoSuchSiteError(string("Unknown error: ") + e.what());
00289 }
00290 } else {
00291 ((*i).second)->acquire();
00292 return *((*i).second);
00293 }
00294 } else {
00295 ((*i).second)->acquire();
00296 return *((*i).second);
00297 }
00298 }
00299
00300 LocalSite* Site::getDefaultPeer()
00301 {
00302 if(defaultPeer) defaultPeer->acquire();
00303 return defaultPeer;
00304 }
00305
00306 void Site::setDefaultPeer(LocalSite* localsite)
00307 {
00308 if(defaultPeer) defaultPeer->release();
00309 localsite->acquire();
00310 defaultPeer = localsite;
00311 }
00312
00313 void Site::doSitePeering(LocalSite* ls, RemoteSite* rs, bool isspooftest, bool waitforhello)
00314 {
00315
00316
00317
00318 ls->acquire();
00319 rs->localpeer = ls;
00320
00321 struct LocalSite::SiteTableEntry* st=new LocalSite::SiteTableEntry();
00322 st->partialMessage=0;
00323 rs->acquire();
00324 if(ls->iteratorsUsingPeerSites == 0 && waitforhello) {
00325 ls->peerSites[rs]=st;
00326 } else {
00327 boost::mutex::scoped_lock lock(ls->peerSitesBuffer_mutex);
00328
00329
00330 ls->peerSitesBuffer_rs.push_back(rs);
00331 ls->peerSitesBuffer_st.push_back(st);
00332 }
00333
00334 rs->defaultContext.setParameter("from", rs->getURL().getString());
00335 rs->defaultContext.setParameter("to", ls->getURL().getString());
00336 rs->defaultContext.setParameter("method", "");
00337
00338 vRef<Message> m = new Message();
00339 m->setType("message");
00340 m->setMethod("core:hello");
00341
00342 if(! isspooftest) {
00343 int r = rand();
00344 char s[16];
00345 snprintf(s, sizeof(s), "%i", r);
00346 m->insertField(-1, "antispoof", s);
00347
00348 m->insertField(-1, "alias", ls->getURL().getHostAndPort());
00349
00350 set<string>& v = ls->getHostAliases();
00351 for(set<string>::iterator i=v.begin(); i != v.end(); i++) {
00352 if((*i).substr(0, 9) != "localhost"
00353 && (*i) != ls->getURL().getHostAndPort())
00354 {
00355 m->insertField(-1, "alias", *i);
00356 }
00357 }
00358 rs->setAntiSpoofID(s);
00359 }
00360
00361 rs->sendMessage(&m);
00362
00363 if(waitforhello) {
00364 while(rs->isConnected() && !rs->getGreeted()) {
00365 defaultPeer->flushIncomingBuffers();
00366 }
00367 }
00368 }
00369
00370 const map<string,Site*>& Site::getAllSites()
00371 {
00372 return siteTable;
00373 }
00374
00375 const string Site::getType()
00376 {
00377 return string("site");
00378 }
00379
00380 void Site::addMessageBlock(MessageBlock* m)
00381 {
00382 m->acquire();
00383 map<string, MessageBlock*>::iterator i = messageBlockTable.find(m->getName());
00384 if(i != messageBlockTable.end()) (*i).second->release();
00385 messageBlockTable[m->getName()] = m;
00386 }
00387
00388 void Site::removeMessageBlock(MessageBlock* m)
00389 {
00390 map<string, MessageBlock*>::iterator i = messageBlockTable.find(m->getName());
00391 if(i != messageBlockTable.end()) {
00392 (*i).second->release();
00393 messageBlockTable.erase(i);
00394 }
00395 }
00396
00397 MessageBlock* Site::getMessageBlock(const string& s) throw (NoSuchMessageBlockError)
00398 {
00399 map<string, MessageBlock*>::iterator i = messageBlockTable.find(s);
00400 if(i != messageBlockTable.end()) {
00401 (*i).second->acquire();
00402 return (*i).second;
00403 } else throw NoSuchMessageBlockError("message block not found");
00404 }
00405
00406 void Site::sendMessage(Message* m)
00407 {
00408 if(m->getNonce() != "") {
00409 map<string, Message*>::iterator i = outgoingTraps.find(m->getNonce());
00410 if(i != outgoingTraps.end()) {
00411 pREF(MessageContext*, mc, (*i).second->getMessageContext(),
00412 if(mc) mc->addToReplyRecord(m));
00413 (*i).second->release();
00414 outgoingTraps.erase(i);
00415 }
00416 }
00417 }
00418
00419 void Site::sendMessage(MessageBlock* mb)
00420 {
00421 for(int i = 0; i < mb->numMessages(); i++) {
00422 vRef<Message> m = mb->getMessage(i);
00423 if(m->getNonce() != "") {
00424 map<string, Message*>::iterator i = outgoingTraps.find(m->getNonce());
00425 if(i != outgoingTraps.end()) {
00426 vRef<MessageContext> mc = (*i).second->getMessageContext();
00427 if(&mc) mc->addToReplyRecord(&m);
00428 (*i).second->release();
00429 outgoingTraps.erase(i);
00430 }
00431 }
00432 }
00433 }
00434
00435 void Site::trapOutgoingReply(Message* m)
00436 {
00437 pREF(MessageContext*, mc, m->getMessageContext(), if(!mc) return; );
00438 string dep = m->getDependency();
00439 unsigned int i=0;
00440 unsigned int n=0;
00441 LOG("site", 3, "Will trap outgoing nonce " << dep);
00442 while(i < dep.size()) {
00443 while(i < dep.size() && dep[i] != ',') i++;
00444 if(outgoingTraps[dep.substr(n, i-n)] == 0) {
00445 m->acquire();
00446 outgoingTraps[dep.substr(n, i-n)] = m;
00447 }
00448 n=++i;
00449 }
00450 }
00451
00452 Site& Site::getSite()
00453 {
00454 acquire();
00455 return *this;
00456 }
00457
00458 bool Site::getGreeted()
00459 {
00460 return greeted;
00461 }
00462
00463 void Site::setGreeted(bool g)
00464 {
00465 greeted = g;
00466 }
00467
00468
00469 string Site::generateUniqueName()
00470 {
00471 char name[256];
00472 bool inuse;
00473
00474 do {
00475 try {
00476 snprintf(name, sizeof(name), "%i", rand());
00477 rREF(Vobject&, foo, findObject(name), );
00478 inuse = true;
00479 } catch(Vobject::NoSuchObjectError) {
00480 inuse = false;
00481 }
00482 } while(inuse);
00483 return string(name);
00484 }
00485
00486 string Site::uniqueName(const char* desiredName) {
00487 string name;
00488
00489 if(desiredName == 0 || strlen(desiredName) == 0) {
00490 return generateUniqueName();
00491 } else {
00492 name = desiredName;
00493 try {
00494 while(true) {
00495 vRef<Vobject> o = findObject(name);
00496 char tmp[256];
00497 snprintf(tmp, sizeof(tmp), "%s_%i", desiredName, rand());
00498 name = tmp;
00499 }
00500 } catch(NoSuchObjectError) {
00501
00502 }
00503 }
00504 return name;
00505 }
00506
00507 void Site::insertMessageFilter(int pos, MessageFilter* mf)
00508 {
00509 if(pos < 0) pos += (int)messagefilters.size() + 1;
00510 messagefilters.insert(messagefilters.begin() + pos, mf);
00511 }
00512
00513 void Site::removeMessageFilter(int pos)
00514 {
00515 if(pos < 0) pos += (int)messagefilters.size() + 1;
00516 messagefilters.erase(messagefilters.begin() + pos);
00517 }
00518
00519 void Site::removeMessageFilter(MessageFilter* m)
00520 {
00521 for(unsigned int i = 0; i < messagefilters.size(); i++) {
00522 if(messagefilters[i] == m) {
00523 messagefilters.erase(messagefilters.begin() + i);
00524 i--;
00525 }
00526 }
00527 }
00528
00529 const deque<MessageFilter*>& Site::getMessageFilters()
00530 {
00531 return messagefilters;
00532 }
00533
00534
00535
00536 MessageFilter::~MessageFilter() { }
00537
00538 bool MessageFilter::checkMessage(MessageBlock* m)
00539 {
00540 for(int n = 0; n < m->numMessages(); n++) {
00541 vRef<Message> msg = m->getMessage(n);
00542 if(! checkMessage(&msg)) {
00543 return false;
00544 }
00545 }
00546 return true;
00547 }
00548
00549
00550
00551 VobjectNotifyEvent::VobjectNotifyEvent(ChildChangeListener* cl, VobjectEvent& e)
00552 : childlistener(cl), parentlistener(0), typelistener(0), event(e)
00553 {
00554
00555 if(RefCounted* rc = dynamic_cast<RefCounted*>(cl)) rc->acquire();
00556 e.acquire();
00557 }
00558
00559 VobjectNotifyEvent::VobjectNotifyEvent(ParentChangeListener* pl, VobjectEvent& e)
00560 : childlistener(0), parentlistener(pl), typelistener(0), event(e)
00561 {
00562
00563 if(RefCounted* rc = dynamic_cast<RefCounted*>(pl)) rc->acquire();
00564 e.acquire();
00565 }
00566
00567 VobjectNotifyEvent::VobjectNotifyEvent(TypeChangeListener* tl, VobjectEvent& e)
00568 : childlistener(0), parentlistener(0), typelistener(tl), event(e)
00569 {
00570
00571 if(RefCounted* rc = dynamic_cast<RefCounted*>(tl)) rc->acquire();
00572 e.acquire();
00573 }
00574
00575 VobjectNotifyEvent::~VobjectNotifyEvent()
00576 {
00577 if(childlistener) if(RefCounted* rc = dynamic_cast<RefCounted*>(childlistener)) rc->release();
00578 if(parentlistener) if(RefCounted* rc = dynamic_cast<RefCounted*>(parentlistener)) rc->release();
00579 if(typelistener) if(RefCounted* rc = dynamic_cast<RefCounted*>(typelistener)) rc->release();
00580 event.release();
00581 }
00582
00583 void VobjectNotifyEvent::notify()
00584 {
00585 switch(event.getEvent()) {
00586 case VobjectEvent::TypeInsert:
00587 typelistener->notifyTypeInserted(event);
00588 break;
00589 case VobjectEvent::TypeRemove:
00590 typelistener->notifyTypeRemoved(event);
00591 break;
00592 case VobjectEvent::ParentInsert:
00593 parentlistener->notifyParentInserted(event);
00594 break;
00595 case VobjectEvent::ParentRemove:
00596 parentlistener->notifyParentRemoved(event);
00597 break;
00598 case VobjectEvent::ChildInsert:
00599 childlistener->notifyChildInserted(event);
00600 break;
00601 case VobjectEvent::ChildReplace:
00602 childlistener->notifyChildReplaced(event);
00603 break;
00604 case VobjectEvent::ChildRemove:
00605 childlistener->notifyChildRemoved(event);
00606 break;
00607 default:
00608 LOG("vobject", 0, "Supplied VobjectNotifyEvent::notify with an unsupported event type!");
00609 }
00610 }