Subversion Repositories HomeAutomation

Rev

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