Subversion Repositories HomeAutomation

Rev

Rev 1595 | Rev 1597 | 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
 
1592 runge 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
 
1593 runge 64
void Manager::SlotOnNewState(ClientId client_id, ServerId server_id, ClientState client_state)
1592 runge 65
{
66
    if (client_state == CLIENT_STATE_DISCONNECTED)
67
    {
1595 runge 68
        this->mutex_clients_.lock();
1592 runge 69
        this->clients_.erase(client_id);
1595 runge 70
        this->mutex_clients_.unlock();
1592 runge 71
    }
72
    else if (client_state == CLIENT_STATE_ACCEPTED)
73
    {
1595 runge 74
        this->mutex_clients_.lock();
1592 runge 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
 
1593 runge 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_));
1592 runge 83
 
1594 runge 84
            client->Accept(boost::polymorphic_downcast<TcpClient*>(it->second.get())->ReleaseAcceptor());
1592 runge 85
 
86
            this->clients_[client->GetId()] = client;
87
 
1595 runge 88
            this->mutex_clients_.unlock();
89
 
1593 runge 90
            this->signal_on_new_state_(client_id, server_id, CLIENT_STATE_CONNECTED);
1592 runge 91
            return;
92
        }
93
        else
94
        {
1595 runge 95
            this->mutex_clients_.unlock();
1592 runge 96
            throw std::runtime_error("Accepted unknown client!");
97
        }
98
    }
99
 
1593 runge 100
    this->signal_on_new_state_(client_id, server_id, client_state);
1592 runge 101
}
102
 
1596 runge 103
void Manager::SlotOnNewData(ClientId client_id, ServerId server_id, type::Byteset data)
1592 runge 104
{
1593 runge 105
    this->signal_on_new_data_(client_id, server_id, data);
1592 runge 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
 
1596 runge 122
    return server_id;
1592 runge 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
 
1595 runge 145
    this->mutex_clients_.lock();
146
 
1592 runge 147
    TcpClient::Pointer client = TcpClient::Pointer(new TcpClient(this->io_service_, this->GetFreeClientId(), this->GetFreeServerId()));
148
 
1593 runge 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_));
1592 runge 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
 
1595 runge 158
    this->mutex_clients_.unlock();
159
 
1592 runge 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
 
1595 runge 167
    this->mutex_clients_.lock();
168
 
1592 runge 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
        {
1595 runge 188
            this->mutex_clients_.unlock();
1592 runge 189
            throw std::runtime_error("Invalid protocol specified!");
190
            return 0;
191
        }
192
    }
193
 
1593 runge 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_));
1592 runge 196
 
197
    try
198
    {
199
        client->Connect(address, port_or_baud);
200
    }
201
    catch (std::exception e)
202
    {
1595 runge 203
        this->mutex_clients_.unlock();
1592 runge 204
        throw e;
205
    }
206
 
207
    this->clients_[client->GetId()] = client;
208
 
1595 runge 209
    this->mutex_clients_.unlock();
210
 
1592 runge 211
    return client->GetId();
212
}
213
 
1596 runge 214
void Manager::SendToAll(ServerId server_id, type::Byteset data)
1592 runge 215
{
216
    this->io_service_.post(boost::bind(&Manager::SendToAllHandler, this, server_id, data));
217
}
218
 
1596 runge 219
void Manager::SendTo(ClientId client_id, type::Byteset data)
1592 runge 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
 
1596 runge 234
void Manager::SendToAllHandler(ServerId server_id, type::Byteset data)
1592 runge 235
{
1595 runge 236
    this->mutex_clients_.lock();
237
 
1592 runge 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
    }
1595 runge 245
 
246
    this->mutex_clients_.unlock();
1592 runge 247
}
248
 
1596 runge 249
void Manager::SendToHandler(ClientId client_id, type::Byteset data)
1592 runge 250
{
1595 runge 251
    this->mutex_clients_.lock();
252
 
1592 runge 253
    ClientList::iterator it = this->clients_.find(client_id);
254
 
255
    if (it != this->clients_.end())
256
    {
257
        it->second->Send(data);
258
    }
1595 runge 259
 
260
    this->mutex_clients_.unlock();
1592 runge 261
}
262
 
263
void Manager::StopServerHandler(ServerId server_id)
264
{
1595 runge 265
    this->mutex_clients_.lock();
266
 
1592 runge 267
    for (ClientList::iterator it = this->clients_.begin(); it != this->clients_.end(); it++)
268
    {
269
        if (it->second->GetServerId() == server_id)
270
        {
1595 runge 271
            this->mutex_clients_.unlock();
1592 runge 272
            it->second->Disconnect();
1595 runge 273
            this->mutex_clients_.lock();
1592 runge 274
        }
275
    }
1595 runge 276
 
277
    this->mutex_clients_.unlock();
1592 runge 278
}
279
 
280
void Manager::DisconnectHandler(ClientId client_id)
281
{
1595 runge 282
    this->mutex_clients_.lock();
283
 
1592 runge 284
    ClientList::iterator it = this->clients_.find(client_id);
285
 
1595 runge 286
    this->mutex_clients_.unlock();
287
 
1592 runge 288
    if (it != this->clients_.end())
289
    {
290
        it->second->Disconnect();
291
    }
1595 runge 292
 
293
 
1592 runge 294
}
295
 
296
}; // namespace net
297
}; // namespace atom