Subversion Repositories HomeAutomation

Rev

Rev 1594 | Rev 1596 | 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
 
23
#include <boost/lexical_cast.hpp>
24
#include <boost/bind.hpp>
1594 runge 25
#include <boost/cast.hpp>
1592 runge 26
 
27
namespace atom {
28
namespace net {
1593 runge 29
 
1592 runge 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
 
1593 runge 62
void Manager::SlotOnNewState(ClientId client_id, ServerId server_id, ClientState client_state)
1592 runge 63
{
64
    if (client_state == CLIENT_STATE_DISCONNECTED)
65
    {
1595 runge 66
        this->mutex_clients_.lock();
1592 runge 67
        this->clients_.erase(client_id);
1595 runge 68
        this->mutex_clients_.unlock();
1592 runge 69
    }
70
    else if (client_state == CLIENT_STATE_ACCEPTED)
71
    {
1595 runge 72
        this->mutex_clients_.lock();
1592 runge 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
 
1593 runge 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_));
1592 runge 81
 
1594 runge 82
            client->Accept(boost::polymorphic_downcast<TcpClient*>(it->second.get())->ReleaseAcceptor());
1592 runge 83
 
84
            this->clients_[client->GetId()] = client;
85
 
1595 runge 86
            this->mutex_clients_.unlock();
87
 
1593 runge 88
            this->signal_on_new_state_(client_id, server_id, CLIENT_STATE_CONNECTED);
1592 runge 89
            return;
90
        }
91
        else
92
        {
1595 runge 93
            this->mutex_clients_.unlock();
1592 runge 94
            throw std::runtime_error("Accepted unknown client!");
95
        }
96
    }
97
 
1593 runge 98
    this->signal_on_new_state_(client_id, server_id, client_state);
1592 runge 99
}
100
 
1593 runge 101
void Manager::SlotOnNewData(ClientId client_id, ServerId server_id, Buffer data)
1592 runge 102
{
1593 runge 103
    this->signal_on_new_data_(client_id, server_id, data);
1592 runge 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
 
1595 runge 143
    this->mutex_clients_.lock();
144
 
1592 runge 145
    TcpClient::Pointer client = TcpClient::Pointer(new TcpClient(this->io_service_, this->GetFreeClientId(), this->GetFreeServerId()));
146
 
1593 runge 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_));
1592 runge 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
 
1595 runge 156
    this->mutex_clients_.unlock();
157
 
1592 runge 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
 
1595 runge 165
    this->mutex_clients_.lock();
166
 
1592 runge 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
        {
1595 runge 186
            this->mutex_clients_.unlock();
1592 runge 187
            throw std::runtime_error("Invalid protocol specified!");
188
            return 0;
189
        }
190
    }
191
 
1593 runge 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_));
1592 runge 194
 
195
    try
196
    {
197
        client->Connect(address, port_or_baud);
198
    }
199
    catch (std::exception e)
200
    {
1595 runge 201
        this->mutex_clients_.unlock();
1592 runge 202
        throw e;
203
    }
204
 
205
    this->clients_[client->GetId()] = client;
206
 
1595 runge 207
    this->mutex_clients_.unlock();
208
 
1592 runge 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
{
1595 runge 234
    this->mutex_clients_.lock();
235
 
1592 runge 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
    }
1595 runge 243
 
244
    this->mutex_clients_.unlock();
1592 runge 245
}
246
 
247
void Manager::SendToHandler(ClientId client_id, Buffer data)
248
{
1595 runge 249
    this->mutex_clients_.lock();
250
 
1592 runge 251
    ClientList::iterator it = this->clients_.find(client_id);
252
 
253
    if (it != this->clients_.end())
254
    {
255
        it->second->Send(data);
256
    }
1595 runge 257
 
258
    this->mutex_clients_.unlock();
1592 runge 259
}
260
 
261
void Manager::StopServerHandler(ServerId server_id)
262
{
1595 runge 263
    this->mutex_clients_.lock();
264
 
1592 runge 265
    for (ClientList::iterator it = this->clients_.begin(); it != this->clients_.end(); it++)
266
    {
267
        if (it->second->GetServerId() == server_id)
268
        {
1595 runge 269
            this->mutex_clients_.unlock();
1592 runge 270
            it->second->Disconnect();
1595 runge 271
            this->mutex_clients_.lock();
1592 runge 272
        }
273
    }
1595 runge 274
 
275
    this->mutex_clients_.unlock();
1592 runge 276
}
277
 
278
void Manager::DisconnectHandler(ClientId client_id)
279
{
1595 runge 280
    this->mutex_clients_.lock();
281
 
1592 runge 282
    ClientList::iterator it = this->clients_.find(client_id);
283
 
1595 runge 284
    this->mutex_clients_.unlock();
285
 
1592 runge 286
    if (it != this->clients_.end())
287
    {
288
        it->second->Disconnect();
289
    }
1595 runge 290
 
291
 
1592 runge 292
}
293
 
294
}; // namespace net
295
}; // namespace atom