BlinkenArea - GitList
Repositories
Blog
Wiki
Blinker
Code
Commits
Branches
Tags
Search
Tree:
46a7c7b
Branches
Tags
master
Blinker
src
noarch
Phone_impl.h
begin of phone connector
Stefan Schuermans
commited
46a7c7b
at 2011-12-22 14:11:23
Phone_impl.h
Blame
History
Raw
/* Blinker Copyright 2011 Stefan Schuermans <stefan@blinkenarea.org> Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html a blinkenarea.org project */ #ifndef BLINKER_PHONE_IMPL_H #define BLINKER_PHONE_IMPL_H #include <string> #include "Directory.h" #include "File.h" #include "IoCallee.h" #include "Mgrs.h" #include "Module.h" #include "Phone.h" #include "SettingFile.h" #include "Time.h" #include "TimeCallee.h" namespace Blinker { /** * @brief constructor * @param[in] mgrs managers * @param[in] dirBase base directory */ template<typename ADDR, typename SOCK> Phone<ADDR, SOCK>::Phone(Mgrs &mgrs, const Directory &dirBase): Module(mgrs, dirBase), m_fileBind(dirBase.getFile("bind")), m_fileServer(dirBase.getFile("server")), m_pSock(NULL) { // read server address readServer(); // create and bind socket createSock(); } /// virtual destructor template<typename ADDR, typename SOCK> Phone<ADDR, SOCK>::~Phone() { // destroy socket destroySock(); // cancel time callback m_mgrs.m_callMgr.cancelTimeCall(this); } /// check for update of configuration template<typename ADDR, typename SOCK> void Phone<ADDR, SOCK>::updateConfig() { // bind address file was modified -> re-create socket if (m_fileBind.checkModified()) { destroySock(); createSock(); } // server address file was modified -> re-read server address if (m_fileServer.checkModified()) readServer(); } /// callback when requested time reached template<typename ADDR, typename SOCK> void Phone<ADDR, SOCK>::timeCall() { Time now = Time::now(); // server timeout -> re-register if (m_timeRegister <= now) sendRegister(); // send heartbeat if (m_timeHeartbeat <= now) sendHeartbeat(); } /** * @brief callback when I/O object is readable * @param[in] io I/O object that is readable */ template<typename ADDR, typename SOCK> void Phone<ADDR, SOCK>::ioReadCall(Io *io) { // reception on socket if (io == m_pSock) receiveFromSock(); } /** * @brief callback when I/O object is writable * @param[in] io I/O object that is writable */ template<typename ADDR, typename SOCK> void Phone<ADDR, SOCK>::ioWriteCall(Io *io) { (void)io; // unused } /// (re-)read server address template<typename ADDR, typename SOCK> void Phone<ADDR, SOCK>::readServer() { m_fileServer.update(); // register with new server sendRegister(); } /// create socket and bind it template<typename ADDR, typename SOCK> void Phone<ADDR, SOCK>::createSock() { // create socket if (!m_pSock) { m_pSock = new SOCK(); if (!m_pSock) return; } // get bind address from bind address setting file m_fileBind.update(); if (!m_fileBind.m_valid) { delete m_pSock; m_pSock = NULL; return; } // bind socket if (!m_pSock->bind(m_fileBind.m_obj)) { delete m_pSock; m_pSock = NULL; return; } // request callback on recepetion m_mgrs.m_callMgr.requestIoReadCall(this, m_pSock); // register with server sendRegister(); } /// destroy socket template<typename ADDR, typename SOCK> void Phone<ADDR, SOCK>::destroySock() { // cancel callback request m_mgrs.m_callMgr.cancelIoReadCall(this, m_pSock); // destroy socket if (m_pSock) { delete m_pSock; m_pSock = NULL; } } /// register with server template<typename ADDR, typename SOCK> void Phone<ADDR, SOCK>::sendRegister() { send("0:register"); // set time for next register message and next heartbeat m_timeRegister = Time::now() + m_serverTimeout; m_timeHeartbeat = m_timeRegister + m_heartbeatInterval; updateTimeCallback(); } /// send heartbeat to server template<typename ADDR, typename SOCK> void Phone<ADDR, SOCK>::sendHeartbeat() { send("0:heartbeat"); // set time for next heartbeat m_timeHeartbeat = Time::now() + m_heartbeatInterval; updateTimeCallback(); } /** * @brief send message to server * @param[in] msg message to send */ template<typename ADDR, typename SOCK> void Phone<ADDR, SOCK>::send(const std::string &msg) { // check that there is a socket and a server address if (!m_pSock || !m_fileServer.m_valid) return; // send message m_pSock->send(msg, m_fileServer.m_obj); } /// receive data from socket template<typename ADDR, typename SOCK> void Phone<ADDR, SOCK>::receiveFromSock() { std::string msg; ADDR addr; // make sure socket exists if (!m_pSock) return; // receive (leave if no reception) if (!m_pSock->recv(msg, addr)) return; // check that packet came from server address if (!m_fileServer.m_valid || addr != m_fileServer.m_obj) return; // mismatch // reset server timeout m_timeRegister = Time::now() + m_serverTimeout; updateTimeCallback(); // TODO } /// update time callback template<typename ADDR, typename SOCK> void Phone<ADDR, SOCK>::updateTimeCallback() { m_mgrs.m_callMgr.requestTimeCall(this, m_timeRegister < m_timeHeartbeat ? m_timeRegister : m_timeHeartbeat); } template<typename ADDR, typename SOCK> const Time Phone<ADDR, SOCK>::m_serverTimeout(5); template<typename ADDR, typename SOCK> const Time Phone<ADDR, SOCK>::m_heartbeatInterval(20); } // namespace Blinker #endif // #ifndef BLINKER_PHONE_IMPL_H