Subversion Repositories HomeAutomation

Rev

Rev 1601 | Rev 1627 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /*
  2.  *
  3.  *  Copyright (C) 2010  Mattias Runge
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License along
  16.  *  with this program; if not, write to the Free Software Foundation, Inc.,
  17.  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18.  *
  19.  */
  20.  
  21. #include "Manager.h"
  22.  
  23. #include <iostream>
  24.  
  25. #include <boost/lexical_cast.hpp>
  26. #include <boost/bind.hpp>
  27. #include <boost/cast.hpp>
  28.  
  29. namespace atom {
  30. namespace net {
  31.  
  32. Manager::Pointer Manager::instance_;
  33.    
  34. Manager::Manager()
  35. {
  36. }
  37.  
  38. Manager::~Manager()
  39. {
  40.     this->clients_.clear();
  41. }
  42.  
  43. Manager::Pointer Manager::Instance()
  44. {
  45.     return Manager::instance_;
  46. }
  47.  
  48. void Manager::Create()
  49. {
  50.     Manager::instance_ = Manager::Pointer(new Manager());
  51. }
  52.  
  53. void Manager::Delete()
  54. {
  55.     Manager::instance_.reset();
  56. }
  57.  
  58. void Manager::ConnectSlots(const SignalOnNewState::slot_type& slot_on_new_state, const SignalOnNewData::slot_type& slot_on_new_data)
  59. {
  60.     this->signal_on_new_state_.connect(slot_on_new_state);
  61.     this->signal_on_new_data_.connect(slot_on_new_data);
  62. }
  63.  
  64. void Manager::SlotOnNewState(ClientId client_id, ServerId server_id, ClientState client_state)
  65. {
  66.     if (client_state == CLIENT_STATE_DISCONNECTED)
  67.     {
  68.         this->clients_.erase(client_id);
  69.     }
  70.     else if (client_state == CLIENT_STATE_ACCEPTED)
  71.     {
  72.         ClientList::iterator it = this->clients_.find(client_id);
  73.        
  74.         if (it != this->clients_.end())
  75.         {
  76.             TcpClient::Pointer client = TcpClient::Pointer(new TcpClient(this->io_service_, this->GetFreeClientId(), it->second->GetServerId()));
  77.            
  78.             client->ConnectSlots(Client::SignalOnNewState::slot_type(&Manager::SlotOnNewState, this, _1, _2, _3).track(Manager::instance_),
  79.                                  Client::SignalOnNewData::slot_type(&Manager::SlotOnNewData, this, _1, _2, _3).track(Manager::instance_));
  80.            
  81.             client->Accept(boost::polymorphic_downcast<TcpClient*>(it->second.get())->ReleaseAcceptor());
  82.            
  83.             this->clients_[client->GetId()] = client;
  84.            
  85.             this->signal_on_new_state_(client_id, server_id, CLIENT_STATE_CONNECTED);
  86.             return;
  87.         }
  88.         else
  89.         {
  90.             throw std::runtime_error("Accepted unknown client!");
  91.         }
  92.     }
  93.    
  94.     this->signal_on_new_state_(client_id, server_id, client_state);
  95. }
  96.  
  97. void Manager::SlotOnNewData(ClientId client_id, ServerId server_id, type::Byteset data)
  98. {
  99.     this->signal_on_new_data_(client_id, server_id, data);
  100. }
  101.  
  102. ServerId Manager::GetFreeServerId()
  103. {
  104.     ServerId server_id = 1;
  105.    
  106.     for (ClientList::iterator it = this->clients_.begin(); it != this->clients_.end(); it++)
  107.     {
  108.         if (it->second->GetServerId() != server_id)
  109.         {
  110.             return server_id;
  111.         }
  112.        
  113.         server_id++;
  114.     }
  115.    
  116.     return server_id;
  117. }
  118.  
  119. ClientId Manager::GetFreeClientId()
  120. {
  121.     ClientId client_id = 1;
  122.    
  123.     while (this->clients_.find(client_id) != this->clients_.end())
  124.     {
  125.         client_id++;
  126.     }
  127.    
  128.     return client_id;
  129. }
  130.  
  131. ServerId Manager::StartServer(Protocol protocol, unsigned int port)
  132. {
  133.     if (protocol != PROTOCOL_TCP)
  134.     {
  135.         throw std::runtime_error("Can not start server for the Serial or UDP protocol!");
  136.         return 0;
  137.     }
  138.    
  139.     TcpClient::Pointer client = TcpClient::Pointer(new TcpClient(this->io_service_, this->GetFreeClientId(), this->GetFreeServerId()));
  140.    
  141.     client->ConnectSlots(Client::SignalOnNewState::slot_type(&Manager::SlotOnNewState, this, _1, _2, _3).track(Manager::instance_),
  142.                          Client::SignalOnNewData::slot_type(&Manager::SlotOnNewData, this, _1, _2, _3).track(Manager::instance_));
  143.    
  144.     TcpClient::AcceptorPointer acceptor = TcpClient::AcceptorPointer(new boost::asio::ip::tcp::acceptor(this->io_service_, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)));    
  145.  
  146.     client->Accept(acceptor);
  147.    
  148.     this->clients_[client->GetId()] = client;
  149.    
  150.     return client->GetServerId();
  151. }
  152.  
  153. ClientId Manager::Connect(Protocol protocol, std::string address, unsigned int port_or_baud)
  154. {
  155.     Client::Pointer client;
  156.    
  157.     switch (protocol)
  158.     {
  159.         case PROTOCOL_TCP:
  160.         {
  161.             client = Client::Pointer(new TcpClient(this->io_service_, this->GetFreeClientId(), 0));
  162.             break;
  163.         }
  164.         case PROTOCOL_UDP:
  165.         {
  166.             client = Client::Pointer(new UdpClient(this->io_service_, this->GetFreeClientId(), 0));
  167.             break;
  168.         }
  169.         case PROTOCOL_SERIAL:
  170.         {
  171.             client = Client::Pointer(new SerialClient(this->io_service_, this->GetFreeClientId(), 0));
  172.             break;
  173.         }
  174.         default:
  175.         {
  176.             throw std::runtime_error("Invalid protocol specified!");
  177.             return 0;
  178.         }
  179.     }
  180.    
  181.     client->ConnectSlots(Client::SignalOnNewState::slot_type(&Manager::SlotOnNewState, this, _1, _2, _3).track(Manager::instance_),
  182.                          Client::SignalOnNewData::slot_type(&Manager::SlotOnNewData, this, _1, _2, _3).track(Manager::instance_));
  183.    
  184.     client->Connect(address, port_or_baud);
  185.    
  186.     this->clients_[client->GetId()] = client;
  187.    
  188.     return client->GetId();
  189. }
  190.  
  191. void Manager::SendToAll(ServerId server_id, type::Byteset data)
  192. {
  193.     this->io_service_.post(boost::bind(&Manager::SendToAllHandler, this, server_id, data));
  194. }
  195.  
  196. void Manager::SendTo(ClientId client_id, type::Byteset data)
  197. {
  198.     this->io_service_.post(boost::bind(&Manager::SendToHandler, this, client_id, data));
  199. }
  200.  
  201. void Manager::StopServer(ServerId server_id)
  202. {
  203.     this->io_service_.post(boost::bind(&Manager::StopServerHandler, this, server_id));
  204. }
  205.  
  206. void Manager::Disconnect(ClientId client_id)
  207. {
  208.     this->io_service_.post(boost::bind(&Manager::DisconnectHandler, this, client_id));
  209. }
  210.  
  211. void Manager::SendToAllHandler(ServerId server_id, type::Byteset data)
  212. {
  213.     for (ClientList::iterator it = this->clients_.begin(); it != this->clients_.end(); it++)
  214.     {
  215.         if (it->second->GetServerId() == server_id)
  216.         {
  217.             it->second->Send(data);
  218.         }
  219.     }
  220. }
  221.  
  222. void Manager::SendToHandler(ClientId client_id, type::Byteset data)
  223. {
  224.     ClientList::iterator it = this->clients_.find(client_id);
  225.  
  226.     if (it != this->clients_.end())
  227.     {
  228.         it->second->Send(data);
  229.     }
  230. }
  231.  
  232. void Manager::StopServerHandler(ServerId server_id)
  233. {
  234.     for (ClientList::iterator it = this->clients_.begin(); it != this->clients_.end(); it++)
  235.     {
  236.         if (it->second->GetServerId() == server_id)
  237.         {
  238.             it->second->Stop();
  239.         }
  240.     }
  241. }
  242.  
  243. void Manager::DisconnectHandler(ClientId client_id)
  244. {
  245.     ClientList::iterator it = this->clients_.find(client_id);
  246.    
  247.     if (it != this->clients_.end())
  248.     {
  249.         it->second->Disconnect();
  250.     }
  251. }
  252.  
  253. }; // namespace net
  254. }; // namespace atom
  255.