28 #include <ibrcommon/net/vaddress.h>
29 #include <ibrcommon/Logger.h>
30 #include <ibrcommon/net/vsocket.h>
31 #include <ibrcommon/net/socketstream.h>
43 const std::string ApiServer::TAG =
"ApiServer";
46 :
_shutdown(false), _garbage_collector(*this)
48 _sockets.add(
new ibrcommon::fileserversocket(socketfile));
52 :
_shutdown(false), _garbage_collector(*this)
54 if (net.isLoopback()) {
55 if (ibrcommon::basesocket::hasSupport(AF_INET6)) {
56 ibrcommon::vaddress addr6(ibrcommon::vaddress::VADDR_LOCALHOST, port, AF_INET6);
57 _sockets.add(
new ibrcommon::tcpserversocket(addr6, 5));
60 ibrcommon::vaddress addr4(ibrcommon::vaddress::VADDR_LOCALHOST, port, AF_INET);
61 _sockets.add(
new ibrcommon::tcpserversocket(addr4, 5));
63 else if (net.isAny()) {
64 ibrcommon::vaddress addr(ibrcommon::vaddress::VADDR_ANY, port);
65 _sockets.add(
new ibrcommon::tcpserversocket(addr, 5));
69 std::list<ibrcommon::vaddress> addrs = net.getAddresses();
72 std::stringstream ss; ss << port;
74 for (std::list<ibrcommon::vaddress>::iterator iter = addrs.begin(); iter != addrs.end(); ++iter) {
75 ibrcommon::vaddress &addr = (*iter);
79 switch (addr.family()) {
82 addr.setService(ss.str());
83 _sockets.add(
new ibrcommon::tcpserversocket(addr, 5), net);
89 }
catch (
const ibrcommon::vaddress::address_exception &ex) {
90 IBRCOMMON_LOGGER_TAG(ApiServer::TAG, warning) << ex.what() << IBRCOMMON_LOGGER_ENDL;
98 _garbage_collector.stop();
99 _garbage_collector.join();
117 }
catch (
const ibrcommon::socket_exception &ex) {
118 IBRCOMMON_LOGGER_TAG(ApiServer::TAG, error) << ex.what() << IBRCOMMON_LOGGER_ENDL;
122 startGarbageCollector();
131 ibrcommon::socketset fds;
134 _sockets.select(&fds, NULL, NULL, NULL);
137 for (ibrcommon::socketset::iterator iter = fds.begin(); iter != fds.end(); ++iter)
141 ibrcommon::serversocket &sock =
dynamic_cast<ibrcommon::serversocket&
>(**iter);
144 ibrcommon::vaddress peeraddr;
147 ibrcommon::clientsocket *peersock = sock.accept(peeraddr);
153 if ( dynamic_cast<ibrcommon::tcpsocket*>(peersock) != NULL )
155 peersock->set(ibrcommon::clientsocket::NO_DELAY,
true);
162 ibrcommon::socketstream *conn =
new ibrcommon::socketstream(peersock);
176 IBRCOMMON_LOGGER_DEBUG_TAG(
"ApiServer", 5) <<
"new connected client at the extended API server" << IBRCOMMON_LOGGER_ENDL;
186 ibrcommon::MutexLock l1(_registration_lock);
190 _registrations.push_back(reg);
191 IBRCOMMON_LOGGER_DEBUG_TAG(
"ApiServer", 5) <<
"new registration " << reg->
getHandle() << IBRCOMMON_LOGGER_ENDL;
194 obj =
new ClientHandler(*
this, *_registrations.back(), conn);
199 ibrcommon::MutexLock l2(_connection_lock);
200 _connections.push_back(obj);
208 ibrcommon::Thread::yield();
210 }
catch (
const std::exception&) {
227 _garbage_collector.pause();
231 ibrcommon::MutexLock l(_connection_lock);
234 for (client_list::iterator iter = _connections.begin(); iter != _connections.end(); ++iter)
241 while (_connections.size() > 0) ibrcommon::Thread::sleep(1000);
246 ibrcommon::MutexLock l(_registration_lock);
247 for (registration_list::iterator iter = _registrations.begin(); iter != _registrations.end(); ++iter)
267 ibrcommon::MutexLock l(_registration_lock);
270 for (registration_list::iterator iter = _registrations.begin(); iter != _registrations.end();)
278 IBRCOMMON_LOGGER_DEBUG_TAG(
"ApiServer", 5) <<
"release registration " << reg->
getHandle() << IBRCOMMON_LOGGER_ENDL;
279 _registrations.erase(iter++);
295 return nextRegistrationExpiry();
306 IBRCOMMON_LOGGER_DEBUG_TAG(
"ApiServer", 5) <<
"api connection up" << IBRCOMMON_LOGGER_ENDL;
312 IBRCOMMON_LOGGER_DEBUG_TAG(
"ApiServer", 5) <<
"api connection down" << IBRCOMMON_LOGGER_ENDL;
314 ibrcommon::MutexLock l(_connection_lock);
317 for (client_list::iterator iter = _connections.begin(); iter != _connections.end(); ++iter)
321 _connections.erase(iter);
332 startGarbageCollector();
336 ibrcommon::MutexLock l(_registration_lock);
338 for (registration_list::iterator iter = _registrations.begin(); iter != _registrations.end(); ++iter)
344 IBRCOMMON_LOGGER_DEBUG_TAG(
"ApiServer", 5) <<
"release registration " << reg.
getHandle() << IBRCOMMON_LOGGER_ENDL;
345 _registrations.erase(iter);
356 if (queued.bundle.isFragment())
return;
358 ibrcommon::MutexLock l(_connection_lock);
359 for (client_list::iterator iter = _connections.begin(); iter != _connections.end(); ++iter)
369 void ApiServer::startGarbageCollector()
374 size_t timeout = nextRegistrationExpiry();
375 _garbage_collector.set(timeout);
378 if(!_garbage_collector.isRunning())
379 _garbage_collector.start();
381 catch(
const ibrcommon::Timer::StopTimerException &ex)
386 size_t ApiServer::nextRegistrationExpiry()
388 ibrcommon::MutexLock l(_registration_lock);
389 bool persistentFound =
false;
390 size_t new_timeout = 0;
391 size_t current_time = ibrcommon::Timer::get_current_time();
394 for (registration_list::iterator iter = _registrations.begin(); iter != _registrations.end(); ++iter)
398 Registration ® = (**iter);
401 if(!reg.isPersistent()){
405 persistentFound =
true;
410 size_t expire_time = reg.getExpireTime();
413 size_t expire_timeout = expire_time - current_time;
419 persistentFound =
true;
420 new_timeout = expire_timeout;
422 else if(expire_timeout < new_timeout)
424 new_timeout = expire_timeout;
428 catch(
const Registration::AlreadyAttachedException &ex)
433 if(!persistentFound)
throw ibrcommon::Timer::StopTimerException();
static Configuration & getInstance(bool reset=false)
virtual void connectionUp(ClientHandler *conn)
virtual const std::string getName() const
virtual void connectionDown(ClientHandler *conn)
static void add(EventReceiver< E > *receiver)
const std::string & getHandle() const
virtual size_t timeout(ibrcommon::Timer *)
static void remove(const EventReceiver< E > *receiver)
ApiServer(const ibrcommon::File &socket)
bool hasSubscribed(const dtn::data::EID &endpoint)
Registration & getRegistration()
void notify(const NOTIFY_CALL)
std::string version() const
void raiseEvent(const dtn::routing::QueueBundleEvent &evt)
Registration & getRegistration(const std::string &handle)
void freeRegistration(Registration ®)