Subversion Repositories HomeAutomation

Rev

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