Subversion Repositories HomeAutomation

Rev

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