/******************************************************************************* * libretroshare/src/pqi: pqiservice.cc * * * * libretroshare: retroshare core library * * * * Copyright 2004-2013 by Robert Fernie. * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * This program 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 Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public License * * along with this program. If not, see . * * * *******************************************************************************/ #include "pqi/pqiservice.h" #include "util/rsdebug.h" #include "util/rsstring.h" #ifdef SERVICE_DEBUG const int pqiservicezone = 60478; #endif /**** * #define SERVICE_DEBUG 1 ****/ void pqiService::setServiceServer(p3ServiceServerIface *server) { mServiceServer = server; } bool pqiService::send(RsRawItem *item) { return mServiceServer->sendItem(item); } p3ServiceServer::p3ServiceServer(pqiPublisher *pub, p3ServiceControl *ctrl) : mPublisher(pub), mServiceControl(ctrl), srvMtx("p3ServiceServer") { RS_STACK_MUTEX(srvMtx); /********* LOCKED *********/ #ifdef SERVICE_DEBUG pqioutput(PQL_DEBUG_BASIC, pqiservicezone, "p3ServiceServer::p3ServiceServer()"); #endif return; } int p3ServiceServer::addService(pqiService *ts, bool defaultOn) { RS_STACK_MUTEX(srvMtx); /********* LOCKED *********/ #ifdef SERVICE_DEBUG pqioutput(PQL_DEBUG_BASIC, pqiservicezone, "p3ServiceServer::addService()"); #endif RsServiceInfo info = ts->getServiceInfo(); std::map::iterator it; it = services.find(info.mServiceType); if (it != services.end()) { std::cerr << "p3ServiceServer::addService(): Service already added with id " << info.mServiceType << "!" << std::endl; // it exists already! return -1; } ts->setServiceServer(this); services[info.mServiceType] = ts; // This doesn't need to be in Mutex. mServiceControl->registerService(info,defaultOn); return 1; } bool p3ServiceServer::getServiceItemNames(uint32_t service_type,std::map& names) { RS_STACK_MUTEX(srvMtx); /********* LOCKED *********/ std::map::iterator it=services.find(service_type) ; if(it != services.end()) { it->second->getItemNames(names) ; return true ; } else return false ; } int p3ServiceServer::removeService(pqiService *ts) { RS_STACK_MUTEX(srvMtx); /********* LOCKED *********/ #ifdef SERVICE_DEBUG pqioutput(PQL_DEBUG_BASIC, pqiservicezone, "p3ServiceServer::removeService()"); #endif RsServiceInfo info = ts->getServiceInfo(); // This doesn't need to be in Mutex. mServiceControl->deregisterService(info.mServiceType); std::map::iterator it = services.find(info.mServiceType); if (it == services.end()) { std::cerr << "p3ServiceServer::removeService(): Service not found with id " << info.mServiceType << "!" << std::endl; return -1; } services.erase(it); return 1; } bool p3ServiceServer::recvItem(RsRawItem *item) { // Packet Filtering. // This doesn't need to be in Mutex. if (!mServiceControl->checkFilter(item->PacketId() & 0xffffff00, item->PeerId())) { delete item; return false; } pqiService *s = NULL; // access the service map under mutex lock { RS_STACK_MUTEX(srvMtx); auto it = services.find(item -> PacketId() & 0xffffff00); if (it == services.end()) { delete item; return false; } s = it->second; } // then call recv off mutex bool result = s->recv(item); return result; } bool p3ServiceServer::sendItem(RsRawItem *item) { #ifdef SERVICE_DEBUG std::cerr << "p3ServiceServer::sendItem()"; std::cerr << std::endl; item -> print(std::cerr); std::cerr << std::endl; #endif if (!item) { std::cerr << "p3ServiceServer::sendItem() Caught Null item"; std::cerr << std::endl; return false; } // Packet Filtering. if (!mServiceControl->checkFilter(item->PacketId() & 0xffffff00, item->PeerId())) { #ifdef SERVICE_DEBUG std::cerr << "p3ServiceServer::sendItem() Fails Filtering for packet id=" << std::hex << item->PacketId() << std::dec << ", and peer " << item->PeerId() << std::endl; #endif delete item; return false; } mPublisher->sendItem(item); return true; } int p3ServiceServer::tick() { mServiceControl->tick(); // make a copy of the service map std::map local_map; { RS_STACK_MUTEX(srvMtx); local_map=services; } // tick all services off mutex for(auto it(local_map.begin());it!=local_map.end();++it) { (it->second)->tick(); } return 1; }