Subversion Repositories HomeAutomation

Rev

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