source: source/ariba/utility/bootstrap/modules/periodicbroadcast/PeriodicBroadcast.h@ 5870

Last change on this file since 5870 was 5638, checked in by Christoph Mayer, 15 years ago

adress detection aufgeräumt, network info für bleutooth, data stream (hopeful crash fix), logging auf maemo nur warn, ...

File size: 10.3 KB
Line 
1// [License]
2// The Ariba-Underlay Copyright
3//
4// Copyright (c) 2008-2009, Institute of Telematics, UniversitÀt Karlsruhe (TH)
5//
6// Institute of Telematics
7// UniversitÀt Karlsruhe (TH)
8// Zirkel 2, 76128 Karlsruhe
9// Germany
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions are
13// met:
14//
15// 1. Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
22// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
25// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32//
33// The views and conclusions contained in the software and documentation
34// are those of the authors and should not be interpreted as representing
35// official policies, either expressed or implied, of the Institute of
36// Telematics.
37// [License]
38
39#ifndef __PERIODIC_BROADCAST_H
40#define __PERIODIC_BROADCAST_H
41
42#include "ariba/config.h"
43
44#include <map>
45#include <string>
46#include <ctime>
47#include <iostream>
48#include <boost/asio.hpp>
49#include <boost/foreach.hpp>
50#include <boost/thread/mutex.hpp>
51#include <boost/thread/thread.hpp>
52#include "ariba/utility/bootstrap/modules/BootstrapModule.h"
53#include "ariba/utility/logging/Logging.h"
54#include "ariba/utility/system/Timer.h"
55#include "PeriodicBroadcastMessage.h"
56
57using std::map;
58using std::string;
59using std::cout;
60using boost::asio::ip::udp;
61
62namespace ariba {
63namespace utility {
64
65class PeriodicBroadcast : public BootstrapModule, public Timer {
66 use_logging_h(PeriodicBroadcast);
67public:
68 PeriodicBroadcast(BootstrapInformationCallback* _callback);
69 virtual ~PeriodicBroadcast();
70
71 virtual void start();
72 virtual void stop();
73
74 virtual string getName();
75 virtual string getInformation();
76 virtual bool isFunctional();
77 virtual void publishService(string name, string info1, string info2, string info3);
78 virtual void revokeService(string name);
79
80protected:
81 virtual void eventFunction();
82
83private:
84 void sendLocalServices();
85 void updateRemoteServices();
86
87 static const long timerinterval; // used to send out updates on our services and check for new services
88 static const long servicetimeout; // timeout after that a service is dead when we did not receive updates
89 static const unsigned int serverport_v4;
90 static const unsigned int serverport_v6;
91
92 class Service {
93 private:
94 string name;
95 string info1;
96 string info2;
97 string info3;
98 time_t lastseen;
99
100 public:
101 Service()
102 : name(""), info1(""), info2(""), info3(""), lastseen(0){
103 }
104
105 Service(const string& _name, const string& _info1,
106 const string& _info2, const string& _info3, const time_t& _lastseen = 0){
107 name.assign (_name);
108 info1.assign(_info1);
109 info2.assign(_info2);
110 info3.assign(_info3);
111 lastseen = _lastseen;
112 }
113
114 Service(const Service& rh){
115 name.assign (rh.name);
116 info1.assign(rh.info1);
117 info2.assign(rh.info2);
118 info3.assign(rh.info3);
119 lastseen = rh.lastseen;
120 }
121
122 string getName() const {
123 return name;
124 }
125
126 string getInfo1() const {
127 return info1;
128 }
129
130 string getInfo2() const {
131 return info2;
132 }
133
134 string getInfo3() const {
135 return info3;
136 }
137
138 time_t getLastseen() const {
139 return lastseen;
140 }
141
142 void setName(string _name){
143 name.assign(_name);
144 }
145
146 void setInfo1(string _info1){
147 info1.assign(_info1);
148 }
149
150 void setInfo2(string _info2){
151 info2.assign(_info2);
152 }
153
154 void setInfo3(string _info3){
155 info3.assign(_info3);
156 }
157
158 void setLastseen(time_t _lastseen){
159 lastseen = _lastseen;
160 }
161
162 Service& operator=(const Service& rh){
163 this->name.assign( rh.getName() );
164 this->info1.assign( rh.getInfo1() );
165 this->info2.assign( rh.getInfo2() );
166 this->info3.assign( rh.getInfo3() );
167 this->lastseen = rh.lastseen;
168 return *this;
169 }
170 };
171
172 typedef map<string,Service> ServiceList;
173
174 ServiceList localServices;
175 boost::mutex localServicesMutex;
176
177 ServiceList remoteServices;
178 boost::mutex remoteServicesMutex;
179
180 ServiceList newRemoteServices;
181 boost::mutex newRemoteServicesMutex;
182
183 boost::asio::io_service io_service;
184 boost::thread* io_service_thread;
185 static void threadFunc(PeriodicBroadcast* obj);
186
187 class udp_server {
188 private:
189 udp::socket socket_v4;
190 udp::socket socket_v6;
191 udp::endpoint remote_endpoint_;
192 boost::array<char, 1500> recv_buffer_4;
193 boost::array<char, 1500> recv_buffer_6;
194 ServiceList* services;
195 boost::mutex* servicesmutex;
196
197 public:
198 udp_server(boost::asio::io_service& io_service, ServiceList* _services, boost::mutex* _servicesmutex)
199 : services(_services), servicesmutex(_servicesmutex),
200 socket_v4(io_service), socket_v6(io_service) {
201
202 if( open4() ) start_receive_4();
203 if( open6() ) start_receive_6();
204 }
205
206 bool open4(){
207 boost::system::error_code err;
208
209 boost::asio::ip::udp::endpoint listen_endpoint_v4(
210 boost::asio::ip::address_v4::any(),
211 PeriodicBroadcast::serverport_v4);
212
213 err = socket_v4.open( listen_endpoint_v4.protocol(), err );
214 if(err){
215 logging_warn("failed opening ipv4 socket");
216 return false;
217 }
218
219 err = socket_v4.set_option( boost::asio::ip::udp::socket::reuse_address(true), err );
220 if(err){
221 logging_warn("failed setting reuse address option on ipv4 socket");
222 return false;
223 }
224
225 err = socket_v4.set_option( boost::asio::socket_base::broadcast(true), err );
226 if(err){
227 logging_warn("failed setting broadcast option on ipv4 socket");
228 return false;
229 }
230
231 err = socket_v4.bind( listen_endpoint_v4, err );
232 if(err){
233 logging_warn("failed binding ipv4 socket");
234 return false;
235 }
236
237 return true;
238 }
239
240 bool open6(){
241 boost::system::error_code err;
242
243 boost::asio::ip::udp::endpoint listen_endpoint_v6(
244 boost::asio::ip::address_v6::any(),
245 PeriodicBroadcast::serverport_v6);
246
247 err = socket_v6.open( listen_endpoint_v6.protocol(), err );
248 if(err){
249 logging_warn("failed opening ipv6 socket");
250 return false;
251 }
252
253 err = socket_v6.set_option( boost::asio::ip::udp::socket::reuse_address(true), err );
254 if(err){
255 logging_warn("failed setting reuse address option on ipv6 socket");
256 return false;
257 }
258
259 err = socket_v6.set_option( boost::asio::socket_base::broadcast(true), err );
260 if(err){
261 logging_warn("failed setting broadcast option on ipv6 socket");
262 return false;
263 }
264
265 err = socket_v6.bind( listen_endpoint_v6, err );
266 if(err){
267 logging_warn("failed binding ipv6 socket");
268 return false;
269 }
270
271 return true;
272 }
273
274 void sendservice(Service service){
275
276 PeriodicBroadcastMessage msg;
277
278 msg.setName( service.getName() );
279 msg.setInfo1( service.getInfo1() );
280 msg.setInfo2( service.getInfo2() );
281 msg.setInfo3( service.getInfo3() );
282
283 Data data = data_serialize( msg, DEFAULT_V );
284 uint8_t* pnt = data.getBuffer();
285 size_t len = data.getLength() / 8;
286
287 boost::system::error_code err;
288
289 {
290 udp::endpoint endp(udp::v4(), PeriodicBroadcast::serverport_v4);
291 endp.address( boost::asio::ip::address_v4::broadcast() );
292 socket_v4.send_to( boost::asio::buffer(pnt, len), endp, 0, err );
293 if(err) logging_warn("failed sending message through ipv4 socket");
294 }
295 {
296 udp::endpoint endp(udp::v6(), PeriodicBroadcast::serverport_v6);
297 endp.address( boost::asio::ip::address_v6::from_string("ff02::1") );
298 socket_v6.send_to( boost::asio::buffer(pnt, len), endp, 0, err );
299 if(err) logging_warn("failed sending message through ipv6 socket");
300 }
301 }
302
303 private:
304 void start_receive_4(){
305 socket_v4.async_receive_from(
306 boost::asio::buffer(recv_buffer_4), remote_endpoint_,
307 boost::bind(&udp_server::handle_receive_4, this,
308 boost::asio::placeholders::error,
309 boost::asio::placeholders::bytes_transferred));
310 }
311
312 void start_receive_6(){
313 socket_v6.async_receive_from(
314 boost::asio::buffer(recv_buffer_6), remote_endpoint_,
315 boost::bind(&udp_server::handle_receive_6, this,
316 boost::asio::placeholders::error,
317 boost::asio::placeholders::bytes_transferred));
318 }
319
320 void handle_receive_4(const boost::system::error_code& error,
321 std::size_t bytes_transferred){
322
323 if (!error || error == boost::asio::error::message_size)
324 handle_info(recv_buffer_4, bytes_transferred);
325 else
326 logging_warn("failed receiving broadcast data: " << error.message());
327
328 start_receive_4();
329 }
330
331 void handle_receive_6(const boost::system::error_code& error,
332 std::size_t bytes_transferred){
333
334 if (!error || error == boost::asio::error::message_size)
335 handle_info(recv_buffer_6, bytes_transferred);
336 else
337 logging_warn("failed receiving broadcast data: " << error.message());
338
339 start_receive_6();
340 }
341
342 void handle_info(boost::array<char, 1500>& buffer, std::size_t length){
343 PeriodicBroadcastMessage msg;
344
345 Data data( (uint8_t*)buffer.data(), length*8 );
346 data_deserialize( msg, data );
347
348 { // insert new found service
349 boost::mutex::scoped_lock( *servicesmutex );
350
351 ServiceList::iterator it = services->find( msg.getName() );
352 if( it != services->end() ){
353
354 /*
355 it->second.setInfo1( msg.getInfo1() );
356 it->second.setInfo2( msg.getInfo2() );
357 it->second.setInfo3( msg.getInfo3() );
358 */
359 it->second.setLastseen( time(NULL) );
360
361 } else {
362 Service s( msg.getName(), msg.getInfo1(), msg.getInfo2(), msg.getInfo3(), time(NULL));
363 services->insert( std::make_pair(msg.getName(), s) );
364 }
365 }
366 }
367
368 void handle_send(boost::shared_ptr<std::string> /*message*/,
369 const boost::system::error_code& error,
370 std::size_t /*bytes_transferred*/){
371
372 if(error)
373 logging_warn("failed sending out message");
374 }
375 };
376
377 udp_server server;
378};
379
380}} //namespace ariba, utility
381
382#endif // __BLUETOOTH_SDP_H
Note: See TracBrowser for help on using the repository browser.