diff --git a/libretroshare/src/Makefile b/libretroshare/src/Makefile index 0625d0c47..90667e183 100644 --- a/libretroshare/src/Makefile +++ b/libretroshare/src/Makefile @@ -3,37 +3,40 @@ all: make -C tcponudp - make -C pqi make -C util + make -C serialiser + make -C pqi make -C dbase + make -C services make -C server make -C dht make -C upnp make -C rsserver make -C rsiface -# make -C fltkgui clean: make -C tcponudp clean - make -C pqi clean make -C util clean + make -C serialiser clean + make -C pqi clean make -C dbase clean + make -C services clean make -C server clean make -C dht clean make -C upnp clean make -C rsserver clean make -C rsiface clean -# make -C fltkgui clean clobber: make -C tcponudp clobber - make -C pqi clobber make -C util clobber + make -C serialiser clobber + make -C pqi clobber make -C dbase clobber + make -C services clobber make -C server clobber make -C dht clobber make -C upnp clobber make -C rsserver clobber make -C rsiface clobber -# make -C fltkgui clobber diff --git a/libretroshare/src/make.opt b/libretroshare/src/make.opt index 1a0812a51..47cf40852 100644 --- a/libretroshare/src/make.opt +++ b/libretroshare/src/make.opt @@ -105,7 +105,7 @@ CC = g++ # flags for components.... PQI_USE_XPGP = 1 -PQI_USE_PROXY = 1 +#PQI_USE_PROXY = 1 #PQI_USE_CHANNELS = 1 USE_FILELOOK = 1 diff --git a/libretroshare/src/rsiface/rsiface.h b/libretroshare/src/rsiface/rsiface.h index a8fb3849f..099390198 100644 --- a/libretroshare/src/rsiface/rsiface.h +++ b/libretroshare/src/rsiface/rsiface.h @@ -261,8 +261,8 @@ virtual int FileSetBandwidthTotals(float outkB, float inkB) = 0; /****************************************/ /* Message Items */ virtual int MessageSend(MessageInfo &info) = 0; -virtual int MessageDelete(std::string id) = 0; -virtual int MessageRead(std::string id) = 0; +virtual int MessageDelete(std::string mid) = 0; +virtual int MessageRead(std::string mid) = 0; /* Channel Items */ virtual int ChannelCreateNew(ChannelInfo &info) = 0; diff --git a/libretroshare/src/rsiface/rstypes.h b/libretroshare/src/rsiface/rstypes.h index 2c535d4bb..62b1685ed 100644 --- a/libretroshare/src/rsiface/rstypes.h +++ b/libretroshare/src/rsiface/rstypes.h @@ -31,6 +31,8 @@ #include #include + +#if 0 #define RSCERTIDLEN 16 class RsCertId @@ -47,13 +49,11 @@ class RsCertId std::ostream &operator<<(std::ostream &out, const RsCertId &id); -/* use RsCertId, (not unsigned long) because the definition will change -typedef unsigned long RsCertId; -*/ - -typedef RsCertId RsChanId; -typedef RsCertId RsMsgId; +#endif +typedef std::string RsCertId; +typedef std::string RsChanId; +typedef std::string RsMsgId; typedef std::string RsAuthId; @@ -192,6 +192,7 @@ class FileTransferInfo: public FileInfo { public: std::string source; + std::list peerIds; int transfered; double tfRate; /* kbytes */ bool download; @@ -223,9 +224,16 @@ class MessageInfo: public BaseInfo unsigned int msgflags; std::string srcname; + + std::list msgto; + std::list msgcc; + std::list msgbcc; + std::string title; - std::string header; std::string msg; + + std::string attach_title; + std::string attach_comment; std::list files; int size; /* total of files */ int count; /* file count */ diff --git a/libretroshare/src/rsserver/p3face-file.cc b/libretroshare/src/rsserver/p3face-file.cc index ee7d668b7..e9318eda1 100644 --- a/libretroshare/src/rsserver/p3face-file.cc +++ b/libretroshare/src/rsserver/p3face-file.cc @@ -29,6 +29,8 @@ #include "rsserver/p3face.h" #include "util/rsdir.h" +#include "serialiser/rsconfigitems.h" + #include #include @@ -82,31 +84,48 @@ int RsServer::UpdateAllTransfers() std::list &transfers = iface.mTransferList; transfers.clear(); - std::list nTransList = server -> getTransfers(); - std::list::iterator it; + std::list nTransList = server -> getTransfers(); + std::list::iterator it; for(it = nTransList.begin(); it != nTransList.end(); it++) { FileTransferInfo ti; - if ((*it) -> p) + + /* set it up */ + certsign sign; + cert *c = NULL; + if (!convert_to_certsign((*it)->PeerId(), sign)) { - ti.source = (*it) -> p -> Name(); + std::cerr << "CERTSIGN error!" << std::endl; + } + + /* look it up */ + c = getSSLRoot() -> findcertsign(sign); + if (c == NULL) + { + std::cerr << "CERTSIGN error! 2" << std::endl; + ti.source = "Unknown"; } else { - ti.source = "Unknown"; + ti.source = c -> Name(); } - ti.id = intGetCertId((cert *) (*it) -> p); - ti.fname = (*it) -> name; - ti.hash = (*it) -> hash; - ti.path = (*it) -> path; - ti.size = (*it) -> size; + ti.id = (*it)->PeerId(); + ti.peerIds = (*it) -> allPeerIds.ids; + + ti.fname = (*it) -> file.name; + ti.hash = (*it) -> file.hash; + ti.path = (*it) -> file.path; + ti.size = (*it) -> file.filesize; + ti.transfered = (*it) -> transferred; /* other ones!!! */ - ti.tfRate = (*it) -> crate; + ti.tfRate = (*it) -> crate / 1000; + ti.download = (*it) -> in; ti.downloadStatus = (*it) -> state; transfers.push_back(ti); + } iface.setChanged(RsIface::Transfer); diff --git a/libretroshare/src/rsserver/p3face-msgs.cc b/libretroshare/src/rsserver/p3face-msgs.cc index 76d5ddb6b..4cf8d741c 100644 --- a/libretroshare/src/rsserver/p3face-msgs.cc +++ b/libretroshare/src/rsserver/p3face-msgs.cc @@ -37,6 +37,7 @@ const int p3facemsgzone = 11453; #include #include +#if 0 unsigned long getMsgId(RsMsgId &id) { @@ -49,7 +50,7 @@ unsigned long getMsgId(RsMsgId &id) return mid; } -void getRsMsgId(RsMsgId &rsmid, unsigned int mid) +void setMsgId(RsMsgId &rsmid, unsigned int mid) { /* version that uses the uniqueMsgId stored in sid */ /* 16 Bytes XXX Must be equal! */ @@ -64,6 +65,8 @@ void getRsMsgId(RsMsgId &rsmid, unsigned int mid) return; } +#endif + /****************************************/ /****************************************/ @@ -73,31 +76,52 @@ int RsServer::MessageSend(MessageInfo &info) /* so we send this.... */ lockRsCore(); /* LOCK */ - MsgItem *msg = new MsgItem(); + RsMsgItem *msg = new RsMsgItem(); - /* id who it is to */ - msg -> p = intFindCert(info.id); - msg -> cid = msg -> p -> cid; + /* id who it is to ???? handled lower */ + msg -> PeerId(""); - msg -> title = info.title; - msg -> header = info.header; - msg -> msg = info.msg; + msg -> msgFlags = 0; + msg -> msgId = 0; msg -> sendTime = time(NULL); + msg -> recvTime = 0; + + msg -> subject = info.title; + msg -> message = info.msg; + + std::list::iterator pit; + for(pit = info.msgto.begin(); pit != info.msgto.end(); pit++) + { + msg -> msgto.ids.push_back(pit->id); + } + + for(pit = info.msgcc.begin(); pit != info.msgcc.end(); pit++) + { + msg -> msgcc.ids.push_back(pit->id); + } + + for(pit = info.msgbcc.begin(); pit != info.msgbcc.end(); pit++) + { + msg -> msgbcc.ids.push_back(pit->id); + } + + msg -> attachment.title = info.attach_title; + msg -> attachment.comment = info.attach_comment; std::list::iterator it; for(it = info.files.begin(); it != info.files.end(); it++) { - MsgFileItem mfi; + RsTlvFileItem mfi; mfi.hash = it -> hash; mfi.name = it -> fname; - mfi.size = it -> size; - msg -> files.push_back(mfi); + mfi.filesize = it -> size; + msg -> attachment.items.push_back(mfi); } std::cerr << "RsServer::MessageSend()" << std::endl; msg->print(std::cerr); - server -> sendMessage(msg); + msgSrv -> sendMessage(msg); unlockRsCore(); /* UNLOCK */ @@ -107,20 +131,14 @@ int RsServer::MessageSend(MessageInfo &info) /****************************************/ /****************************************/ -int RsServer::MessageDelete(std::string id) +int RsServer::MessageDelete(std::string mid) { lockRsCore(); /* LOCK */ - RsMsgId uid(id); - - unsigned long mid = getMsgId(uid); - - std::cerr << "RsServer::MessageDelete()" << std::endl; - std::cerr << "str: " << id << std::endl; - std::cerr << "uid: " << uid << std::endl; + std::cerr << "RsServer::MessageDelete() "; std::cerr << "mid: " << mid << std::endl; - server -> removeMsgId(mid); + msgSrv -> removeMsgId(atoi(mid.c_str())); unlockRsCore(); /* UNLOCK */ @@ -128,20 +146,14 @@ int RsServer::MessageDelete(std::string id) return 1; } -int RsServer::MessageRead(std::string id) +int RsServer::MessageRead(std::string mid) { lockRsCore(); /* LOCK */ - RsMsgId uid(id); - - unsigned long mid = getMsgId(uid); - - std::cerr << "RsServer::MessageRead()" << std::endl; - std::cerr << "str: " << id << std::endl; - std::cerr << "uid: " << uid << std::endl; + std::cerr << "RsServer::MessageRead() "; std::cerr << "mid: " << mid << std::endl; - server -> markMsgIdRead(mid); + msgSrv -> markMsgIdRead(atoi(mid.c_str())); unlockRsCore(); /* UNLOCK */ @@ -173,22 +185,12 @@ int RsServer::ChatSend(ChatInfo &ci) /* send a message to all for now */ if (ci.chatflags & RS_CHAT_PRIVATE) { - - /* to only one person */ - RsCertId id(ci.rsid); - cert *c = intFindCert(id); - ChatItem *item = new ChatItem(); - item -> sid = getPQIsearchId(); - item -> p = c; - item -> cid = c -> cid; - item -> msg = ci.msg; - item -> flags = PQI_ITEM_FLAG_PRIVATE; - server -> sendPrivateChat(item); + chatSrv -> sendPrivateChat(ci.msg, ci.rsid); } else { /* global */ - server -> sendChat(ci.msg); + chatSrv -> sendChat(ci.msg); } unlockRsCore(); /* UNLOCK */ @@ -206,22 +208,17 @@ int RsServer::UpdateAllChat() /* get any messages and push them to iface */ -#if 1 - // at the end here, we handle chats. - if (server -> chatChanged.Changed(0)) + // get the items from the list. + std::list clist = chatSrv -> getChatQueue(); + std::list::iterator it; + for(it = clist.begin(); it != clist.end(); it++) { - // get the items from the list. - std::list clist = server -> getChatQueue(); - std::list::iterator it; - for(it = clist.begin(); it != clist.end(); it++) - { - ChatInfo ci; - initRsChatInfo((*it), ci); - iface.mChatList.push_back(ci); - delete (*it); - } + ChatInfo ci; + initRsChatInfo((*it), ci); + iface.mChatList.push_back(ci); + delete (*it); } -#endif + iface.setChanged(RsIface::Chat); /* unlock Mutexes */ @@ -245,9 +242,9 @@ int RsServer::UpdateAllMsgs() iface.lockData(); /* LOCK */ /* do stuff */ - std::list &msglist = server -> getMsgList(); - std::list &msgOutlist = server -> getMsgOutList(); - std::list::iterator mit; + std::list &msglist = msgSrv -> getMsgList(); + std::list &msgOutlist = msgSrv -> getMsgOutList(); + std::list::iterator mit; std::list &msgs = iface.mMessageList; @@ -377,16 +374,17 @@ int RsServer::UpdateAllChannels() * for intAddChannel / intAddChannelMsg. */ -void RsServer::initRsChatInfo(ChatItem *c, ChatInfo &i) +void RsServer::initRsChatInfo(RsChatItem *c, ChatInfo &i) { - RsCertId id = intGetCertId((cert *) c->p); - std::ostringstream out; - out << id; + i.rsid = c -> PeerId(); + cert *peer = intFindCert(c->PeerId()); + if (peer) + i.name = peer -> Name(); + else + i.name = "Unknown"; - i.name = c -> p -> Name(); - i.rsid = out.str(); - i.msg = c -> msg; - if (c -> flags & PQI_ITEM_FLAG_PRIVATE) + i.msg = c -> message; + if (c -> chatFlags & RS_CHAT_FLAG_PRIVATE) { std::cerr << "RsServer::initRsChatInfo() Chat Private!!!"; i.chatflags = RS_CHAT_PRIVATE; @@ -509,71 +507,100 @@ void RsServer::intCheckFileStatus(FileInfo &file) } -void RsServer::initRsMI(MsgItem *msg, MessageInfo &mi) +void RsServer::initRsMI(RsMsgItem *msg, MessageInfo &mi) { - mi.id = intGetCertId((cert *) msg->p); mi.msgflags = 0; /* translate flags, if we sent it... outgoing */ - if ((msg->msgflags & PQI_MI_FLAGS_OUTGOING) - || (msg->p == sslr->getOwnCert())) + if ((msg->msgFlags & RS_MSG_FLAGS_OUTGOING) + || (msg->PeerId() == sslr->getOwnCert()->PeerId())) { mi.msgflags |= RS_MSG_OUTGOING; } /* if it has a pending flag, then its in the outbox */ - if (msg->msgflags & PQI_MI_FLAGS_PENDING) + if (msg->msgFlags & RS_MSG_FLAGS_PENDING) { mi.msgflags |= RS_MSG_PENDING; } - if (msg->msgflags & PQI_MI_FLAGS_NEW) + if (msg->msgFlags & RS_MSG_FLAGS_NEW) { mi.msgflags |= RS_MSG_NEW; } - mi.srcname = msg->p->Name(); + mi.id = msg->PeerId(); + cert *c = intFindCert(mi.id); + if (c) + mi.srcname = c->Name(); + else + mi.srcname = "Unknown"; + + std::list::iterator pit; + + for(pit = msg->msgto.ids.begin(); + pit != msg->msgto.ids.end(); pit++) + { + PersonInfo pi; + pi.id = (*pit); + cert *peer = intFindCert(pi.id); + if (peer) + pi.name = peer->Name(); + else + pi.name = "Unknown"; + mi.msgto.push_back(pi); + } + + for(pit = msg->msgcc.ids.begin(); + pit != msg->msgcc.ids.end(); pit++) + { + PersonInfo pi; + pi.id = (*pit); + cert *peer = intFindCert(pi.id); + if (peer) + pi.name = peer->Name(); + else + pi.name = "Unknown"; + mi.msgcc.push_back(pi); + } + + for(pit = msg->msgbcc.ids.begin(); + pit != msg->msgbcc.ids.end(); pit++) + { + PersonInfo pi; + pi.id = (*pit); + cert *peer = intFindCert(pi.id); + if (peer) + pi.name = peer->Name(); + else + pi.name = "Unknown"; + mi.msgbcc.push_back(pi); + } + + mi.title = msg->subject; + mi.msg = msg->message; + + mi.attach_title = msg->attachment.title; + mi.attach_comment = msg->attachment.comment; - mi.title = msg->title; - mi.header = msg->header; - mi.msg = msg->msg; mi.count = 0; mi.size = 0; - std::list::iterator it; - for(it = msg->files.begin(); it != msg->files.end(); it++) + std::list::iterator it; + for(it = msg->attachment.items.begin(); + it != msg->attachment.items.end(); it++) { FileInfo fi; fi.fname = RsDirUtil::getTopDir(it->name); - fi.size = it->size; + fi.size = it->filesize; fi.hash = it->hash; - fi.path = it->name; + fi.path = it->path; mi.files.push_back(fi); mi.count++; mi.size += fi.size; } + mi.ts = msg->sendTime; - -#if 0 - /* hash the message (nasty to put here!) */ - std::ostringstream out; - msg->print(out); - char *data = strdup(out.str().c_str()); - unsigned int dlen = strlen(data); - unsigned int hashsize = 1024; - unsigned char hash[hashsize]; - - int hsize = sslr -> hashDigest(data, dlen, hash, hashsize); - if (hsize >= CHAN_SIGN_SIZE) - { - for(int i = 0; i < CHAN_SIGN_SIZE; i++) /* 16 Bytes XXX Must be equal! */ - mi.msgId.data[i] = hash[i]; - } - - free(data); -#else - getRsMsgId(mi.msgId, msg->sid); -#endif - + mi.msgId = msg->msgId; } /* Flagging Persons / Channels / Files in or out of a set (CheckLists) */ diff --git a/libretroshare/src/rsserver/p3face-server.cc b/libretroshare/src/rsserver/p3face-server.cc index b38645945..c10d7bebe 100644 --- a/libretroshare/src/rsserver/p3face-server.cc +++ b/libretroshare/src/rsserver/p3face-server.cc @@ -45,25 +45,18 @@ RsServer::~RsServer() ----> MUST BE LOCKED! */ -cert *RsServer::intFindCert(RsCertId &id) +cert *RsServer::intFindCert(RsCertId id) { certsign cs; - for(int i = 0; i < RSCERTIDLEN; i++) - { - cs.data[i] = id.data[i]; - } + convert_to_certsign(id, cs); return sslr -> findcertsign(cs); } -RsChanId RsServer::intGetCertId(cert *c) +RsCertId RsServer::intGetCertId(cert *c) { certsign cs; - RsChanId id; sslr -> getcertsign(c, cs); - for(int i = 0; i < RSCERTIDLEN; i++) - { - id.data[i] = cs.data[i]; - } + RsCertId id = convert_to_str(cs); return id; } diff --git a/libretroshare/src/rsserver/p3face-startup.cc b/libretroshare/src/rsserver/p3face-startup.cc index 14e6dd6de..1c76062fb 100644 --- a/libretroshare/src/rsserver/p3face-startup.cc +++ b/libretroshare/src/rsserver/p3face-startup.cc @@ -27,12 +27,15 @@ #include //#include -#include "dbase/filedex.h" #include "server/filedexserver.h" #include "pqi/pqipersongrp.h" #include "pqi/pqiloopback.h" #include "util/rsdir.h" +#include "services/p3disc.h" +#include "services/p3msgservice.h" +#include "services/p3chatservice.h" + #include #include #include @@ -455,9 +458,6 @@ int RsServer::StartupRetroShare(RsInit *config) /* sslroot does further checks */ sslr -> loadInitialTrustedPeer(config->load_trustedpeer_file); } - - server->loadWelcomeMsg(); - } unsigned long flags = 0; @@ -476,10 +476,11 @@ int RsServer::StartupRetroShare(RsInit *config) // create loopback device, and add to pqisslgrp. + std::string ownPeerId = sslr->getOwnCert()->PeerId(); SearchModule *mod = new SearchModule(); - pqiloopback *ploop = new pqiloopback(); + pqiloopback *ploop = new pqiloopback(ownPeerId); - mod -> smi = 1; + mod -> peerid = ownPeerId; mod -> pqi = ploop; mod -> sp = secpolicy_create(); @@ -491,7 +492,21 @@ int RsServer::StartupRetroShare(RsInit *config) server->load_config(); - ad = pqih->getP3Disc(); + /* create Services */ + ad = new p3disc(sslr); + msgSrv = new p3MsgService(); + chatSrv = new p3ChatService(); + + pqih -> addService(ad); + pqih -> addService(msgSrv); + pqih -> addService(chatSrv); + + /* put a welcome message in! */ + if (config->firsttime_run) + { + msgSrv->loadWelcomeMsg(); + } + // load up the help page std::string helppage = config->basedir + config->dirSeperator; diff --git a/libretroshare/src/rsserver/p3face.h b/libretroshare/src/rsserver/p3face.h index ab2a6ca52..551fea95e 100644 --- a/libretroshare/src/rsserver/p3face.h +++ b/libretroshare/src/rsserver/p3face.h @@ -30,12 +30,14 @@ #include "pqi/pqipersongrp.h" #include "pqi/pqissl.h" -#include "pqi/p3disc.h" - #include "rsiface/rsiface.h" #include "rsiface/rstypes.h" #include "util/rsthreads.h" +#include "services/p3disc.h" +#include "services/p3msgservice.h" +#include "services/p3chatservice.h" + /* The Main Interface Class - for controlling the server */ /* The init functions are actually Defined in p3face-startup.cc @@ -48,6 +50,8 @@ int LoadCertificates(RsInit *config); RsControl *createRsControl(RsIface &iface, NotifyBase ¬ify); +#if 0 + class PendingDirectory { public: @@ -60,6 +64,9 @@ void addEntry(PQFileItem *item); DirInfo data; }; +#endif + + class RsServer: public RsControl, public RsThread { @@ -99,7 +106,7 @@ void unlockRsCore() (Must be Locked) */ -cert *intFindCert(RsCertId &id); +cert *intFindCert(RsCertId id); RsCertId intGetCertId(cert *c); /****************************************/ @@ -190,9 +197,8 @@ int UpdateRemotePeople(); public: /* Message Items */ virtual int MessageSend(MessageInfo &info); -virtual int MessageDelete(std::string id); -virtual int MessageRead(std::string id); - +virtual int MessageDelete(std::string mid); +virtual int MessageRead(std::string mid); /* Channel Items */ virtual int ChannelCreateNew(ChannelInfo &info); @@ -221,7 +227,7 @@ int UpdateAllChat(); int UpdateAllMsgs(); int UpdateAllChannels(); -void initRsChatInfo(ChatItem *c, ChatInfo &i); +void initRsChatInfo(RsChatItem *c, ChatInfo &i); #ifdef PQI_USE_CHANNELS @@ -242,7 +248,7 @@ void initRsCMFI(pqichannel *chan, chanMsgSummary *msg, void intCheckFileStatus(FileInfo &file); -void initRsMI(MsgItem *msg, MessageInfo &mi); +void initRsMI(RsMsgItem *msg, MessageInfo &mi); /****************************************/ /****************************************/ @@ -300,7 +306,11 @@ int UpdateAllConfig(); filedexserver *server; pqipersongrp *pqih; sslroot *sslr; + + /* services */ p3disc *ad; + p3MsgService *msgSrv; + p3ChatService *chatSrv; // Worker Data..... diff --git a/libretroshare/src/rsserver/rstypes.cc b/libretroshare/src/rsserver/rstypes.cc index e45ca173d..232ef66c9 100644 --- a/libretroshare/src/rsserver/rstypes.cc +++ b/libretroshare/src/rsserver/rstypes.cc @@ -35,6 +35,7 @@ #include +#if 0 /****************************************/ RsCertId::RsCertId() { @@ -115,6 +116,8 @@ std::ostream &operator<<(std::ostream &out, const RsCertId &id) return out; } +#endif + /****************************************/ /* Print Functions for Info Classes */ diff --git a/libretroshare/src/services/Makefile b/libretroshare/src/services/Makefile new file mode 100644 index 000000000..f8897891b --- /dev/null +++ b/libretroshare/src/services/Makefile @@ -0,0 +1,25 @@ + +RS_TOP_DIR = .. +##### Define any flags that are needed for this section ####### +############################################################### + +############################################################### +include $(RS_TOP_DIR)/scripts/config.mk +############################################################### + +RSOBJ = p3service.o p3disc.o p3chatservice.o p3msgservice.o + +#TESTOBJ = + +#TESTS = + +all: librs tests + +#tlvbase_test : tlvbase_test.o +# $(CC) $(CFLAGS) -o tlvbase_test tlvbase_test.o $(OBJ) $(LIBS) + + +############################################################### +include $(RS_TOP_DIR)/scripts/rules.mk +############################################################### + diff --git a/libretroshare/src/services/p3chatservice.cc b/libretroshare/src/services/p3chatservice.cc new file mode 100644 index 000000000..29b15ed95 --- /dev/null +++ b/libretroshare/src/services/p3chatservice.cc @@ -0,0 +1,145 @@ +/* + * "$Id: p3ChatService.cc,v 1.24 2007-05-05 16:10:06 rmf24 Exp $" + * + * Other Bits for RetroShare. + * + * Copyright 2004-2006 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "services/p3chatservice.h" +#include "pqi/pqidebug.h" +#include + +/**************** PQI_USE_XPGP ******************/ +#if defined(PQI_USE_XPGP) + +#include "pqi/xpgpcert.h" + +#else /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + +#include "pqi/sslcert.h" + +#endif /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + + + +const int p3chatzone = 1745; + +p3ChatService::p3ChatService() + :p3Service(RS_SERVICE_TYPE_CHAT) +{ + addSerialType(new RsChatSerialiser()); +} + +int p3ChatService::tick() +{ + pqioutput(PQL_DEBUG_BASIC, p3chatzone, + "p3ChatService::tick()"); + return 0; +} + +int p3ChatService::status() +{ + pqioutput(PQL_DEBUG_BASIC, p3chatzone, + "p3ChatService::status()"); + return 1; +} + +/***************** Chat Stuff **********************/ + +int p3ChatService::sendChat(std::string msg) +{ + /* go through all the peers */ + sslroot *sslr = getSSLRoot(); + + std::list::iterator it; + std::list &certs = sslr -> getCertList(); + + for(it = certs.begin(); it != certs.end(); it++) + { + pqioutput(PQL_DEBUG_BASIC, p3chatzone, + "p3ChatService::sendChat()"); + + RsChatItem *ci = new RsChatItem(); + + ci->PeerId((*it)->PeerId()); + ci->chatFlags = 0; + ci->sendTime = time(NULL); + ci->message = msg; + + { + std::ostringstream out; + out << "Chat Item we are sending:" << std::endl; + ci -> print(out); + pqioutput(PQL_DEBUG_BASIC, p3chatzone, out.str()); + } + + sendItem(ci); + } + + return 1; +} + +int p3ChatService::sendPrivateChat(std::string msg, std::string id) +{ + // make chat item.... + pqioutput(PQL_DEBUG_BASIC, p3chatzone, + "p3ChatService::sendPrivateChat()"); + + RsChatItem *ci = new RsChatItem(); + + ci->PeerId(id); + ci->chatFlags = RS_CHAT_FLAG_PRIVATE; + ci->sendTime = time(NULL); + ci->message = msg; + + { + std::ostringstream out; + out << "Private Chat Item we are sending:" << std::endl; + ci -> print(out); + out << "Sending to:" << id << std::endl; + pqioutput(PQL_DEBUG_BASIC, p3chatzone, out.str()); + } + + sendItem(ci); + + return 1; +} + +std::list p3ChatService::getChatQueue() +{ + time_t now = time(NULL); + + RsChatItem *ci = NULL; + std::list ilist; + + while(NULL != (ci = (RsChatItem *) recvItem())) + { + ci->recvTime = now; + ilist.push_back(ci); + } + + return ilist; +} + + diff --git a/libretroshare/src/services/p3chatservice.h b/libretroshare/src/services/p3chatservice.h new file mode 100644 index 000000000..52d250493 --- /dev/null +++ b/libretroshare/src/services/p3chatservice.h @@ -0,0 +1,57 @@ +/* + * libretroshare/src/services chatservice.h + * + * Services for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef SERVICE_CHAT_HEADER +#define SERVICE_CHAT_HEADER + +/* + * The basic Chat service. + * + */ + +#include +#include + +#include "serialiser/rsmsgitems.h" +#include "services/p3service.h" + + +class p3ChatService: public p3Service +{ + public: + p3ChatService(); + + /* overloaded */ +virtual int tick(); +virtual int status(); + +int sendChat(std::string msg); +int sendPrivateChat(std::string msg, std::string id); + +std::list getChatQueue(); +}; + +#endif // SERVICE_CHAT_HEADER diff --git a/libretroshare/src/services/p3disc.cc b/libretroshare/src/services/p3disc.cc new file mode 100644 index 000000000..70e41eaf0 --- /dev/null +++ b/libretroshare/src/services/p3disc.cc @@ -0,0 +1,2229 @@ +/* + * libretroshare/src/services: p3disc.cc + * + * Services for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "services/p3disc.h" + +// for active local cert stuff. +#include "pqi/pqissl.h" + +#include +#include +#include + +const uint32_t AUTODISC_LDI_SUBTYPE_PING = 0x01; +const uint32_t AUTODISC_LDI_SUBTYPE_RPLY = 0x02; + +#include +#include "pqi/pqidebug.h" + +const int pqidisczone = 2482; + + +static int updateAutoServer(autoserver *as, RsDiscItem *di); +static int convertTDeltaToTRange(double tdelta); +static int convertTRangeToTDelta(int trange); +static int updateCertAvailabilityFlags(cert *c, unsigned long discFlags); +static unsigned long determineCertAvailabilityFlags(cert *c); + +// Operating System specific includes. +#include "pqi/pqinetwork.h" + +p3disc::p3disc(sslroot *r) + :p3Service(RS_SERVICE_TYPE_DISC), sroot(r) +{ + addSerialType(new RsDiscSerialiser()); + + ldata = NULL; + ldlenmax = 1024; + + local_disc = false; //true; + remote_disc = true; + + // set last check to current time, this prevents queued. + // messages at the start! (actually shouldn't matter - as they aren't connected). + ts_lastcheck = time(NULL); // 0; + + // configure... + load_configuration(); + localSetup(); + + return; +} + +p3disc::~p3disc() +{ + return; +} + +int p3disc::tick() +{ + pqioutput(PQL_DEBUG_ALL, pqidisczone, + "p3disc::tick()"); + + if (local_disc) + { + if (ts_nextlp == 0) + { + pqioutput(PQL_DEBUG_ALL, pqidisczone, + "Local Discovery On!"); + localPing(baddr); + localListen(); + } + } + else + { + pqioutput(PQL_DEBUG_ALL, pqidisczone, + "Local Discovery Off!"); + } + + // ten minute counter. + if (--ts_nextlp < 0) + { + ts_nextlp = 600; + } + + if (ts_nextlp % 300 == 0) + idServers(); + + + /* remote discovery can run infrequently.... + * this is a good idea, as it ensures that + * multiple Pings aren't sent to neighbours.... + * + * only run every 5 seconds. + */ + + if (ts_nextlp % 5 != 0) + { + return 1; + } + + // important bit + int nr = handleReplies(); // discards packets if not running. + if (remote_disc) + { + pqioutput(PQL_DEBUG_ALL, pqidisczone, + "Remote Discovery On!"); + newRequests(); + if ((sroot -> collectedCerts()) || (nr > 0)) + { + distillData(); + } + } + else + { + pqioutput(PQL_DEBUG_ALL, pqidisczone, + "Remote Discovery Off!"); + } + return 1; +} + +static int local_disc_def_port = 7770; +static int local_disc_secondary_port = 7870; + +int p3disc::setLocalAddress(struct sockaddr_in srvaddr) +{ + saddr = srvaddr; + return 1; +} + + +int p3disc::determineLocalNetAddr() +{ + // laddr filled in by load_configuration. + laddr.sin_port = htons(local_disc_def_port); + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS // ie UNIX + // broadcast address. + baddr.sin_family = AF_INET; + inet_aton("0.0.0.0", &(baddr.sin_addr)); + baddr.sin_port = htons(local_disc_def_port); +#else // WIN + + baddr. sin_family = AF_INET; + + // So as recommended on this site.. will use |+& to calc it. + unsigned long netmask = inet_addr("255.255.255.0"); + unsigned long netaddr = saddr.sin_addr.s_addr & netmask; + baddr.sin_addr.s_addr = netaddr | (~netmask); + + // direct works! + //baddr.sin_addr.s_addr = inet_addr("10.0.0.59"); + //baddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + // broadcast! + baddr.sin_addr.s_addr = INADDR_BROADCAST; + baddr.sin_port = htons(local_disc_def_port); + + + + + +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + { + std::ostringstream out; + out << "p3disc::determineLocalNetAddr() baddr: "; + out << inet_ntoa(baddr.sin_addr) << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + + return 1; +} + +int p3disc::setupLocalPacket(int type, struct sockaddr_in *home, + struct sockaddr_in *server) +{ + if (ldata == NULL) + { + ldata = malloc(ldlenmax); + } + + // setup packet. + // 8 bytes - tag + ((char *) ldata)[0] = 'P'; + ((char *) ldata)[1] = 'Q'; + ((char *) ldata)[2] = 'I'; + ((char *) ldata)[3] = 'L'; + if (type == AUTODISC_LDI_SUBTYPE_PING) + { + ((char *) ldata)[4] = 'D'; + ((char *) ldata)[5] = 'I'; + ((char *) ldata)[6] = 'S'; + ((char *) ldata)[7] = 'C'; + } + else + { + ((char *) ldata)[4] = 'R'; + ((char *) ldata)[5] = 'P'; + ((char *) ldata)[6] = 'L'; + ((char *) ldata)[7] = 'Y'; + } + + // sockaddr copy. + ldlen = 8; + for(unsigned int i = 0; i < sizeof(*home); i++) + { + ((char *) ldata)[ldlen + i] = ((char *) home)[i]; + } + + ldlen += sizeof(*home); + for(unsigned int i = 0; i < sizeof(*server); i++) + { + ((char *) ldata)[ldlen + i] = ((char *) server)[i]; + } + ldlen += sizeof(*server); + + return 1; +} + + + + + +int p3disc::localSetup() +{ + + if (!local_disc) + { + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "p3disc::localSetup() Warning local_disc OFF!"); + return -1; + } + + //First we must attempt to open the default socket + determineLocalNetAddr(); + + int err = 0; + + lsock = socket(PF_INET, SOCK_DGRAM, 0); +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS // ie UNIX + + if (lsock < 0) + { + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "p3disc::localSetup() Cannot open UDP socket!"); + local_disc = false; + return -1; + } + + err = fcntl(lsock, F_SETFL, O_NONBLOCK); + if (err < 0) + { + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "p3disc::localSetup() Error: Cannot make socket NON-Blocking: "); + + local_disc = false; + return -1; + } + + int on = 1; + if(0 != (err =setsockopt(lsock, SOL_SOCKET, SO_BROADCAST,(void *) &on, sizeof(on)))) + { + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "p3disc::localSetup() Error: Cannot make socket Broadcast: "); + local_disc = false; + return -1; + } + else + { + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "p3disc::localSetup() Broadcast Flag Set!"); + } + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#else //WINDOWS_SYS + + if (lsock == INVALID_SOCKET) + { + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "p3disc::localSetup() Cannot open UDP socket!"); + local_disc = false; + return -1; + } + + unsigned long int on = 1; + if (0 != (err = ioctlsocket(lsock, FIONBIO, &on))) + { + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "p3disc::localSetup() Error: Cannot make socket NON-Blocking: "); + local_disc = false; + return -1; + } + + on = 1; + if(0 != (err=setsockopt(lsock, SOL_SOCKET, SO_BROADCAST,(char *) &on, sizeof(on)))) + { + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "p3disc::localSetup() Error: Cannot make socket Broadcast: "); + + local_disc = false; + return -1; + } + else + { + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "p3disc::localSetup() Broadcast Flag Set!"); + } + +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + { + std::ostringstream out; + out << "p3disc::localSetup()" << std::endl; + out << "\tSetup Family: " << laddr.sin_family; + out << std::endl; + out << "\tSetup Address: " << inet_ntoa(laddr.sin_addr); + out << std::endl; + out << "\tSetup Port: " << ntohs(laddr.sin_port) << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + + if (0 != (err = bind(lsock, (struct sockaddr *) &laddr, sizeof(laddr)))) + { + std::ostringstream out; + out << "p3disc::localSetup()"; + out << " Cannot Bind to Default Address!" << std::endl; + showSocketError(out); + out << std::endl; + out << " Trying Secondary Address." << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + + } + else + { + // ifsucessful then call localPing + // set ts to -1 and don't worry about outgoing until + // we receive a packet + std::ostringstream out; + out << "p3disc::localSetup()" << std::endl; + out << " Bound to Address." << std::endl; + out << "\tSetup Address: " << inet_ntoa(laddr.sin_addr); + out << std::endl; + out << "\tSetup Port: " << ntohs(laddr.sin_port) << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + + ts_nextlp = -1; + ts_nextlp = 10; + localPing(baddr); + return 1; + } + + laddr.sin_port = htons(local_disc_secondary_port); + if (0 != (err = bind(lsock, (struct sockaddr *) &laddr, sizeof(laddr)))) + { + std::ostringstream out; + out << "p3disc::localSetup()"; + out << " Cannot Bind to Secondary Address!" << std::endl; + showSocketError(out); + out << std::endl; + out << " Giving Up!" << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + local_disc = false; + return -1; + } + else + { + std::ostringstream out; + out << "p3disc::localSetup()" << std::endl; + out << " Bound to Secondary Address." << std::endl; + out << "\tSetup Address: " << inet_ntoa(laddr.sin_addr); + out << std::endl; + out << "\tSetup Port: " << ntohs(laddr.sin_port) << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + + ts_nextlp = 10; + localPing(baddr); + return 1; + } + + // else we open a random port and set the timer + // ie - don't bind to a port..... + ts_nextlp = 10; // ping every 10 minutes. + localPing(baddr); + return 1; +} + +int p3disc::localPing(struct sockaddr_in reply_to) +{ + //This function sends a meessage out containing both cert + // and server address, as well as the ping address (if not standard) + + // so we send a packet out to that address + // (most likely broadcast address). + + // setup up the data for connection. + setupLocalPacket(AUTODISC_LDI_SUBTYPE_PING,&laddr, &saddr); + + // Cast to char for windows benefit. + int len = sendto(lsock, (char *) ldata, ldlen, 0, (struct sockaddr *) &reply_to, sizeof(reply_to)); + if (len != ldlen) + { + std::ostringstream out; + out << "p3disc::localPing()"; + out << " Failed to send Packet." << std::endl; + out << "Sent (" << len << "/" << ldlen; + out << std::endl; + out << "Addr:" << inet_ntoa(reply_to.sin_addr) << std::endl; + out << "Port:" << ntohs(reply_to.sin_port) << std::endl; + out << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + else + { + std::ostringstream out; + out << "p3disc::localPing() Success!" << std::endl; + out << "Sent To Addr:" << inet_ntoa(reply_to.sin_addr) << std::endl; + out << "Sent To Port:" << ntohs(reply_to.sin_port) << std::endl; + out << "Message Size: " << len << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + return 1; +} + +int p3disc::localReply(struct sockaddr_in reply_to) +{ + //This function sends a meessage out containing both cert + // and server address, as well as the ping address (if not standard) + + // so we send a packet out to that address + // (most likely broadcast address). + + // setup up the data for connection. + setupLocalPacket(AUTODISC_LDI_SUBTYPE_RPLY,&laddr, &saddr); + + // Cast to char for windows benefit. + int len = sendto(lsock, (char *) ldata, ldlen, 0, (struct sockaddr *) &reply_to, sizeof(reply_to)); + if (len != ldlen) + { + std::ostringstream out; + out << "p3disc::localPing()"; + out << " Failed to send Packet." << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + + return 1; +} + + +int p3disc::localListen() +{ + //This function listens to the ping address. + //For each reply, store the result in the structure and mark as local + struct sockaddr_in addr; + struct sockaddr_in neighbour; + struct sockaddr_in server; + socklen_t alen = sizeof(addr); + int nlen = sizeof(neighbour); + int len; + int size = 0; + + while(0 < (size = recvfrom(lsock, (char *) ldata, ldlen, 0, + (struct sockaddr *) &addr, &alen))) + { + std::ostringstream out; + out << "Recved Message" << std::endl; + out << "From Addr:" << inet_ntoa(addr.sin_addr) << std::endl; + out << "From Port:" << ntohs(addr.sin_port) << std::endl; + out << "Message Size: " << size << std::endl; + + for(int i = 0; i < 8; i++) + { + out << ((char *) ldata)[i]; + } + out << std::endl; + + len = 8; + // sockaddr copy. + for(int i = 0; i < nlen; i++) + { + ((char *) &neighbour)[i] = ((char *) ldata)[len + i]; + } + len += nlen; + for(int i = 0; i < nlen; i++) + { + ((char *) &server)[i] = ((char *) ldata)[len + i]; + } + len += nlen; + + + out << "Neighbour Addr:" << inet_ntoa(neighbour.sin_addr) << std::endl; + out << "Neighbour Port:" << ntohs(neighbour.sin_port) << std::endl; + out << "Server Addr:" << inet_ntoa(server.sin_addr) << std::endl; + out << "Server Port:" << ntohs(server.sin_port) << std::endl; + + if ((laddr.sin_addr.s_addr == neighbour.sin_addr.s_addr) && + (laddr.sin_port == neighbour.sin_port)) + { + // Then We Sent it!!!! + // ignore.. + out << "Found Self! Addr - " << inet_ntoa(neighbour.sin_addr); + out << ":" << ntohs(neighbour.sin_port) << std::endl; + } + else + { + if ('D' == (((char *) ldata)[4])) // Then Ping. + { + // reply. + localReply(neighbour); + } + + addLocalNeighbour(&neighbour, &server); + } + + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS // ie UNIX + + if ((size < 0) && (errno != EAGAIN)) + { + std::ostringstream out; + out << "Error Recieving Message" << std::endl; + out << "Errno: " << errno << std::endl; + out << socket_errorType(errno) << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#else // WINDOWS_SYS + + if (size == SOCKET_ERROR) + { + int err = WSAGetLastError(); + if (err != WSAEWOULDBLOCK) + { + std::ostringstream out; + out << "Error Recieving Message" << std::endl; + out << "WSE: " << err << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + } + +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + return 1; +} + +// This needs to be fixed up.... +// Local dicsovery disabled for the moment.... + +int p3disc::addLocalNeighbour(struct sockaddr_in *n, struct sockaddr_in *s) +{ + std::list::iterator it; + for(it = neighbours.begin(); it != neighbours.end(); it++) + { + // if the server address matches one already! + // make sure its flags as local and return. + if (0 == memcmp((char *) &((*it) -> server_addr), (char *) s, sizeof(*s))) + { + (*it) -> local = true; + return 1; + } + } + // else add it in! + autoneighbour *ln = new autoneighbour(); + ln -> server_addr = (*s); + ln -> local = true; + ln -> id = NULL; // null cert + + std::string nname = "Local Neighbour ("; + nname += inet_ntoa(ln -> server_addr.sin_addr); + nname += ")"; + + //ln -> id -> Name(nname); + + // now we call the dummy connect... + // this will only be done once per local neighbour. + // connectForExchange(ln -> server_addr); + + neighbours.push_back(ln); + // update dicovered. + distillData(); + return 1; +} + + +// Code Fragment that might be useful when local is patched up.... +/**************************************************** +int p3disc::distillLocalData() +{ + // This transforms the autoneighbour tree into + // a list of certificates with the best guess settings. + + discovered.clear(); + + pqioutput(PQL_DEBUG_BASIC, pqidisczone, "p3disc::distillData()"); + + std::list::iterator it; + std::list::iterator it2; + + // Now check for local -> remote duplicates.... + for(it = neighbours.begin(); it != neighbours.end();) + { + cert *c = (cert *) ((*it) -> id); + if (((*it) -> local) && (c == NULL)) + { + // potentially a duplicate. + bool found = false; + for(it2 = neighbours.begin(); it2 != neighbours.end(); it2++) + { + // if address is the same -> remove first version. + if ((it != it2) && (0 == memcmp((char *) &((*it) -> addr), + (char *) &((*it2) -> addr), + sizeof(struct sockaddr)))) + { + (*it2) -> local = true; + found = true; + } + } + if (found == true) + { + // remove the certless local. + it = neighbours.erase(it); + } + else + { + it++; + } + } + else + { + it++; + } + } + +******************************************/ + + +int p3disc::idServers() +{ + std::list::iterator it; + std::list::iterator nit; + int cts = time(NULL); + + std::ostringstream out; + out << "::::AutoDiscovery Neighbours::::" << std::endl; + for(it = neighbours.begin(); it != neighbours.end(); it++) + { + if ((*it) -> local) + { + out << "Local Neighbour: "; + } + else + { + out << "Friend of a friend: "; + } + cert *c = (cert *) ((*it) -> id); + + if (c != NULL) + { + if (c -> certificate != NULL) + { + out << c -> certificate -> name; + } + else + { + out << c -> Name(); + } + } + else + { + out << "UnIdentified"; + } + + out << std::endl; + out << "BG LocalAddr: "; + out << inet_ntoa((*it) -> local_addr.sin_addr); + out << ":" << ntohs((*it) -> local_addr.sin_port) << std::endl; + out << "BG Server: "; + out << inet_ntoa((*it) -> server_addr.sin_addr); + out << ":" << ntohs((*it) -> server_addr.sin_port) << std::endl; + out << " Listen TR: "; + if (((*it) -> listen) && ((*it) -> l_ts)) + { + out << cts - (*it) -> l_ts << " sec ago"; + } + else + { + out << "Never"; + } + out << " "; + + out << "Connect TR: "; + if (((*it) -> connect) && ((*it) -> c_ts)) + { + out << cts - (*it) -> c_ts << " sec ago"; + } + else + { + out << "Never"; + } + + if ((*it) -> active) + { + out << " Active!!!"; + } + out << std::endl; + + out << " -->DiscFlags: 0x" << std::hex << (*it)->discFlags; + out << std::dec << std::endl; + + for(nit = ((*it) -> neighbour_of).begin(); + nit != ((*it) -> neighbour_of).end(); nit++) + { + out << "\tConnected via: "; + if ((*nit) -> id != NULL) + { + out << ((*nit) ->id) -> Name() << "("; + out << inet_ntoa(((*nit) -> id) -> lastaddr.sin_addr); + out << ":" << ntohs(((*nit) -> id) -> lastaddr.sin_port); + out << ")"; + } + out << std::endl; + out << "\t\tServer: "; + out << inet_ntoa((*nit) -> server_addr.sin_addr); + out <<":"<< ntohs((*nit) -> server_addr.sin_port); + out << std::endl; + out << "\t\tLocalAddr: "; + out << inet_ntoa((*nit) -> local_addr.sin_addr); + out <<":"<< ntohs((*nit) -> local_addr.sin_port); + + out << std::endl; + if ((*nit) -> listen) + { + out << "\t\tListen TR:"; + out << cts - (*nit) -> l_ts << " sec ago"; + } + else + { + out << "\t\tNever Received!"; + } + out << std::endl; + if ((*nit) -> connect) + { + out << "\t\tConnect TR:"; + out << cts - (*nit) -> c_ts << " sec ago"; + } + else + { + out << "\t\tNever Connected!"; + } + out << std::endl; + out << "\t\tDiscFlags: 0x" << std::hex << (*nit)->discFlags; + out << std::dec << std::endl; + } + } + pqioutput(PQL_WARNING, pqidisczone, out.str()); + return 1; +} + + + + +int p3disc::newRequests() +{ + // Check the timestamp against the list of certs. + // If any are newer and currently active, then + // send out Discovery Request. + // This initiates the p3disc procedure. + + if (!remote_disc) + { + pqioutput(PQL_DEBUG_ALL, pqidisczone, + "p3disc::newRequests() Remote Discovery is turned off"); + return -1; + } + + pqioutput(PQL_DEBUG_ALL, pqidisczone, + "p3disc::newRequests() checkin for new neighbours"); + + // Perform operation on the cert list. + std::list::iterator it; + // Temp variable + std::list &certlist = sroot -> getCertList(); + + { + std::ostringstream out; + out << "Checking CertList!" << std::endl; + out << "last_check: " << ts_lastcheck; + out << " time(): " << time(NULL); + pqioutput(PQL_DEBUG_ALL, pqidisczone, out.str()); + } + + for(it = certlist.begin(); it != certlist.end(); it++) + { + { + std::ostringstream out; + out << "Cert: " << (*it) -> Name(); + out << " lc_ts: " << (*it) -> lc_timestamp; + out << " lr_ts: " << (*it) -> lr_timestamp; + pqioutput(PQL_DEBUG_ALL, pqidisczone, out.str()); + } + + // This should be Connected(), rather than Accepted(). + // should reply with all Accepted(), but only send to all connected(). + // if (((*it) -> Accepted()) && + // + // need >= to ensure that it will happen, + // about 1 in 5 chance of multiple newRequests if called every 5 secs. + // can live with this. (else switch to fractional seconds). + + if (((*it) -> Connected()) && + (((*it) -> lc_timestamp >= ts_lastcheck) + || ((*it) -> lr_timestamp >= ts_lastcheck))) + { + + // also must not have already sent message. + // (unless reconnection?) + // actually - this should occur, even if last + // exchange not complete. + // reconnect + +/***************************************************************************** + * No more need for ad_init silliness.... + * + //if (ad_init.end() == + // find(ad_init.begin(),ad_init.end(),*it)) + // infact - we need the opposite behaviour. + // remove if in the init list. + + std::list::iterator it2; + if (ad_init.end() != + (it2 = find(ad_init.begin(),ad_init.end(),*it))) + { + ad_init.erase(it2); + } + * + * + * + ****************************************************************************/ + + + { + // Then send message. + { + std::ostringstream out; + out << "p3disc::newRequests()"; + out << "Constructing a Message!" << std::endl; + out << "Sending to: " << (*it) -> Name(); + out << " lc_ts: " << (*it) -> lc_timestamp; + out << " lr_ts: " << (*it) -> lr_timestamp; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + + // Construct a message + RsDiscItem *di = new RsDiscItem(); + + // get our details..... + cert *own = sroot -> getOwnCert(); + + // Fill the message + di -> PeerId((*it) -> PeerId()); + di -> laddr = own -> localaddr; + di -> saddr = own -> serveraddr; + + // if we are firewalled..... (and no forwarding...) + // set received as impossible. + if (own -> Firewalled() && (!(own -> Forwarded()))) + di -> receive_tr = 0; /* invalid */ + else + di -> receive_tr = 1; /* zero time */ + + di -> connect_tr = 1; /* zero time */ + di -> discFlags = determineCertAvailabilityFlags(own); + + // Send off message + sendItem(di); + +/***************************************************************************** + * No more need for ad_init silliness.... + // push onto init list. + ad_init.push_back(*it); + * + ****************************************************************************/ + + // Finally we should also advertise the + // new connection to our neighbours???? + // SHOULD DO - NOT YET. + + } + } + } + ts_lastcheck = time(NULL); + return 1; +} + +int p3disc::handleReplies() +{ + RsItem *item = NULL; + pqioutput(PQL_DEBUG_ALL, pqidisczone, "p3disc::handleReplies()"); + + // if off discard item. + if (!remote_disc) + { + while(NULL != (item = recvItem())) + { + std::ostringstream out; + out << "p3disc::handleReplies()"; + out << " Deleting - Cos RemoteDisc Off!" << std::endl; + + item -> print(out); + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + + delete item; + } + return 0; + } + + int nhandled = 0; + // While messages read + while(NULL != (item = recvItem())) + { + RsDiscItem *di = NULL; + RsDiscReply *dri = NULL; + + if (NULL == (di = dynamic_cast (item))) + { + std::ostringstream out; + out << "p3disc::handleReplies()"; + out << "Deleting Non RsDiscItem Msg" << std::endl; + item -> print(out); + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + + // delete and continue to next loop. + delete item; + + continue; + } + nhandled++; + + { + std::ostringstream out; + out << "p3disc::handleReplies()"; + out << " Received Message!" << std::endl; + di -> print(out); + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + + + // if discovery reply then respondif haven't already. + if (NULL != (dri = dynamic_cast (di))) + { + + // add to data tree. + handleDiscoveryData(dri); + } + else /* Ping */ + { + handleDiscoveryPing(di); + + /* find the certificate */ + certsign sign; + convert_to_certsign(di->PeerId(), sign); + cert *peer = getSSLRoot() -> findcertsign(sign); + if (peer) + { + sendDiscoveryReply(peer); + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "After Reply to Ping"); + } + else + { + pqioutput(PQL_ALERT, pqidisczone, + "Failed to Match disc Ping ID"); + } + } + delete di; + } + return nhandled; +} + +int p3disc::sendDiscoveryReply(cert *p) +{ + if (!remote_disc) + return -1; + + // So to send a discovery reply .... we need to.... + // 1) generate a list of our neighbours..... + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "p3disc::sendDiscoveryReply() Generating Messages!"); + + std::list::iterator it; + // Temp variable + std::list &certlist = sroot -> getCertList(); + int good_certs = 0; + int cts = time(NULL); + + for(it = certlist.begin(); it != certlist.end(); it++) + { + // if accepted and has connected (soon) + if ((*it) -> Accepted()) + { + good_certs++; + + { + std::ostringstream out; + out << "p3disc::sendDiscoveryReply()"; + out << " Found Neighbour Cert!" << std::endl; + out << "Encoding: "<<(*it)->Name() << std::endl; + out << "Encoding(2): "<<(*it)->certificate->name << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + + // Construct a message + RsDiscReply *di = new RsDiscReply(); + + // Fill the message + // Set Target as input cert. + di -> PeerId(p -> PeerId()); + + // set the server address. + di -> laddr = (*it) -> localaddr; + di -> saddr = (*it) -> serveraddr; + + // set the timeframe since last connection. + if ((*it) -> lr_timestamp <= 0) + { + di -> receive_tr = 0; + } + else + { + di -> receive_tr = convertTDeltaToTRange(cts - (*it) -> lr_timestamp); + } + + if ((*it) -> lc_timestamp <= 0) + { + di -> connect_tr = 0; + } + else + { + di -> connect_tr = convertTDeltaToTRange(cts - (*it) -> lc_timestamp); + } + di -> discFlags = determineCertAvailabilityFlags(*it); + + // actually ned to copy certificate to array + // for proper cert stuff. + +/**************** PQI_USE_XPGP ******************/ +#if defined(PQI_USE_XPGP) + int len = i2d_XPGP((*it) -> certificate, (unsigned char **) &(di -> certDER.bin_data)); +#else /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + int len = i2d_X509((*it) -> certificate, (unsigned char **) &(di -> certDER.bin_data)); +#endif /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + if (len > 0) + { + di -> certDER.bin_len = len; + std::ostringstream out; + out << "Cert Encoded(" << len << ")" << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + else + { + pqioutput(PQL_DEBUG_BASIC, pqidisczone, "Failed to Encode Cert"); + di -> certDER.bin_len = 0; + } + + // Send off message + sendItem(di); + pqioutput(PQL_DEBUG_BASIC, pqidisczone, "Sent DI Message"); + } + else + { + std::ostringstream out; + out << "p3disc::sendDiscoveryReply()"; + out << "Not Sending Cert: " << std::endl; + out << (*it) -> Name() << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + + } + + { + std::ostringstream out; + out << "p3disc::sendDiscoveryReply()"; + out << "Found " << good_certs << " Certs" << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + + return 1; +} + + +int p3disc::handleDiscoveryPing(RsDiscItem *di) +{ + std::list::iterator it; + + // as already connected.... certificate available. + certsign sign; + convert_to_certsign(di->PeerId(), sign); + cert *c = getSSLRoot() -> findcertsign(sign); + + if (c == NULL) + return -1; + + { + std::ostringstream out; + out << "p3disc::handleDiscoveryPing()" << std::endl; + di -> print(out); + out << "RECEIVED Self Describing RsDiscItem!"; + out << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + + // The first check is whether this packet came from + // the cert in the reply. + + // Local address is always right! + // No User control anyway! + c -> localaddr = di -> laddr; + + // The Rest of this should only be set + // if we are in autoconnect mode..... + // else should be done manually. + // ----> Think we should do this always (is disc from then) + /**************************** + if (!(c -> Manual())) + ****************************/ + { + + // if the connect addr isn't valid. + if (!isValidNet(&(c -> lastaddr.sin_addr))) + { + // set it all + c -> serveraddr = di -> saddr; + pqioutput(PQL_WARNING, pqidisczone, + "lastaddr !Valid -> serveraddr=di->saddr"); + } + // if the connect addr == dispkt.local + else if (0 == inaddr_cmp(c -> lastaddr, di -> laddr)) + { + // set it all + c -> serveraddr = di -> saddr; + c -> Local(true); + pqioutput(PQL_WARNING, pqidisczone, + "lastaddr=di->laddr -> Local & serveraddr=di->saddr"); + } + else if (0 == inaddr_cmp(c -> lastaddr, di -> saddr)) + { + pqioutput(PQL_WARNING, pqidisczone, + "lastaddr=di->saddr -> !Local & serveraddr=di->saddr"); + c -> serveraddr = di -> saddr; + c -> Local(false); + } + else + { + pqioutput(PQL_WARNING, pqidisczone, + "lastaddr!=(di->laddr|di->saddr) -> !Local,serveraddr left"); + c -> Local(false); + } + + updateCertAvailabilityFlags(c, di->discFlags); + + } + /**************************** + else + { + pqioutput(PQL_WARNING, pqidisczone, + "peer is Manual -> leaving server settings"); + if (0 == inaddr_cmp(c -> lastaddr, di -> laddr)) + { + pqioutput(PQL_WARNING, pqidisczone, + "c->lastaddr=di->laddr -> local"); + c -> Local(true); + } + else + { + pqioutput(PQL_WARNING, pqidisczone, + "c->lastaddr!=di->laddr -> !local"); + c -> Local(false); + } + + } + ****************************/ + + // Now add it into the system. + // check if it exists already...... + for(it = neighbours.begin(); it != neighbours.end(); it++) + { + cert *c2 = (cert *) (*it) -> id; +/**************** PQI_USE_XPGP ******************/ +#if defined(PQI_USE_XPGP) + if ((c2 != NULL) && (0 == XPGP_cmp( + c -> certificate, c2 -> certificate))) +#else /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + if ((c2 != NULL) && (0 == X509_cmp( + c -> certificate, c2 -> certificate))) +#endif /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + { + // matching.... + // update it....; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, "Updating Certificate (AN)!"); + + (*it)-> local = c -> Local(); + updateAutoServer((*it), di); + + /* now look through the neighbours_of */ + std::list::iterator nit; + for(nit = ((*it) -> neighbour_of).begin(); + nit != ((*it) -> neighbour_of).end(); nit++) + { + + /* check if we already have a autoserver.... */ + if ((*it)->id == (*nit)->id) + { + /* we already have one */ + // update it....; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "Updating Certificate (AS)!"); + + updateAutoServer(*nit, di); + return 0; + } + } + + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "Adding Certificate (AS)!"); + + /* if we get here, we need to add an autoserver */ + autoserver *as = new autoserver(); + as -> id = c; + updateAutoServer(as, di); + (*it) -> neighbour_of.push_back(as); + + return 1; + } + } + + // if get here must add a autoneighbour + an autoserver. + + autoneighbour *an = new autoneighbour(); + an -> id = c; + an -> local = c -> Local(); + updateAutoServer(an, di); + + // add autoserver to an. + autoserver *as = new autoserver(); + as -> id = c; + updateAutoServer(as, di); + + an -> neighbour_of.push_back(as); + neighbours.push_back(an); + + return 1; +} + + +int p3disc::handleDiscoveryData(RsDiscReply *di) +{ + std::list::iterator it; + + { + std::ostringstream out; + out << "p3disc::handleDiscoveryData()" << std::endl; + di -> print(out); + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + + + certsign sign; + convert_to_certsign(di->PeerId(), sign); + cert *di_peer = getSSLRoot() -> findcertsign(sign); + if (!di_peer) + { + std::ostringstream out; + out << "p3disc::handleDiscoveryData() BAD Id" << std::endl; + di -> print(out); + pqioutput(PQL_ALERT, pqidisczone, out.str()); + delete di; + return 0; + } + + + /* WIN/LINUX Difference. + */ +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ +#ifndef WINDOWS_SYS // ie UNIX + const unsigned char *certptr = (const unsigned char *) di -> certDER.bin_data; +#else + unsigned char *certptr = (unsigned char *) di -> certDER.bin_data; +#endif +/********************************** WINDOWS/UNIX SPECIFIC PART ******************/ + + + // load up the certificate..... +/**************** PQI_USE_XPGP ******************/ +#if defined(PQI_USE_XPGP) + + XPGP *tmp = NULL; + XPGP *xpgp = d2i_XPGP(&tmp, (unsigned char **) &certptr, di -> certDER.bin_len); + if (xpgp == NULL) + return -1; + { + std::ostringstream out; + out << "p3disc::handleDiscoveryData()" << std::endl; + out << "certificate name: " << xpgp -> name << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + + // if a duplicate with ad/or sslroot; + cert *c = sroot -> makeCertificateXPGP(xpgp); + if (c == NULL) + { + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "Failed to Create Certificate"); + // delete the cert. + XPGP_free(xpgp); + return -1; + } + + +#else /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + + X509 *tmp = NULL; + X509 *x509 = d2i_X509(&tmp, &certptr, di -> certLen); + if (x509 == NULL) + return -1; + { + std::ostringstream out; + out << "p3disc::handleDiscoveryData()" << std::endl; + out << "certificate name: " << x509 -> name << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + + // if a duplicate with ad/or sslroot; + cert *c = sroot -> makeCertificate(x509); + if (c == NULL) + { + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "Failed to Create Certificate"); + // delete the cert. + X509_free(x509); + return -1; + } + +#endif /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + + + // So have new/existing cert; + // check if it exists already...... + for(it = neighbours.begin(); it != neighbours.end(); it++) + { + cert *c2 = (cert *) (*it) -> id; + +/**************** PQI_USE_XPGP ******************/ +#if defined(PQI_USE_XPGP) + if ((c2 != NULL) && (0 == XPGP_cmp( + c -> certificate, c2 -> certificate))) +#else /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + if ((c2 != NULL) && (0 == X509_cmp( + c -> certificate, c2 -> certificate))) +#endif /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + { + // matching.... check neighbours of.... + // for the source of the message. + + std::list::iterator nit; + for(nit = ((*it) -> neighbour_of).begin(); + nit != ((*it) -> neighbour_of).end(); nit++) + { + + +/**************** PQI_USE_XPGP ******************/ +#if defined(PQI_USE_XPGP) + if (0 == XPGP_cmp( +#else /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + if (0 == X509_cmp( +#endif /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + ((cert *) (*nit) -> id) -> certificate, + di_peer -> certificate)) + { + + // update it....; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "Updating Certificate!"); + + updateAutoServer(*nit, di); + + return 0; + } + } + + // if we get to here - add neighbour of info. + autoserver *as = new autoserver(); + as -> id = di_peer; + + // add in some more ....as -> addr = (di -> ); + + updateAutoServer(as, di); + + (*it) -> neighbour_of.push_back(as); + + return 1; + } + } + + // if get here must add a autoneighbour + autoserver. + + { + std::ostringstream out; + out << "p3disc::handleDiscoveryData()" << std::endl; + out << "Adding New AutoNeighbour:" << c -> Name() << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + + autoneighbour *an = new autoneighbour(); + an -> id = c; + // initial guess. + an -> local_addr = di -> laddr; + an -> server_addr = di -> saddr; + an -> local = false; + + autoserver *as = new autoserver(); + as -> id = di_peer; + + updateAutoServer(as, di); + + an -> neighbour_of.push_back(as); + + neighbours.push_back(an); + + return 1; +} + +int p3disc::collectCerts() +{ + + // First get any extras from the CollectedCerts Queue. + // if the cert matches an existing one.... update + discard + // else add in.... + + std::list::iterator it; + std::list::iterator it2; + + cert *nc; + while(NULL != (nc = sroot -> getCollectedCert())) + { + // check for matching certs. + bool found = false; + + { + std::ostringstream out; + out << "p3disc::collectCert: " << std::endl; + out << "Name: " << nc -> Name() << std::endl; + out << "CN: " << nc -> certificate -> name << std::endl; + + out << " From: "; + out << inet_ntoa(nc -> lastaddr.sin_addr); + out << ":" << ntohs(nc -> lastaddr.sin_port) << std::endl; + out << " Local: "; + out << inet_ntoa(nc -> localaddr.sin_addr); + out << ":" << ntohs(nc -> localaddr.sin_port) << std::endl; + out << " Server: "; + out << inet_ntoa(nc -> serveraddr.sin_addr); + out << ":" << ntohs(nc -> serveraddr.sin_port) << std::endl; + out << " Listen TS:"; + out << nc -> lr_timestamp << " "; + out << "Connect TR:"; + out << nc -> lc_timestamp << std::endl; + out << std::endl; + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + } + + + for(it = neighbours.begin(); (!found) && (it != neighbours.end()); it++) + { + cert *c = (cert *) ((*it) -> id); +/**************** PQI_USE_XPGP ******************/ +#if defined(PQI_USE_XPGP) + if ((c != NULL) && + (0 == XPGP_cmp(c -> certificate, nc -> certificate))) +#else /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + if ((c != NULL) && + (0 == X509_cmp(c -> certificate, nc -> certificate))) +#endif /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + { + /* addresses handled already .... + * by sslroot. (more intelligent decisions). + * update timestamps so we don't overwrite + * the uptodate cert data. + */ + + found = true; + if ((nc -> lc_timestamp > 0) && + ((unsigned) nc -> lc_timestamp > (*it) -> c_ts)) + { + // connect.... timestamp + (*it) -> connect = true; + (*it) -> c_ts = nc -> lc_timestamp; + // don't make this decision here. + //(*it) -> server_addr = nc -> lastaddr; + } + + if ((nc -> lr_timestamp > 0) && + ((unsigned) nc -> lr_timestamp > (*it) -> l_ts)) + { + // received.... timestamp + (*it) -> listen = true; + (*it) -> l_ts = nc -> lr_timestamp; + } + + if ((c != nc) || + (c -> certificate != nc -> certificate)) + { + std::ostringstream out; + out << "Warning Dup/Diff Mem "; + out << " Found in p3Disc!"; + out << std::endl; + pqioutput(PQL_ALERT, pqidisczone, out.str()); + exit(1); + } + } + } + if (!found) + { + // add into the list..... + autoneighbour *an = new autoneighbour(); + an -> id = nc; + + // initial guess. + an -> local_addr = nc -> localaddr; + an -> server_addr = nc -> serveraddr; + an -> local = false; + + if (nc -> lc_timestamp > 0) + { + an -> c_ts = nc -> lc_timestamp; + an -> connect = true; + } + else + { + an -> c_ts = 0; + an -> connect = false; + } + + if (nc -> lr_timestamp > 0) + { + an -> l_ts = nc -> lr_timestamp; + an -> listen = true; + } + else + { + an -> l_ts = 0; + an -> listen = false; + } + + neighbours.push_back(an); + } + } + return 1; +} + +int p3disc::distillData() +{ + // This transforms the autoneighbour tree into + // a list of certificates with the best guess settings. + + // get any extra. from sslroot. + collectCerts(); + + discovered.clear(); + + std::ostringstream out; + out << "p3disc::distillData()" << std::endl; + + std::list::iterator it; + std::list::iterator it2; + std::list::iterator nit; + cert *own = sroot -> getOwnCert(); + + for(it = neighbours.begin(); it != neighbours.end(); it++) + { + /* for the moment this is going to be a simplistic + * (and non-fault tolerent design).... + * we will take the most up-to-date values.... from the friends of neighbours. + * + * if these are more up-to-date than both the + * (1) neighbour (*it) and + * (2) the actual certificate and + * (3) we are not connected... then + * + * (a) we update the addresses and timestamps on the neighbour. + * (b) addresses on the certificate. + * + * Therefore + * cert has (1) our connect times, (2) best guess server. + * neighbour has uptodate times/servers from last distill. + * + * NOTE this requires a better algorithm. + * + */ + + unsigned int mr_connect = 0; + unsigned int mr_listen = 0; + + unsigned int mr_both = 0; /* connect or receive */ + /* three fields below match most recent (of either) */ + struct sockaddr_in mr_server; + struct sockaddr_in mr_local; + unsigned int mr_flags = 0; + + /* if we find a neighbour_of, which is the same cert. + * then we have the definitive answer already + * (and it has been installed) + */ + + bool haveDefinitive = false; + + cert *c = (cert *) (*it) -> id; + for(nit = ((*it) -> neighbour_of).begin(); + nit != ((*it) -> neighbour_of).end(); nit++) + { + out << "\tDistill Connected via: "; + if ((*nit) -> id != NULL) + { + out << ((*nit) ->id) -> Name(); + } + out << std::endl; + out << "\t\tServer: "; + out << inet_ntoa((*nit)->server_addr.sin_addr); + out << ":" << ntohs((*nit)->server_addr.sin_port); + out << std::endl; + if ((*nit)->id == (*it)->id) + { + haveDefinitive = true; + out << "\t\tIs Definitive Answer!"; + out << std::endl; + } + + if ((*nit) -> listen) + { + if ((*nit)->l_ts > mr_listen) + { + mr_listen = (*nit)->l_ts; + if (mr_listen > mr_both) + { + mr_both = mr_listen; + mr_server = (*nit) -> server_addr; + mr_local = (*nit) -> local_addr; + mr_flags = (*nit) -> discFlags; + } + } + } + + if ((*nit) -> connect) + { + if ((*nit) -> c_ts > mr_connect) + { + mr_connect = (*nit)->c_ts; + if (mr_connect > mr_both) + { + mr_both = mr_connect; + mr_server = (*nit) -> server_addr; + mr_local = (*nit) -> local_addr; + mr_flags = (*nit) -> discFlags; + } + } + } + } + + if ((c == own) || (haveDefinitive)) + { + out << c -> Name(); + out << ": Is Own or Definitive: no Update..."; + out << std::endl; + + discovered.push_back(c); + continue; + } + + if ((mr_both > (*it)-> c_ts) && (mr_both > (*it)-> l_ts)) + { + (*it) -> server_addr = mr_server; + (*it) -> local_addr = mr_local; + (*it) -> discFlags = mr_flags; + + } + + /* now we can check against (*it) */ + if ((!(*it)->listen) || ((*it)-> l_ts < mr_listen)) + { + (*it) -> listen = true; + (*it)-> l_ts = mr_listen; + } + + if ((!(*it)->connect) || ((*it)-> c_ts < mr_connect)) + { + (*it) -> connect = true; + (*it)-> c_ts = mr_connect; + } + + /* XXX fixme ***/ + // Finally we can update the certificate, if auto + // is selected.... or not in use. + if (!(c -> Connected())) + { + out << "Checking: " << c -> Name() << std::endl; + + // if empty local + if (0 == inaddr_cmp(c -> localaddr, INADDR_ANY)) + { + out << "\tUpdating NULL Local Addr:" << std::endl; + out << "\t\tOld: "; + out << inet_ntoa(c->localaddr.sin_addr); + out << ":" << ntohs(c->localaddr.sin_port); + c -> localaddr = (*it) -> local_addr; + out << "\t\tNew: "; + out << inet_ntoa(c->localaddr.sin_addr); + out << ":" << ntohs(c->localaddr.sin_port); + } + + // if empty server ..... + if (0 == inaddr_cmp(c -> serveraddr, INADDR_ANY)) + { + out << "\tUpdating NULL Serv Addr:" << std::endl; + out << "\t\tOld: "; + out << inet_ntoa(c->serveraddr.sin_addr); + out << ":" << ntohs(c->serveraddr.sin_port); + c -> serveraddr = (*it) -> server_addr; + out << "\t\tNew: "; + out << inet_ntoa(c->serveraddr.sin_addr); + out << ":" << ntohs(c->serveraddr.sin_port); + } + // if local (second as should catch empty) + else if ((0 == inaddr_cmp((*it) -> server_addr, + c -> localaddr))) + //&& (inaddr_local(c -> localaddr)) + { + out << "\tMaking Local..." << std::endl; + c -> Local(true); + } + + // Finally the key update .... + // check only against the latest data.... + + if (mr_both) + { + // + unsigned int cert_both = c -> lc_timestamp; + if (cert_both < (unsigned) c -> lr_timestamp) + { + cert_both = c -> lr_timestamp; + } + + int log_delta = -1; /* invalid log */ + if (mr_both > cert_both) + { + log_delta = (int) log10((double) (mr_both - cert_both)); + } + + /* if a peer has connected more recently than us */ + if (log_delta > 3) // or > 10000 (secs), or ~3 hours. + { + out << "\tUpdating OLD Addresses:" << std::endl; + out << "\t\tOld Local: "; + out << inet_ntoa(c->serveraddr.sin_addr); + out << ":" << ntohs(c->serveraddr.sin_port); + out << std::endl; + out << "\t\tOld Server: "; + out << inet_ntoa(c->serveraddr.sin_addr); + out << ":" << ntohs(c->serveraddr.sin_port); + out << std::endl; + if (c->Firewalled()) + { + out << "\t\tFireWalled/"; + } + else + { + out << "\t\tNot FireWalled/"; + } + if (c->Forwarded()) + { + out << "Forwarded"; + } + else + { + out << "Not Forwarded"; + } + out << std::endl; + + if (0!=inaddr_cmp(mr_server, INADDR_ANY)) + { + c -> serveraddr = mr_server; + } + + if (0!=inaddr_cmp(mr_local, INADDR_ANY)) + { + c -> localaddr = mr_local; + } + + updateCertAvailabilityFlags(c, mr_flags); + + out << "\t\tNew: "; + out << inet_ntoa(c->serveraddr.sin_addr); + out << ":" << ntohs(c->serveraddr.sin_port); + out << "\t\tNew Local: "; + out << inet_ntoa(c->serveraddr.sin_addr); + out << ":" << ntohs(c->serveraddr.sin_port); + out << std::endl; + out << "\t\tNew Server: "; + out << inet_ntoa(c->serveraddr.sin_addr); + out << ":" << ntohs(c->serveraddr.sin_port); + out << std::endl; + if (c->Firewalled()) + { + out << "\t\tFireWalled/"; + } + else + { + out << "\t\tNot FireWalled/"; + } + if (c->Forwarded()) + { + out << "Forwarded"; + } + else + { + out << "Not Forwarded"; + } + out << std::endl; + } + } + } + discovered.push_back(c); + } + pqioutput(PQL_DEBUG_BASIC, pqidisczone, out.str()); + idServers(); + return 1; +} + +std::list &p3disc::getDiscovered() +{ + return discovered; +} + +static const std::string pqi_adflags("PQI_ADFLAGS"); + +int p3disc::save_configuration() +{ + if (sroot == NULL) + return -1; + + std::string localflags; + if (local_disc) + localflags += "L"; + if (remote_disc) + localflags += "R"; + sroot -> setSetting(pqi_adflags, localflags); + return 1; +} + + +// load configuration from sslcert -> owncert() +// instead of from the configuration files. + +int p3disc::load_configuration() +{ + unsigned int i = 0; + + if (sroot == NULL) + return -1; + + Person *p = sroot -> getOwnCert(); + if (p == NULL) + return -1; + laddr = p -> localaddr; + //laddr.sin_family = AF_INET; + + saddr = p -> serveraddr; + local_firewalled = p -> Firewalled(); + local_forwarded = p -> Forwarded(); + + std::string localflags = sroot -> getSetting(pqi_adflags); + // initially drop out gracefully. + if (localflags.length() == 0) + return 1; + if (i < localflags.length()) + if (local_disc = ('L' == localflags[i])) + i++; + if (i < localflags.length()) + if (remote_disc = ('R' == localflags[i])) + i++; + // temp turn on! + local_disc = false; // true; + remote_disc = true; + return 1; +} + + +std::list p3disc::potentialproxy(cert *target) +{ + std::list certs; + // search the discovery tree for proxies for target. + + std::list::iterator it; + std::list::iterator nit; + + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "p3disc::potentialproxy()"); + + for(it = neighbours.begin(); it != neighbours.end(); it++) + { + cert *c = (cert *) (*it) -> id; + if (c == target) + { + // found target. + for(nit = ((*it) -> neighbour_of).begin(); + nit != ((*it) -> neighbour_of).end(); nit++) + { + /* can't use target as proxy */ + cert *pp = (cert *) (*nit)->id; + if ((pp -> Connected()) && (target != pp)) + { + std::ostringstream out; + out << "Potential Proxy: "; + out << pp -> Name(); + certs.push_back(pp); + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + out.str()); + } + } + + return certs; + } + } + + pqioutput(PQL_DEBUG_BASIC, pqidisczone, + "p3disc::potentialproxy() No proxies found"); + // empty list. + return certs; +} + +std::list p3disc::requestStunServers() +{ + + /* loop through all the possibilities + * + * find the ones which aren't firewalled. + * + * get their addresses. + */ + cert *own = sroot -> getOwnCert(); + + std::list stunList; + + std::list::iterator it; + for(it = neighbours.begin(); it != neighbours.end(); it++) + { + cert *c = (cert *) (*it) -> id; + + /* if flags are correct, and the address looks + * valid. + */ + +/* switch on Local Stun for testing */ +/* + * #define STUN_ALLOW_LOCAL_NET 1 + */ + + +#ifdef STUN_ALLOW_LOCAL_NET + bool isExtern = true; +#else + bool isExtern = (!c->Firewalled()) || + (c->Firewalled() && c->Forwarded()); +#endif + + if (isExtern) + { + // second level of checks. + // if we will connect, and haven't -> they are probably + // offline. + if (c->Accepted() && (!c->Connected())) + { + std::ostringstream out; + out << "Offline Friend: "; + out << c -> Name(); + out << " not available for Stun"; + pqioutput(PQL_DEBUG_ALERT, pqidisczone, out.str()); + isExtern = false; + } + + // and address looks good. + // + // and not in our subnet (external to us) + } + + + if (isExtern) + { + std::ostringstream out; + out << "Potential Stun Server: "; + out << c -> Name(); + out << std::endl; + out << " ServerAddr: " << inet_ntoa(c->serveraddr.sin_addr); + out << " : " << ntohs(c->serveraddr.sin_port); + out << std::endl; + out << " LocalAddr: " << inet_ntoa(c->localaddr.sin_addr); + out << " : " << ntohs(c->localaddr.sin_port); + out << std::endl; + +#ifdef STUN_ALLOW_LOCAL_NET + if (isValidNet(&(c->serveraddr.sin_addr)) && + (!sameNet(&(own->serveraddr.sin_addr), &(c->serveraddr.sin_addr)))) +#else + if ((isValidNet(&(c->serveraddr.sin_addr))) && + (!isPrivateNet(&(c->serveraddr.sin_addr))) && + (!sameNet(&(own->localaddr.sin_addr), &(c->serveraddr.sin_addr))) && + (!sameNet(&(own->serveraddr.sin_addr), &(c->serveraddr.sin_addr)))) +#endif + { + out << " -- Chose Server Address"; + out << std::endl; + stunList.push_back(c->serveraddr); + } +#ifdef STUN_ALLOW_LOCAL_NET + else if (isValidNet(&(c->localaddr.sin_addr))) +#else + else if ((!c->Firewalled()) && + (isValidNet(&(c->localaddr.sin_addr))) && + (!isPrivateNet(&(c->localaddr.sin_addr))) && + (!sameNet(&(own->localaddr.sin_addr), &(c->localaddr.sin_addr)))) +#endif + { + out << " -- Chose Local Address"; + out << std::endl; + stunList.push_back(c->localaddr); + } + else + { + out << "<=> Invalid / Private Addresses"; + out << std::endl; + } + pqioutput(PQL_DEBUG_ALERT, pqidisczone, out.str()); + } + else + { + std::ostringstream out; + out << "Non-Stun Neighbour: "; + out << c -> Name(); + pqioutput(PQL_DEBUG_ALERT, pqidisczone, out.str()); + } + } + + return stunList; +} + + + + + +// tdelta -> trange. +// -inf...<0 0 (invalid) +// 0.. <9 1 +// 9...<99 2 +// 99...<999 3 +// 999...<9999 4 +// etc... + +int convertTDeltaToTRange(double tdelta) +{ + if (tdelta < 0) + return 0; + int trange = 1 + (int) log10(tdelta + 1.0); + return trange; + +} + +// trange -> tdelta +// -inf...0 -1 (invalid) +// 1 8 +// 2 98 +// 3 998 +// 4 9998 +// etc... + +int convertTRangeToTDelta(int trange) +{ + if (trange <= 0) + return -1; + + return (int) (pow(10.0, trange) - 1.5); // (int) xxx98.5 -> xxx98 +} + +// fn which updates: connect, c_ts, +// listen, l_ts, +// local_addr, server_addr, +// and discFlags. +int updateAutoServer(autoserver *as, RsDiscItem *di) +{ + int cts = time(NULL); + + + as->listen = (di->receive_tr != 0); + as->connect= (di->connect_tr != 0); + + /* convert [r|c]_tf to timestamps.... + * + * Conversion to a _tf.... + * + * + * */ + if (as->listen) + { + as->l_ts = cts - convertTRangeToTDelta(di->receive_tr); + } + + if (as->connect) + { + as->c_ts = cts - convertTRangeToTDelta(di->connect_tr); + + } + as->local_addr = di->laddr; + as->server_addr = di->saddr; + as->discFlags = di->discFlags; + + return 1; +} + + +static const int PQI_DISC_FLAGS_FIREWALLED = 0x0001; +static const int PQI_DISC_FLAGS_FORWARDED = 0x0002; +static const int PQI_DISC_FLAGS_LOCAL = 0x0004; + +int updateCertAvailabilityFlags(cert *c, unsigned long discFlags) +{ + if (c) + { + c->Firewalled(discFlags & PQI_DISC_FLAGS_FIREWALLED); + c->Forwarded(discFlags & PQI_DISC_FLAGS_FORWARDED); + + if (discFlags & PQI_DISC_FLAGS_FIREWALLED) + { + pqioutput(PQL_WARNING, pqidisczone, + "updateCertAvailabilityFlags() Setting Firewalled Flag = true"); + } + else + { + pqioutput(PQL_WARNING, pqidisczone, + "updateCertAvailabilityFlags() Setting Firewalled Flag = false"); + } + + if (discFlags & PQI_DISC_FLAGS_FORWARDED) + { + pqioutput(PQL_WARNING, pqidisczone, + "updateCertAvailabilityFlags() Setting Forwarded Flag = true"); + } + else + { + pqioutput(PQL_WARNING, pqidisczone, + "updateCertAvailabilityFlags() Setting Forwarded Flag = false"); + } + + return 1; + } + return 0; +} + + +unsigned long determineCertAvailabilityFlags(cert *c) +{ + unsigned long flags = 0; + if (c->Firewalled()) + { + flags |= PQI_DISC_FLAGS_FIREWALLED; + } + + if (c->Forwarded()) + { + flags |= PQI_DISC_FLAGS_FORWARDED; + } + + if (c->Local()) + { + flags |= PQI_DISC_FLAGS_LOCAL; + } + + return flags; +} + diff --git a/libretroshare/src/services/p3disc.h b/libretroshare/src/services/p3disc.h new file mode 100644 index 000000000..c0a212cff --- /dev/null +++ b/libretroshare/src/services/p3disc.h @@ -0,0 +1,169 @@ +/* + * libretroshare/src/services: p3disc.h + * + * Services for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef MRK_PQI_AUTODISC_H +#define MRK_PQI_AUTODISC_H + +// The AutoDiscovery Class + +#include +#include + +// system specific network headers +#include "pqi/pqinetwork.h" + +#include "pqi/pqi.h" + +/**************** PQI_USE_XPGP ******************/ +#if defined(PQI_USE_XPGP) + +#include "pqi/xpgpcert.h" + +#else /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + +#include "pqi/sslcert.h" + +#endif /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + + +#include "serialiser/rsdiscitems.h" +#include "services/p3service.h" + +class autoserver +{ + public: + autoserver() + :id(NULL), ca(NULL), connect(false), c_ts(0), + listen(false), l_ts(0), discFlags(0) { return;} + + Person *id; + Person *ca; + bool connect; + unsigned int c_ts; // this is connect_tf converted to timestamp, 0 invalid. + + bool listen; + unsigned int l_ts; // this is receive_tf converted to timestamp, 0 invalid. + + struct sockaddr_in local_addr; + struct sockaddr_in server_addr; + unsigned long discFlags; +}; + + +class autoneighbour: public autoserver +{ + public: + autoneighbour() + :autoserver(), local(false), active(false) {} + + bool local; + bool active; // meaning in ssl's list. + std::list neighbour_of; + +}; + + +class p3disc: public p3Service +{ + public: + bool local_disc; + bool remote_disc; + //sslroot *sslbase; + + p3disc(sslroot *r); +virtual ~p3disc(); + + // Overloaded from p3Service functions. +virtual int tick(); + + + // For Proxy Information. +std::list requestStunServers(); +std::list potentialproxy(cert *target); + + // load and save configuration to sslroot. + int save_configuration(); + int load_configuration(); + + int ts_lastcheck; + + int idServers(); + + // Handle Local Discovery. + int localListen(); + int localSetup(); + + int lsock; // local discovery socket. + struct sockaddr_in laddr; // local addr + struct sockaddr_in baddr; // local broadcast addr. + struct sockaddr_in saddr; // pqi ssl server addr. + + // bonus configuration flags. + bool local_firewalled; + bool local_forwarded; + + + // local message construction/destruction. + void *ldata; + int ldlen; + int ldlenmax; + + + bool std_port; // if we have bound to default. + int ts_nextlp; // -1 for never (if on default) + + // helper functions. + int setLocalAddress(struct sockaddr_in srvaddr); + int determineLocalNetAddr(); + int setupLocalPacket(int type, struct sockaddr_in *home, + struct sockaddr_in *server); + int localPing(struct sockaddr_in); + int localReply(struct sockaddr_in); + int addLocalNeighbour(struct sockaddr_in*, struct sockaddr_in*); + + // remote discovery function. + int newRequests(); + int handleReplies(); + + int handleDiscoveryData(RsDiscReply *di); + int handleDiscoveryPing(RsDiscItem *di); + int sendDiscoveryReply(cert *); + int collectCerts(); + int distillData(); + + //cert *checkDuplicateX509(X509 *x509); + std::list &getDiscovered(); + + // Main Storage + std::list neighbours; + std::list ad_init; + + std::list discovered; + sslroot *sroot; +}; + +#endif // MRK_PQI_AUTODISC_H diff --git a/libretroshare/src/services/p3msgservice.cc b/libretroshare/src/services/p3msgservice.cc new file mode 100644 index 000000000..2a6d06198 --- /dev/null +++ b/libretroshare/src/services/p3msgservice.cc @@ -0,0 +1,383 @@ +/* + * libretroshare/src/services msgservice.cc + * + * Services for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#include "pqi/pqibin.h" +#include "pqi/pqiarchive.h" +#include "pqi/pqidebug.h" + +#include "services/p3msgservice.h" + +#include +#include + + +/**************** PQI_USE_XPGP ******************/ +#if defined(PQI_USE_XPGP) + +#include "pqi/xpgpcert.h" + +#else /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + +#include "pqi/sslcert.h" + +#endif /* X509 Certificates */ +/**************** PQI_USE_XPGP ******************/ + + +const int msgservicezone = 54319; + + +/* Another little hack ..... unique message Ids + * will be handled in this class..... + * These are unique within this run of the server, + * and are not stored long term.... + * + * Only 3 entry points: + * (1) from network.... + * (2) from local send + * (3) from storage... + */ + +static unsigned int msgUniqueId = 1; +unsigned int getNewUniqueMsgId() +{ + return msgUniqueId++; +} + +p3MsgService::p3MsgService() + :p3Service(RS_SERVICE_TYPE_MSG), + msgChanged(1), msgMajorChanged(1) +{ + sslr = getSSLRoot(); +} + + +int p3MsgService::tick() +{ + pqioutput(PQL_DEBUG_BASIC, msgservicezone, + "p3MsgService::tick()"); + + /* don't worry about increasing tick rate! + * (handled by p3service) + */ + + incomingMsgs(); + checkOutgoingMessages(); + + return 0; +} + + +int p3MsgService::status() +{ + pqioutput(PQL_DEBUG_BASIC, msgservicezone, + "p3MsgService::status()"); + + return 1; +} + +int p3MsgService::incomingMsgs() +{ + RsMsgItem *mi; + int i = 0; + while((mi = (RsMsgItem *) recvItem()) != NULL) + { + ++i; + mi -> recvTime = time(NULL); + std::string mesg; + + if (mi -> PeerId() == sslr->getOwnCert()->PeerId()) + { + /* from the loopback device */ + mi -> msgFlags = RS_MSG_FLAGS_OUTGOING; + } + else + { + /* from a peer */ + mi -> msgFlags = 0; + } + + /* new as well! */ + mi -> msgFlags |= RS_MSG_FLAGS_NEW; + + /* STORE MsgID */ + mi -> msgId = getNewUniqueMsgId(); + + imsg.push_back(mi); + msgChanged.IndicateChanged(); + } + return 1; +} + + +std::list &p3MsgService::getMsgList() +{ + return imsg; +} + +std::list &p3MsgService::getMsgOutList() +{ + return msgOutgoing; +} + +/* remove based on the unique mid (stored in sid) */ +int p3MsgService::removeMsgId(uint32_t mid) +{ + std::list::iterator it; + + for(it = imsg.begin(); it != imsg.end(); it++) + { + if ((*it)->msgId == mid) + { + RsMsgItem *mi = (*it); + imsg.erase(it); + delete mi; + msgChanged.IndicateChanged(); + msgMajorChanged.IndicateChanged(); + return 1; + } + } + + /* try with outgoing messages otherwise */ + for(it = msgOutgoing.begin(); it != msgOutgoing.end(); it++) + { + if ((*it)->msgId == mid) + { + RsMsgItem *mi = (*it); + msgOutgoing.erase(it); + delete mi; + msgChanged.IndicateChanged(); + msgMajorChanged.IndicateChanged(); + return 1; + } + } + + return 0; +} + +int p3MsgService::markMsgIdRead(uint32_t mid) +{ + std::list::iterator it; + + for(it = imsg.begin(); it != imsg.end(); it++) + { + if ((*it)->msgId == mid) + { + RsMsgItem *mi = (*it); + mi -> msgFlags &= ~(RS_MSG_FLAGS_NEW); + msgChanged.IndicateChanged(); + return 1; + } + } + return 0; +} + +int p3MsgService::sendMessage(RsMsgItem *item) +{ + pqioutput(PQL_DEBUG_BASIC, msgservicezone, + "p3MsgService::sendMessage()"); + + /* add pending flag */ + item->msgFlags |= + (RS_MSG_FLAGS_OUTGOING | + RS_MSG_FLAGS_PENDING); + /* STORE MsgID */ + item -> msgId = getNewUniqueMsgId(); + msgOutgoing.push_back(item); + + return 1; +} + +int p3MsgService::checkOutgoingMessages() +{ + /* iterate through the outgoing queue + * + * if online, send + */ + + std::list::iterator it; + for(it = msgOutgoing.begin(); it != msgOutgoing.end();) + { + + /* find the certificate */ + certsign sign; + convert_to_certsign((*it)->PeerId(), sign); + cert *peer = sslr -> findcertsign(sign); + + /* if online, send it */ + if ((peer -> Status() & PERSON_STATUS_CONNECTED) + || (peer == sslr->getOwnCert())) + { + /* send msg */ + pqioutput(PQL_ALERT, msgservicezone, + "p3MsgService::checkOutGoingMessages() Sending out message"); + /* remove the pending flag */ + (*it)->msgFlags &= ~RS_MSG_FLAGS_PENDING; + + sendItem(*it); + it = msgOutgoing.erase(it); + } + else + { + pqioutput(PQL_ALERT, msgservicezone, + "p3MsgService::checkOutGoingMessages() Delaying until available..."); + it++; + } + } + return 0; +} + + +int p3MsgService::save_config() +{ + std::list::iterator it; + std::string empty(""); + + pqioutput(PQL_DEBUG_BASIC, msgservicezone, + "p3MsgService::save_config()"); + + /* now we create a pqiarchive, and stream all the msgs into it + */ + + std::string statelog = config_dir + "/msgs.rst"; + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsMsgSerialiser()); + + BinFileInterface *out = new BinFileInterface((char *) statelog.c_str(), BIN_FLAGS_WRITEABLE); + pqiarchive *pa_out = new pqiarchive(rss, out, BIN_FLAGS_WRITEABLE | BIN_FLAGS_NO_DELETE); + bool written = false; + + std::list::iterator mit; + for(mit = imsg.begin(); mit != imsg.end(); mit++) + { + //RsMsgItem *mi = (*mit)->clone(); + if (pa_out -> SendItem(*mit)) + { + written = true; + } + + } + + for(mit = msgOutgoing.begin(); mit != msgOutgoing.end(); mit++) + { + //RsMsgItem *mi = (*mit)->clone(); + //mi -> msgFlags |= RS_MSG_FLAGS_PENDING; + if (pa_out -> SendItem(*mit)) + { + written = true; + } + + } + + if (!written) + { + /* need to push something out to overwrite old data! (For WINDOWS ONLY) */ + } + + delete pa_out; + return 1; +} + +int p3MsgService::load_config() +{ + std::list::iterator it; + + std::string empty(""); + std::string dir("notempty"); + std::string str_true("true"); + + /* load msg/ft */ + std::string statelog = config_dir + "/msgs.rst"; + + RsSerialiser *rss = new RsSerialiser(); + rss->addSerialType(new RsMsgSerialiser()); + + BinFileInterface *in = new BinFileInterface((char *) statelog.c_str(), BIN_FLAGS_READABLE); + pqiarchive *pa_in = new pqiarchive(rss, in, BIN_FLAGS_READABLE); + RsItem *item; + RsMsgItem *mitem; + + while((item = pa_in -> GetItem())) + { + if (NULL != (mitem = dynamic_cast(item))) + { + /* switch depending on the PENDING + * flags + */ + /* STORE MsgID */ + mitem->msgId = getNewUniqueMsgId(); + if (mitem -> msgFlags & RS_MSG_FLAGS_PENDING) + { + std::cerr << "MSG_PENDING"; + std::cerr << std::endl; + mitem->print(std::cerr); + msgOutgoing.push_back(mitem); + } + else + { + imsg.push_back(mitem); + } + } + else + { + delete item; + } + } + + delete pa_in; + + return 1; +} + + +void p3MsgService::loadWelcomeMsg() +{ + /* Load Welcome Message */ + RsMsgItem *msg = new RsMsgItem(); + + msg -> PeerId(sslr->getOwnCert()->PeerId()); + + msg -> sendTime = 0; + + msg -> subject = "Welcome to Retroshare"; + + msg -> message = "Send and receive messages\n"; + msg -> message += "with your friends...\n\n"; + + msg -> message += "These can hold recommendations\n"; + msg -> message += "from your local shared files\n\n"; + + msg -> message += "Add recommendations through\n"; + msg -> message += "the Local Files Dialog\n\n"; + + msg -> message += "Enjoy.\n"; + + imsg.push_back(msg); +} + + + diff --git a/libretroshare/src/services/p3msgservice.h b/libretroshare/src/services/p3msgservice.h new file mode 100644 index 000000000..eaca14d9b --- /dev/null +++ b/libretroshare/src/services/p3msgservice.h @@ -0,0 +1,84 @@ +/* + * libretroshare/src/services msgservice.h + * + * Services for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + +#ifndef MESSAGE_SERVICE_HEADER +#define MESSAGE_SERVICE_HEADER + +#include +#include +#include + +#include "pqi/pqi.h" +#include "pqi/pqiindic.h" +#include "services/p3service.h" +#include "serialiser/rsmsgitems.h" + +#include "rsiface/rsiface.h" +class pqimonitor; +class sslroot; + +class p3MsgService: public p3Service +{ + public: + p3MsgService(); + +void loadWelcomeMsg(); /* startup message */ + +int sendMessage(RsMsgItem *item); +int checkOutgoingMessages(); + +std::list &getMsgList(); +std::list &getMsgOutList(); + + // cleaning up.... +int removeMsgId(uint32_t mid); /* id stored in sid */ +int markMsgIdRead(uint32_t mid); + +int load_config(); +int save_config(); + +int tick(); +int status(); + + private: + +int incomingMsgs(); + + +std::list imsg; +std::list msgOutgoing; /* ones that haven't made it out yet! */ + +// bool state flags. + public: + Indicator msgChanged; + Indicator msgMajorChanged; + +sslroot *sslr; +std::string config_dir; + +}; + +#endif // MESSAGE_SERVICE_HEADER diff --git a/libretroshare/src/services/p3service.cc b/libretroshare/src/services/p3service.cc new file mode 100644 index 000000000..7d2a0fc00 --- /dev/null +++ b/libretroshare/src/services/p3service.cc @@ -0,0 +1,163 @@ +/* + * libretroshare/src/services p3service.cc + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#include "pqi/pqi.h" +#include "services/p3service.h" + +void p3Service::addSerialType(RsSerialType *st) +{ + rsSerialiser->addSerialType(st); +} + +RsItem *p3Service::recvItem() +{ + srvMtx.lock(); /***** LOCK MUTEX *****/ + + if (recv_queue.size() == 0) + { + srvMtx.unlock(); /***** UNLOCK MUTEX *****/ + return NULL; /* nothing there! */ + } + + /* get something off front */ + RsItem *item = recv_queue.front(); + recv_queue.pop_front(); + + srvMtx.unlock(); /***** UNLOCK MUTEX *****/ + return item; +} + + +bool p3Service::receivedItems() +{ + srvMtx.lock(); /***** LOCK MUTEX *****/ + + bool moreData = (recv_queue.size() != 0); + + srvMtx.unlock(); /***** UNLOCK MUTEX *****/ + + return moreData; +} + + +int p3Service::sendItem(RsItem *item) +{ + srvMtx.lock(); /***** LOCK MUTEX *****/ + + send_queue.push_back(item); + + srvMtx.unlock(); /***** UNLOCK MUTEX *****/ + + return 1; +} + + // overloaded pqiService interface. +int p3Service::receive(RsRawItem *raw) +{ + srvMtx.lock(); /***** LOCK MUTEX *****/ + + std::cerr << "p3Service::receive()" << std::endl; + + /* convert to RsServiceItem */ + uint32_t size = raw->getRawLength(); + RsItem *item = rsSerialiser->deserialise(raw->getRawData(), &size); + if ((!item) || (size != raw->getRawLength())) + { + /* error in conversion */ + std::cerr << "p3Service::receive() Error" << std::endl; + std::cerr << "p3Service::receive() Size: " << size << std::endl; + std::cerr << "p3Service::receive() RawLength: " << raw->getRawLength() << std::endl; + if (item) + { + delete item; + } + } + + + /* if we have something - pass it on */ + if (item) + { + /* ensure PeerId is transferred */ + item->PeerId(raw->PeerId()); + recv_queue.push_back(item); + } + + /* cleanup input */ + delete raw; + + srvMtx.unlock(); /***** UNLOCK MUTEX *****/ + + return (item != NULL); +} + +RsRawItem *p3Service::send() +{ + srvMtx.lock(); /***** LOCK MUTEX *****/ + + if (send_queue.size() == 0) + { + srvMtx.unlock(); /***** UNLOCK MUTEX *****/ + return NULL; /* nothing there! */ + } + + /* get something off front */ + RsItem *si = send_queue.front(); + send_queue.pop_front(); + + /* try to convert */ + uint32_t size = rsSerialiser->size(si); + if (!size) + { + /* can't convert! */ + delete si; + srvMtx.unlock(); /***** UNLOCK MUTEX *****/ + return NULL; + } + + RsRawItem *raw = new RsRawItem(si->PacketId(), size); + if (!rsSerialiser->serialise(si, raw->getRawData(), &size)) + { + delete raw; + raw = NULL; + } + + if ((raw) && (size != raw->getRawLength())) + { + delete raw; + raw = NULL; + } + + /* ensure PeerId is transferred */ + raw->PeerId(si->PeerId()); + + /* cleanup */ + delete si; + + srvMtx.unlock(); /***** UNLOCK MUTEX *****/ + return raw; +} + + + diff --git a/libretroshare/src/services/p3service.h b/libretroshare/src/services/p3service.h new file mode 100644 index 000000000..a65cc6f01 --- /dev/null +++ b/libretroshare/src/services/p3service.h @@ -0,0 +1,116 @@ +/* + * libretroshare/src/services p3service.h + * + * 3P/PQI network interface for RetroShare. + * + * Copyright 2004-2008 by Robert Fernie. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + +#ifndef P3_GENERIC_SERVICE_HEADER +#define P3_GENERIC_SERVICE_HEADER + +#include "pqi/pqi.h" +#include "pqi/pqiservice.h" +#include "util/rsthreads.h" + +/* This provides easy to use extensions to the pqiservice class provided in src/pqi. + * + * We will have a number of different strains. + * + * (1) p3Service -> pqiService + * + * Basic service with serialisation handled by a RsSerialiser. + * + * (2) p3ThreadedService -> p3service. + * + * Independent thread with mutex locks for i/o Queues. + * ideal for games etc. + * + * (3) p3CacheService -> p3service + CacheSource + CacheStore. + * + * For both Cached and Messages. + */ + +class p3Service: public pqiService +{ + protected: + + p3Service(uint16_t type) + :pqiService((((uint32_t) RS_PKT_VERSION_SERVICE) << 24) + (((uint32_t) type) << 8)), + rsSerialiser(NULL) + { + rsSerialiser = new RsSerialiser(); + return; + } + + public: + +virtual ~p3Service() { delete rsSerialiser; return; } + +/*************** INTERFACE ******************************/ + /* called from Thread/tick/GUI */ +int sendItem(RsItem *); +RsItem * recvItem(); +bool receivedItems(); + +virtual int tick() { return 0; } +/*************** INTERFACE ******************************/ + + + public: + // overloaded pqiService interface. +virtual int receive(RsRawItem *); +virtual RsRawItem * send(); + + protected: +void addSerialType(RsSerialType *); + + private: + + RsMutex srvMtx; + /* below locked by Mutex */ + + RsSerialiser *rsSerialiser; + std::list recv_queue, send_queue; +}; + + +#if 0 + +class p3ThreadedService: public p3Service, public RsThread +{ + protected: + + p3ThreadedService(RsSerialiser *rss, uint32_t type) + :p3Service(rss, type) { return; } + + public: + +virtual ~p3ThreadedService() { return; } + + private: + +}; + +#endif + + +#endif // P3_GENERIC_SERVICE_HEADER +