Subversion Repositories HomeAutomation

Rev

Rev 1597 | Rev 1601 | 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() : io_service_work_(io_service_)
  35. {
  36.     boost::thread thread(boost::bind(&boost::asio::io_service::run, &this->io_service_));
  37.     this->thread_ = thread.move();
  38. }
  39.  
  40. Manager::~Manager()
  41. {
  42.     this->clients_.clear();
  43.    
  44.     this->io_service_.stop();
  45.    
  46.     this->thread_.interrupt();
  47.     this->thread_.join();
  48. }
  49.  
  50. Manager::Pointer Manager::Instance()
  51. {
  52.     return Manager::instance_;
  53. }
  54.  
  55. void Manager::Create()
  56. {
  57.     Manager::instance_ = Manager::Pointer(new Manager());
  58. }
  59.  
  60. void Manager::Delete()
  61. {
  62.     Manager::instance_.reset();
  63. }
  64.  
  65. void Manager::ConnectSlots(const SignalOnNewState::slot_type& slot_on_new_state, const SignalOnNewData::slot_type& slot_on_new_data)
  66. {
  67.     this->signal_on_new_state_.connect(slot_on_new_state);
  68.     this->signal_on_new_data_.connect(slot_on_new_data);
  69. }
  70.  
  71. void Manager::SlotOnNewState(ClientId client_id, ServerId server_id, ClientState client_state)
  72. {
  73.     if (client_state == CLIENT_STATE_DISCONNECTED)
  74.     {
  75.         this->clients_.erase(client_id);
  76.     }
  77.     else if (client_state == CLIENT_STATE_ACCEPTED)
  78.     {
  79.         ClientList::iterator it = this->clients_.find(client_id);
  80.        
  81.         if (it != this->clients_.end())
  82.         {
  83.             TcpClient::Pointer client = TcpClient::Pointer(new TcpClient(this->io_service_, this->GetFreeClientId(), it->second->GetServerId()));
  84.            
  85.             client->ConnectSlots(Client::SignalOnNewState::slot_type(&Manager::SlotOnNewState, this, _1, _2, _3).track(Manager::instance_),
  86.                                  Client::SignalOnNewData::slot_type(&Manager::SlotOnNewData, this, _1, _2, _3).track(Manager::instance_));
  87.            
  88.             client->Accept(boost::polymorphic_downcast<TcpClient*>(it->second.get())->ReleaseAcceptor());
  89.            
  90.             this->clients_[client->GetId()] = client;
  91.            
  92.             this->signal_on_new_state_(client_id, server_id, CLIENT_STATE_CONNECTED);
  93.             return;
  94.         }
  95.         else
  96.         {
  97.             throw std::runtime_error("Accepted unknown client!");
  98.         }
  99.     }
  100.    
  101.     this->signal_on_new_state_(client_id, server_id, client_state);
  102. }
  103.  
  104. void Manager::SlotOnNewData(ClientId client_id, ServerId server_id, type::Byteset data)
  105. {
  106.     this->signal_on_new_data_(client_id, server_id, data);
  107. }
  108.  
  109. ServerId Manager::GetFreeServerId()
  110. {
  111.     ServerId server_id = 1;
  112.    
  113.     for (ClientList::iterator it = this->clients_.begin(); it != this->clients_.end(); it++)
  114.     {
  115.         if (it->second->GetServerId() != server_id)
  116.         {
  117.             return server_id;
  118.         }
  119.        
  120.         server_id++;
  121.     }
  122.    
  123.     return server_id;
  124. }
  125.  
  126. ClientId Manager::GetFreeClientId()
  127. {
  128.     ClientId client_id = 1;
  129.    
  130.     while (this->clients_.find(client_id) != this->clients_.end())
  131.     {
  132.         client_id++;
  133.     }
  134.    
  135.     return client_id;
  136. }
  137.  
  138. ServerId Manager::StartServer(Protocol protocol, unsigned int port)
  139. {
  140.     if (protocol != PROTOCOL_TCP)
  141.     {
  142.         throw std::runtime_error("Can not start server for the Serial or UDP protocol!");
  143.         return 0;
  144.     }
  145.    
  146.     TcpClient::Pointer client = TcpClient::Pointer(new TcpClient(this->io_service_, this->GetFreeClientId(), this->GetFreeServerId()));
  147.    
  148.     client->ConnectSlots(Client::SignalOnNewState::slot_type(&Manager::SlotOnNewState, this, _1, _2, _3).track(Manager::instance_),
  149.                          Client::SignalOnNewData::slot_type(&Manager::SlotOnNewData, this, _1, _2, _3).track(Manager::instance_));
  150.    
  151.     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)));    
  152.  
  153.     client->Accept(acceptor);
  154.    
  155.     this->clients_[client->GetId()] = client;
  156.    
  157.     return client->GetServerId();
  158. }
  159.  
  160. ClientId Manager::Connect(Protocol protocol, std::string address, unsigned int port_or_baud)
  161. {
  162.     Client::Pointer client;
  163.    
  164.     switch (protocol)
  165.     {
  166.         case PROTOCOL_TCP:
  167.         {
  168.             client = Client::Pointer(new TcpClient(this->io_service_, this->GetFreeClientId(), 0));
  169.             break;
  170.         }
  171.         case PROTOCOL_UDP:
  172.         {
  173.             client = Client::Pointer(new UdpClient(this->io_service_, this->GetFreeClientId(), 0));
  174.             break;
  175.         }
  176.         case PROTOCOL_SERIAL:
  177.         {
  178.             client = Client::Pointer(new SerialClient(this->io_service_, this->GetFreeClientId(), 0));
  179.             break;
  180.         }
  181.         default:
  182.         {
  183.             throw std::runtime_error("Invalid protocol specified!");
  184.             return 0;
  185.         }
  186.     }
  187.    
  188.     client->ConnectSlots(Client::SignalOnNewState::slot_type(&Manager::SlotOnNewState, this, _1, _2, _3).track(Manager::instance_),
  189.                          Client::SignalOnNewData::slot_type(&Manager::SlotOnNewData, this, _1, _2, _3).track(Manager::instance_));
  190.    
  191.     try
  192.     {
  193.         client->Connect(address, port_or_baud);
  194.     }
  195.     catch (std::exception& e)
  196.     {
  197.         throw std::runtime_error(e.what());
  198.     }
  199.    
  200.     this->clients_[client->GetId()] = client;
  201.    
  202.     return client->GetId();
  203. }
  204.  
  205. void Manager::SendToAll(ServerId server_id, type::Byteset data)
  206. {
  207.     this->io_service_.post(boost::bind(&Manager::SendToAllHandler, this, server_id, data));
  208. }
  209.  
  210. void Manager::SendTo(ClientId client_id, type::Byteset data)
  211. {
  212.     this->io_service_.post(boost::bind(&Manager::SendToHandler, this, client_id, data));
  213. }
  214.  
  215. void Manager::StopServer(ServerId server_id)
  216. {
  217.     this->io_service_.post(boost::bind(&Manager::StopServerHandler, this, server_id));
  218. }
  219.  
  220. void Manager::Disconnect(ClientId client_id)
  221. {
  222.     this->io_service_.post(boost::bind(&Manager::DisconnectHandler, this, client_id));
  223. }
  224.  
  225. void Manager::SendToAllHandler(ServerId server_id, type::Byteset data)
  226. {
  227.     for (ClientList::iterator it = this->clients_.begin(); it != this->clients_.end(); it++)
  228.     {
  229.         if (it->second->GetServerId() == server_id)
  230.         {
  231.             it->second->Send(data);
  232.         }
  233.     }
  234. }
  235.  
  236. void Manager::SendToHandler(ClientId client_id, type::Byteset data)
  237. {
  238.     ClientList::iterator it = this->clients_.find(client_id);
  239.  
  240.     if (it != this->clients_.end())
  241.     {
  242.         it->second->Send(data);
  243.     }
  244. }
  245.  
  246. void Manager::StopServerHandler(ServerId server_id)
  247. {
  248.     for (ClientList::iterator it = this->clients_.begin(); it != this->clients_.end(); it++)
  249.     {
  250.         if (it->second->GetServerId() == server_id)
  251.         {
  252.             it->second->Stop();
  253.         }
  254.     }
  255. }
  256.  
  257. void Manager::DisconnectHandler(ClientId client_id)
  258. {
  259.     ClientList::iterator it = this->clients_.find(client_id);
  260.    
  261.     if (it != this->clients_.end())
  262.     {
  263.         it->second->Disconnect();
  264.     }
  265. }
  266.  
  267. }; // namespace net
  268. }; // namespace atom
  269.