Subversion Repositories HomeAutomation

Rev

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

Rev Author Line No. Line
1592 runge 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
 
1596 runge 23
#include <iostream>
24
 
1592 runge 25
#include <boost/lexical_cast.hpp>
26
#include <boost/bind.hpp>
1594 runge 27
#include <boost/cast.hpp>
1592 runge 28
 
29
namespace atom {
30
namespace net {
1593 runge 31
 
1599 runge 32
Manager::Pointer Manager::instance_;
1592 runge 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
 
1599 runge 44
    this->io_service_.stop();
45
 
1592 runge 46
    this->thread_.interrupt();
47
    this->thread_.join();
48
}
49
 
50
Manager::Pointer Manager::Instance()
51
{
52
    return Manager::instance_;
53
}
54
 
1599 runge 55
void Manager::Create()
56
{
57
    Manager::instance_ = Manager::Pointer(new Manager());
58
}
59
 
1592 runge 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
 
1593 runge 71
void Manager::SlotOnNewState(ClientId client_id, ServerId server_id, ClientState client_state)
1592 runge 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
 
1593 runge 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_));
1592 runge 87
 
1594 runge 88
            client->Accept(boost::polymorphic_downcast<TcpClient*>(it->second.get())->ReleaseAcceptor());
1592 runge 89
 
90
            this->clients_[client->GetId()] = client;
91
 
1593 runge 92
            this->signal_on_new_state_(client_id, server_id, CLIENT_STATE_CONNECTED);
1592 runge 93
            return;
94
        }
95
        else
96
        {
97
            throw std::runtime_error("Accepted unknown client!");
98
        }
99
    }
100
 
1593 runge 101
    this->signal_on_new_state_(client_id, server_id, client_state);
1592 runge 102
}
103
 
1596 runge 104
void Manager::SlotOnNewData(ClientId client_id, ServerId server_id, type::Byteset data)
1592 runge 105
{
1593 runge 106
    this->signal_on_new_data_(client_id, server_id, data);
1592 runge 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
 
1596 runge 123
    return server_id;
1592 runge 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
 
1593 runge 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_));
1592 runge 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
 
1593 runge 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_));
1592 runge 190
 
191
    try
192
    {
193
        client->Connect(address, port_or_baud);
194
    }
1597 runge 195
    catch (std::exception& e)
1592 runge 196
    {
1597 runge 197
        throw std::runtime_error(e.what());
1592 runge 198
    }
199
 
200
    this->clients_[client->GetId()] = client;
201
 
202
    return client->GetId();
203
}
204
 
1596 runge 205
void Manager::SendToAll(ServerId server_id, type::Byteset data)
1592 runge 206
{
207
    this->io_service_.post(boost::bind(&Manager::SendToAllHandler, this, server_id, data));
208
}
209
 
1596 runge 210
void Manager::SendTo(ClientId client_id, type::Byteset data)
1592 runge 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
 
1596 runge 225
void Manager::SendToAllHandler(ServerId server_id, type::Byteset data)
1592 runge 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
 
1596 runge 236
void Manager::SendToHandler(ClientId client_id, type::Byteset data)
1592 runge 237
{
238
    ClientList::iterator it = this->clients_.find(client_id);
1599 runge 239
 
1592 runge 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
        {
1599 runge 252
            it->second->Stop();
1592 runge 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