Subversion Repositories HomeAutomation

Rev

Rev 1593 | Rev 1595 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

Rev 1593 Rev 1594
1
/*
1
/*
2
 *
2
 *
3
 *  Copyright (C) 2010  Mattias Runge
3
 *  Copyright (C) 2010  Mattias Runge
4
 *
4
 *
5
 *  This program is free software; you can redistribute it and/or modify
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
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
7
 *  the Free Software Foundation; either version 2 of the License, or
8
 *  (at your option) any later version.
8
 *  (at your option) any later version.
9
 *
9
 *
10
 *  This program is distributed in the hope that it will be useful,
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
13
 *  GNU General Public License for more details.
14
 *
14
 *
15
 *  You should have received a copy of the GNU General Public License along
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.,
16
 *  with this program; if not, write to the Free Software Foundation, Inc.,
17
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
 *
18
 *
19
 */
19
 */
20
 
20
 
21
#include "Manager.h"
21
#include "Manager.h"
22
 
-
 
23
#include <iostream>
-
 
24
 
22
 
25
#include <boost/lexical_cast.hpp>
23
#include <boost/lexical_cast.hpp>
26
#include <boost/bind.hpp>
24
#include <boost/bind.hpp>
-
 
25
#include <boost/cast.hpp>
27
 
26
 
28
namespace atom {
27
namespace atom {
29
namespace net {
28
namespace net {
30
 
29
 
31
Manager::Pointer Manager::instance_ = Manager::Pointer(new Manager());
30
Manager::Pointer Manager::instance_ = Manager::Pointer(new Manager());
32
   
31
   
33
Manager::Manager() : io_service_work_(io_service_)
32
Manager::Manager() : io_service_work_(io_service_)
34
{
33
{
35
    boost::thread thread(boost::bind(&boost::asio::io_service::run, &this->io_service_));
34
    boost::thread thread(boost::bind(&boost::asio::io_service::run, &this->io_service_));
36
    this->thread_ = thread.move();
35
    this->thread_ = thread.move();
37
}
36
}
38
 
37
 
39
Manager::~Manager()
38
Manager::~Manager()
40
{
39
{
41
    this->clients_.clear();
40
    this->clients_.clear();
42
   
41
   
43
    this->thread_.interrupt();
42
    this->thread_.interrupt();
44
    this->thread_.join();
43
    this->thread_.join();
45
}
44
}
46
 
45
 
47
Manager::Pointer Manager::Instance()
46
Manager::Pointer Manager::Instance()
48
{
47
{
49
    return Manager::instance_;
48
    return Manager::instance_;
50
}
49
}
51
 
50
 
52
void Manager::Delete()
51
void Manager::Delete()
53
{
52
{
54
    Manager::instance_.reset();
53
    Manager::instance_.reset();
55
}
54
}
56
 
55
 
57
void Manager::ConnectSlots(const SignalOnNewState::slot_type& slot_on_new_state, const SignalOnNewData::slot_type& slot_on_new_data)
56
void Manager::ConnectSlots(const SignalOnNewState::slot_type& slot_on_new_state, const SignalOnNewData::slot_type& slot_on_new_data)
58
{
57
{
59
    this->signal_on_new_state_.connect(slot_on_new_state);
58
    this->signal_on_new_state_.connect(slot_on_new_state);
60
    this->signal_on_new_data_.connect(slot_on_new_data);
59
    this->signal_on_new_data_.connect(slot_on_new_data);
61
}
60
}
62
 
61
 
63
void Manager::SlotOnNewState(ClientId client_id, ServerId server_id, ClientState client_state)
62
void Manager::SlotOnNewState(ClientId client_id, ServerId server_id, ClientState client_state)
64
{
63
{
65
    if (client_state == CLIENT_STATE_DISCONNECTED)
64
    if (client_state == CLIENT_STATE_DISCONNECTED)
66
    {
65
    {
67
        this->clients_.erase(client_id);
66
        this->clients_.erase(client_id);
68
    }
67
    }
69
    else if (client_state == CLIENT_STATE_ACCEPTED)
68
    else if (client_state == CLIENT_STATE_ACCEPTED)
70
    {
69
    {
71
        ClientList::iterator it = this->clients_.find(client_id);
70
        ClientList::iterator it = this->clients_.find(client_id);
72
       
71
       
73
        if (it != this->clients_.end())
72
        if (it != this->clients_.end())
74
        {
73
        {
75
            TcpClient::Pointer client = TcpClient::Pointer(new TcpClient(this->io_service_, this->GetFreeClientId(), it->second->GetServerId()));
74
            TcpClient::Pointer client = TcpClient::Pointer(new TcpClient(this->io_service_, this->GetFreeClientId(), it->second->GetServerId()));
76
           
75
           
77
            client->ConnectSlots(Client::SignalOnNewState::slot_type(&Manager::SlotOnNewState, this, _1, _2, _3).track(Manager::instance_),
76
            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_));
77
                                 Client::SignalOnNewData::slot_type(&Manager::SlotOnNewData, this, _1, _2, _3).track(Manager::instance_));
79
           
78
           
80
            client->Accept(((TcpClient*)(it->second.get()))->ReleaseAcceptor());
79
            client->Accept(boost::polymorphic_downcast<TcpClient*>(it->second.get())->ReleaseAcceptor());
81
           
80
           
82
            this->clients_[client->GetId()] = client;
81
            this->clients_[client->GetId()] = client;
83
           
82
           
84
            this->signal_on_new_state_(client_id, server_id, CLIENT_STATE_CONNECTED);
83
            this->signal_on_new_state_(client_id, server_id, CLIENT_STATE_CONNECTED);
85
            return;
84
            return;
86
        }
85
        }
87
        else
86
        else
88
        {
87
        {
89
            throw std::runtime_error("Accepted unknown client!");
88
            throw std::runtime_error("Accepted unknown client!");
90
        }
89
        }
91
    }
90
    }
92
   
91
   
93
    this->signal_on_new_state_(client_id, server_id, client_state);
92
    this->signal_on_new_state_(client_id, server_id, client_state);
94
}
93
}
95
 
94
 
96
void Manager::SlotOnNewData(ClientId client_id, ServerId server_id, Buffer data)
95
void Manager::SlotOnNewData(ClientId client_id, ServerId server_id, Buffer data)
97
{
96
{
98
    this->signal_on_new_data_(client_id, server_id, data);
97
    this->signal_on_new_data_(client_id, server_id, data);
99
}
98
}
100
 
99
 
101
ServerId Manager::GetFreeServerId()
100
ServerId Manager::GetFreeServerId()
102
{
101
{
103
    ServerId server_id = 1;
102
    ServerId server_id = 1;
104
   
103
   
105
    for (ClientList::iterator it = this->clients_.begin(); it != this->clients_.end(); it++)
104
    for (ClientList::iterator it = this->clients_.begin(); it != this->clients_.end(); it++)
106
    {
105
    {
107
        if (it->second->GetServerId() != server_id)
106
        if (it->second->GetServerId() != server_id)
108
        {
107
        {
109
            return server_id;
108
            return server_id;
110
        }
109
        }
111
       
110
       
112
        server_id++;
111
        server_id++;
113
    }
112
    }
114
   
113
   
115
    return 0;
114
    return 0;
116
}
115
}
117
 
116
 
118
ClientId Manager::GetFreeClientId()
117
ClientId Manager::GetFreeClientId()
119
{
118
{
120
    ClientId client_id = 1;
119
    ClientId client_id = 1;
121
   
120
   
122
    while (this->clients_.find(client_id) != this->clients_.end())
121
    while (this->clients_.find(client_id) != this->clients_.end())
123
    {
122
    {
124
        client_id++;
123
        client_id++;
125
    }
124
    }
126
   
125
   
127
    return client_id;
126
    return client_id;
128
}
127
}
129
 
128
 
130
ServerId Manager::StartServer(Protocol protocol, unsigned int port)
129
ServerId Manager::StartServer(Protocol protocol, unsigned int port)
131
{
130
{
132
    if (protocol != PROTOCOL_TCP)
131
    if (protocol != PROTOCOL_TCP)
133
    {
132
    {
134
        throw std::runtime_error("Can not start server for the Serial or UDP protocol!");
133
        throw std::runtime_error("Can not start server for the Serial or UDP protocol!");
135
        return 0;
134
        return 0;
136
    }
135
    }
137
   
136
   
138
    TcpClient::Pointer client = TcpClient::Pointer(new TcpClient(this->io_service_, this->GetFreeClientId(), this->GetFreeServerId()));
137
    TcpClient::Pointer client = TcpClient::Pointer(new TcpClient(this->io_service_, this->GetFreeClientId(), this->GetFreeServerId()));
139
   
138
   
140
    client->ConnectSlots(Client::SignalOnNewState::slot_type(&Manager::SlotOnNewState, this, _1, _2, _3).track(Manager::instance_),
139
    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_));
140
                         Client::SignalOnNewData::slot_type(&Manager::SlotOnNewData, this, _1, _2, _3).track(Manager::instance_));
142
   
141
   
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)));    
142
    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
 
143
 
145
    client->Accept(acceptor);
144
    client->Accept(acceptor);
146
   
145
   
147
    this->clients_[client->GetId()] = client;
146
    this->clients_[client->GetId()] = client;
148
   
147
   
149
    return client->GetServerId();
148
    return client->GetServerId();
150
}
149
}
151
 
150
 
152
ClientId Manager::Connect(Protocol protocol, std::string address, unsigned int port_or_baud)
151
ClientId Manager::Connect(Protocol protocol, std::string address, unsigned int port_or_baud)
153
{
152
{
154
    Client::Pointer client;
153
    Client::Pointer client;
155
   
154
   
156
    switch (protocol)
155
    switch (protocol)
157
    {
156
    {
158
        case PROTOCOL_TCP:
157
        case PROTOCOL_TCP:
159
        {
158
        {
160
            client = Client::Pointer(new TcpClient(this->io_service_, this->GetFreeClientId(), 0));
159
            client = Client::Pointer(new TcpClient(this->io_service_, this->GetFreeClientId(), 0));
161
            break;
160
            break;
162
        }
161
        }
163
        case PROTOCOL_UDP:
162
        case PROTOCOL_UDP:
164
        {
163
        {
165
            client = Client::Pointer(new UdpClient(this->io_service_, this->GetFreeClientId(), 0));
164
            client = Client::Pointer(new UdpClient(this->io_service_, this->GetFreeClientId(), 0));
166
            break;
165
            break;
167
        }
166
        }
168
        case PROTOCOL_SERIAL:
167
        case PROTOCOL_SERIAL:
169
        {
168
        {
170
            client = Client::Pointer(new SerialClient(this->io_service_, this->GetFreeClientId(), 0));
169
            client = Client::Pointer(new SerialClient(this->io_service_, this->GetFreeClientId(), 0));
171
            break;
170
            break;
172
        }
171
        }
173
        default:
172
        default:
174
        {
173
        {
175
            throw std::runtime_error("Invalid protocol specified!");
174
            throw std::runtime_error("Invalid protocol specified!");
176
            return 0;
175
            return 0;
177
        }
176
        }
178
    }
177
    }
179
   
178
   
180
    client->ConnectSlots(Client::SignalOnNewState::slot_type(&Manager::SlotOnNewState, this, _1, _2, _3).track(Manager::instance_),
179
    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_));
180
                         Client::SignalOnNewData::slot_type(&Manager::SlotOnNewData, this, _1, _2, _3).track(Manager::instance_));
182
   
181
   
183
    try
182
    try
184
    {
183
    {
185
        client->Connect(address, port_or_baud);
184
        client->Connect(address, port_or_baud);
186
    }
185
    }
187
    catch (std::exception e)
186
    catch (std::exception e)
188
    {
187
    {
189
        throw e;
188
        throw e;
190
    }
189
    }
191
   
190
   
192
    this->clients_[client->GetId()] = client;
191
    this->clients_[client->GetId()] = client;
193
   
192
   
194
    return client->GetId();
193
    return client->GetId();
195
}
194
}
196
 
195
 
197
void Manager::SendToAll(ServerId server_id, Buffer data)
196
void Manager::SendToAll(ServerId server_id, Buffer data)
198
{
197
{
199
    this->io_service_.post(boost::bind(&Manager::SendToAllHandler, this, server_id, data));
198
    this->io_service_.post(boost::bind(&Manager::SendToAllHandler, this, server_id, data));
200
}
199
}
201
 
200
 
202
void Manager::SendTo(ClientId client_id, Buffer data)
201
void Manager::SendTo(ClientId client_id, Buffer data)
203
{
202
{
204
    this->io_service_.post(boost::bind(&Manager::SendToHandler, this, client_id, data));
203
    this->io_service_.post(boost::bind(&Manager::SendToHandler, this, client_id, data));
205
}
204
}
206
 
205
 
207
void Manager::StopServer(ServerId server_id)
206
void Manager::StopServer(ServerId server_id)
208
{
207
{
209
    this->io_service_.post(boost::bind(&Manager::StopServerHandler, this, server_id));
208
    this->io_service_.post(boost::bind(&Manager::StopServerHandler, this, server_id));
210
}
209
}
211
 
210
 
212
void Manager::Disconnect(ClientId client_id)
211
void Manager::Disconnect(ClientId client_id)
213
{
212
{
214
    this->io_service_.post(boost::bind(&Manager::DisconnectHandler, this, client_id));
213
    this->io_service_.post(boost::bind(&Manager::DisconnectHandler, this, client_id));
215
}
214
}
216
 
215
 
217
void Manager::SendToAllHandler(ServerId server_id, Buffer data)
216
void Manager::SendToAllHandler(ServerId server_id, Buffer data)
218
{
217
{
219
    for (ClientList::iterator it = this->clients_.begin(); it != this->clients_.end(); it++)
218
    for (ClientList::iterator it = this->clients_.begin(); it != this->clients_.end(); it++)
220
    {
219
    {
221
        if (it->second->GetServerId() == server_id)
220
        if (it->second->GetServerId() == server_id)
222
        {
221
        {
223
            it->second->Send(data);
222
            it->second->Send(data);
224
        }
223
        }
225
    }
224
    }
226
}
225
}
227
 
226
 
228
void Manager::SendToHandler(ClientId client_id, Buffer data)
227
void Manager::SendToHandler(ClientId client_id, Buffer data)
229
{
228
{
230
    ClientList::iterator it = this->clients_.find(client_id);
229
    ClientList::iterator it = this->clients_.find(client_id);
231
   
230
   
232
    if (it != this->clients_.end())
231
    if (it != this->clients_.end())
233
    {
232
    {
234
        it->second->Send(data);
233
        it->second->Send(data);
235
    }
234
    }
236
}
235
}
237
 
236
 
238
void Manager::StopServerHandler(ServerId server_id)
237
void Manager::StopServerHandler(ServerId server_id)
239
{
238
{
240
    for (ClientList::iterator it = this->clients_.begin(); it != this->clients_.end(); it++)
239
    for (ClientList::iterator it = this->clients_.begin(); it != this->clients_.end(); it++)
241
    {
240
    {
242
        if (it->second->GetServerId() == server_id)
241
        if (it->second->GetServerId() == server_id)
243
        {
242
        {
244
            it->second->Disconnect();
243
            it->second->Disconnect();
245
        }
244
        }
246
    }
245
    }
247
}
246
}
248
 
247
 
249
void Manager::DisconnectHandler(ClientId client_id)
248
void Manager::DisconnectHandler(ClientId client_id)
250
{
249
{
251
    ClientList::iterator it = this->clients_.find(client_id);
250
    ClientList::iterator it = this->clients_.find(client_id);
252
   
251
   
253
    if (it != this->clients_.end())
252
    if (it != this->clients_.end())
254
    {
253
    {
255
        it->second->Disconnect();
254
        it->second->Disconnect();
256
    }
255
    }
257
}
256
}
258
 
257
 
259
}; // namespace net
258
}; // namespace net
260
}; // namespace atom
259
}; // namespace atom
261
 
260