// TODO: Prohibit multiple logins #include #include #include #include "Swiften/Elements/IQ.h" #include "Swiften/Elements/Presence.h" #include "Swiften/Elements/RosterPayload.h" #include "Swiften/Elements/VCard.h" #include "Swiften/Server/UserRegistry.h" #include "Swiften/JID/JID.h" #include "Swiften/Base/String.h" #include "Swiften/Server/UserRegistry.h" #include "Swiften/Base/IDGenerator.h" #include "Swiften/EventLoop/MainEventLoop.h" #include "Swiften/EventLoop/SimpleEventLoop.h" #include "Swiften/EventLoop/EventOwner.h" #include "Swiften/Elements/Stanza.h" #include "Swiften/LinkLocal/LinkLocalServiceInfo.h" #include "Swiften/LinkLocal/LinkLocalRoster.h" #include "Swiften/LinkLocal/DNSSDService.h" #include "Swiften/LinkLocal/AppleDNSSDService.h" #include "Swiften/Network/ConnectionServer.h" #include "Swiften/Network/BoostConnection.h" #include "Swiften/Network/BoostIOServiceThread.h" #include "Swiften/Network/BoostConnectionServer.h" #include "Swiften/Server/ServerFromClientSession.h" #include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h" #include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h" using namespace Swift; class DummyUserRegistry : public UserRegistry { public: DummyUserRegistry() { } virtual bool isValidUserPassword(const JID&, const String&) const { return true; } }; class Server { public: Server(int clientConnectionPort, int linkLocalConnectionPort) : dnsSDServiceRegistered_(false), rosterRequested_(false), clientConnectionPort_(clientConnectionPort), linkLocalConnectionPort_(linkLocalConnectionPort) { serverFromClientConnectionServer_ = boost::shared_ptr(new BoostConnectionServer(clientConnectionPort, &boostIOServiceThread_.getIOService())); serverFromClientConnectionServer_->onNewConnection.connect(boost::bind(&Server::handleNewClientConnection, this, _1)); serverFromClientConnectionServer_->start(); serverFromNetworkConnectionServer_ = boost::shared_ptr(new BoostConnectionServer(linkLocalConnectionPort, &boostIOServiceThread_.getIOService())); serverFromNetworkConnectionServer_->onNewConnection.connect(boost::bind(&Server::handleNewLinkLocalConnection, this, _1)); serverFromNetworkConnectionServer_->start(); dnsSDService_ = boost::shared_ptr(new AppleDNSSDService()); linkLocalRoster_ = boost::shared_ptr(new LinkLocalRoster(dnsSDService_)); linkLocalRoster_->onRosterChanged.connect(boost::bind(&Server::handleRosterChanged, this, _1)); linkLocalRoster_->onPresenceChanged.connect(boost::bind(&Server::handlePresenceChanged, this, _1)); dnsSDService_->start(); } private: void handleNewClientConnection(boost::shared_ptr c) { if (serverFromClientSession_) { c->disconnect(); } serverFromClientSession_ = boost::shared_ptr(new ServerFromClientSession(idGenerator_.generateID(), c, &payloadParserFactories_, &payloadSerializers_, &userRegistry_)); serverFromClientSession_->onStanzaReceived.connect(boost::bind(&Server::handleStanzaReceived, this, _1, serverFromClientSession_)); serverFromClientSession_->onSessionStarted.connect(boost::bind(&Server::handleSessionStarted, this, serverFromClientSession_)); serverFromClientSession_->onSessionFinished.connect(boost::bind(&Server::handleSessionFinished, this, serverFromClientSession_)); serverFromClientSession_->start(); } void handleNewLinkLocalConnection(boost::shared_ptr) { std::cout << "Incoming link local connection" << std::endl; } void handleSessionStarted(boost::shared_ptr session) { if (!dnsSDServiceRegistered_) { dnsSDServiceRegistered_ = true; dnsSDService_->onServiceRegistered.connect(boost::bind(&Server::handleServiceRegistered, this, _1)); LinkLocalServiceInfo info; info.setFirstName("Remko"); info.setLastName("Tron\xc3\xa7on"); info.setEMail("email@example.com"); info.setJID(JID("jid@example.com")); info.setMessage("I'm not Here"); info.setNick("Remko"); info.setStatus(LinkLocalServiceInfo::Away); info.setPort(linkLocalConnectionPort_); dnsSDService_->registerService(session->getJID().toBare().toString(), linkLocalConnectionPort_, info); } } void handleServiceRegistered(const DNSSDService::Service& service) { std::cout << "Service registered " << service.name << " " << service.type << " " << service.domain << std::endl; } void handleSessionFinished(boost::shared_ptr) { serverFromClientSession_.reset(); std::cout << "Service unregistered" << std::endl; dnsSDServiceRegistered_ = false; rosterRequested_ = false; dnsSDService_->unregisterService(); } void handleStanzaReceived(boost::shared_ptr stanza, boost::shared_ptr session) { stanza->setFrom(session->getJID()); if (!stanza->getTo().isValid()) { stanza->setTo(JID(session->getDomain())); } if (!stanza->getTo().isValid() || stanza->getTo() == session->getDomain() || stanza->getTo() == session->getJID().toBare()) { if (boost::shared_ptr iq = boost::dynamic_pointer_cast(stanza)) { if (iq->getPayload()) { if (iq->getType() == IQ::Get) { session->sendStanza(IQ::createResult(iq->getFrom(), iq->getID(), linkLocalRoster_->getRoster())); rosterRequested_ = true; foreach(const boost::shared_ptr presence, linkLocalRoster_->getAllPresence()) { session->sendStanza(presence); } } else { session->sendStanza(IQ::createError(iq->getFrom(), iq->getID(), Error::Forbidden, Error::Cancel)); } } if (iq->getPayload()) { if (iq->getType() == IQ::Get) { boost::shared_ptr vcard(new VCard()); vcard->setNickname(iq->getFrom().getNode()); session->sendStanza(IQ::createResult(iq->getFrom(), iq->getID(), vcard)); } else { session->sendStanza(IQ::createError(iq->getFrom(), iq->getID(), Error::Forbidden, Error::Cancel)); } } else { session->sendStanza(IQ::createError(iq->getFrom(), iq->getID(), Error::FeatureNotImplemented, Error::Cancel)); } } } } void handleRosterChanged(boost::shared_ptr roster) { if (rosterRequested_) { boost::shared_ptr iq = IQ::createRequest(IQ::Set, serverFromClientSession_->getJID(), idGenerator_.generateID(), roster); iq->setFrom(serverFromClientSession_->getJID().toBare()); serverFromClientSession_->sendStanza(iq); } } void handlePresenceChanged(boost::shared_ptr presence) { if (rosterRequested_) { serverFromClientSession_->sendStanza(presence); } } private: IDGenerator idGenerator_; BoostIOServiceThread boostIOServiceThread_; DummyUserRegistry userRegistry_; boost::shared_ptr dnsSDService_; boost::shared_ptr linkLocalRoster_; boost::shared_ptr serverFromClientConnectionServer_; boost::shared_ptr serverFromClientSession_; boost::shared_ptr serverFromNetworkConnectionServer_; FullPayloadParserFactoryCollection payloadParserFactories_; FullPayloadSerializerCollection payloadSerializers_; bool dnsSDServiceRegistered_; bool rosterRequested_; int clientConnectionPort_; int linkLocalConnectionPort_; }; int main() { SimpleEventLoop eventLoop; Server server(5222, 5562); eventLoop.run(); return 0; }