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

Last change on this file since 5618 was 5531, checked in by Christoph Mayer, 15 years ago
File size: 10.3 KB
RevLine 
[4850]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
[4851]44#include <map>
45#include <string>
[4866]46#include <ctime>
[4850]47#include <iostream>
[4853]48#include <boost/asio.hpp>
[4851]49#include <boost/foreach.hpp>
[4850]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"
[4853]55#include "PeriodicBroadcastMessage.h"
[4850]56
57using std::map;
58using std::string;
[4866]59using std::cout;
[4853]60using boost::asio::ip::udp;
[4850]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
[4866]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
[4853]89 static const unsigned int serverport_v4;
90 static const unsigned int serverport_v6;
[4850]91
[5531]92 class Service {
93 private:
[4850]94 string name;
95 string info1;
96 string info2;
97 string info3;
[4866]98 time_t lastseen;
99
[5531]100 public:
101 Service()
[4866]102 : name(""), info1(""), info2(""), info3(""), lastseen(0){
103 }
[5414]104
[5531]105 Service(const string& _name, const string& _info1,
[5516]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;
[5420]112 }
113
[5531]114 Service(const Service& rh){
[5516]115 name.assign (rh.name);
116 info1.assign(rh.info1);
117 info2.assign(rh.info2);
118 info3.assign(rh.info3);
119 lastseen = rh.lastseen;
[5414]120 }
[4850]121
[5531]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
[4850]172 typedef map<string,Service> ServiceList;
[5516]173
[4850]174 ServiceList localServices;
175 boost::mutex localServicesMutex;
176
[4853]177 ServiceList remoteServices;
178 boost::mutex remoteServicesMutex;
179
180 ServiceList newRemoteServices;
181 boost::mutex newRemoteServicesMutex;
182
183 boost::asio::io_service io_service;
[4924]184 boost::thread* io_service_thread;
185 static void threadFunc(PeriodicBroadcast* obj);
[4853]186
187 class udp_server {
188 private:
[4920]189 udp::socket socket_v4;
190 udp::socket socket_v6;
[4853]191 udp::endpoint remote_endpoint_;
[5464]192 boost::array<char, 1500> recv_buffer_4;
193 boost::array<char, 1500> recv_buffer_6;
[4853]194 ServiceList* services;
195 boost::mutex* servicesmutex;
196
197 public:
198 udp_server(boost::asio::io_service& io_service, ServiceList* _services, boost::mutex* _servicesmutex)
[4872]199 : services(_services), servicesmutex(_servicesmutex),
[4920]200 socket_v4(io_service), socket_v6(io_service) {
[4853]201
[5516]202 if( open4() ) start_receive_4();
203 if( open6() ) start_receive_6();
204 }
205
206 bool open4(){
207 boost::system::error_code err;
208
[4872]209 boost::asio::ip::udp::endpoint listen_endpoint_v4(
[4920]210 boost::asio::ip::address_v4::any(),
[4872]211 PeriodicBroadcast::serverport_v4);
[4853]212
[5516]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
[4872]243 boost::asio::ip::udp::endpoint listen_endpoint_v6(
[4920]244 boost::asio::ip::address_v6::any(),
[4872]245 PeriodicBroadcast::serverport_v6);
246
[4920]247 err = socket_v6.open( listen_endpoint_v6.protocol(), err );
[5516]248 if(err){
249 logging_warn("failed opening ipv6 socket");
250 return false;
251 }
[4872]252
[4920]253 err = socket_v6.set_option( boost::asio::ip::udp::socket::reuse_address(true), err );
[5516]254 if(err){
255 logging_warn("failed setting reuse address option on ipv6 socket");
256 return false;
257 }
[4896]258
[4920]259 err = socket_v6.set_option( boost::asio::socket_base::broadcast(true), err );
[5516]260 if(err){
261 logging_warn("failed setting broadcast option on ipv6 socket");
262 return false;
263 }
[4896]264
[4921]265 err = socket_v6.bind( listen_endpoint_v6, err );
[5516]266 if(err){
267 logging_warn("failed binding ipv6 socket");
268 return false;
269 }
[4920]270
[5516]271 return true;
[4853]272 }
273
274 void sendservice(Service service){
275
[5479]276 PeriodicBroadcastMessage msg;
277
[5531]278 msg.setName( service.getName() );
279 msg.setInfo1( service.getInfo1() );
280 msg.setInfo2( service.getInfo2() );
281 msg.setInfo3( service.getInfo3() );
[5479]282
[4853]283 Data data = data_serialize( msg, DEFAULT_V );
284 uint8_t* pnt = data.getBuffer();
[4866]285 size_t len = data.getLength() / 8;
[4853]286
[4896]287 boost::system::error_code err;
[4866]288
[4853]289 {
290 udp::endpoint endp(udp::v4(), PeriodicBroadcast::serverport_v4);
291 endp.address( boost::asio::ip::address_v4::broadcast() );
[4920]292 socket_v4.send_to( boost::asio::buffer(pnt, len), endp, 0, err );
[4896]293 if(err) logging_warn("failed sending message through ipv4 socket");
[4853]294 }
[4920]295 {
[4853]296 udp::endpoint endp(udp::v6(), PeriodicBroadcast::serverport_v6);
297 endp.address( boost::asio::ip::address_v6::from_string("ff02::1") );
[4933]298 socket_v6.send_to( boost::asio::buffer(pnt, len), endp, 0, err );
299 if(err) logging_warn("failed sending message through ipv6 socket");
[4920]300 }
[4853]301 }
302
303 private:
[5465]304 void start_receive_4(){
[4920]305 socket_v4.async_receive_from(
[5464]306 boost::asio::buffer(recv_buffer_4), remote_endpoint_,
307 boost::bind(&udp_server::handle_receive_4, this,
[4853]308 boost::asio::placeholders::error,
309 boost::asio::placeholders::bytes_transferred));
[5465]310 }
[4920]311
[5465]312 void start_receive_6(){
[4853]313 socket_v6.async_receive_from(
[5464]314 boost::asio::buffer(recv_buffer_6), remote_endpoint_,
315 boost::bind(&udp_server::handle_receive_6, this,
[4853]316 boost::asio::placeholders::error,
317 boost::asio::placeholders::bytes_transferred));
318 }
319
[5464]320 void handle_receive_4(const boost::system::error_code& error,
[4853]321 std::size_t bytes_transferred){
322
[5464]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());
[4853]327
[5465]328 start_receive_4();
[5464]329 }
[4853]330
[5464]331 void handle_receive_6(const boost::system::error_code& error,
332 std::size_t bytes_transferred){
[4853]333
[5464]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());
[4853]338
[5465]339 start_receive_6();
[5464]340 }
[5421]341
[5464]342 void handle_info(boost::array<char, 1500>& buffer, std::size_t length){
343 PeriodicBroadcastMessage msg;
[4853]344
[5464]345 Data data( (uint8_t*)buffer.data(), length*8 );
346 data_deserialize( msg, data );
[4896]347
[5464]348 { // insert new found service
349 boost::mutex::scoped_lock( *servicesmutex );
[4896]350
[5464]351 ServiceList::iterator it = services->find( msg.getName() );
352 if( it != services->end() ){
353
[5531]354 it->second.setInfo1( msg.getInfo1() );
355 it->second.setInfo2( msg.getInfo2() );
356 it->second.setInfo3( msg.getInfo3() );
357 it->second.setLastseen( time(NULL) );
[5464]358
359 } else {
360 Service s( msg.getName(), msg.getInfo1(), msg.getInfo2(), msg.getInfo3(), time(NULL));
361 services->insert( std::make_pair(msg.getName(), s) );
362 }
[4853]363 }
364 }
365
366 void handle_send(boost::shared_ptr<std::string> /*message*/,
[4896]367 const boost::system::error_code& error,
[4853]368 std::size_t /*bytes_transferred*/){
[4920]369
[4896]370 if(error)
371 logging_warn("failed sending out message");
[4853]372 }
373 };
374
375 udp_server server;
[4850]376};
377
378}} //namespace ariba, utility
379
380#endif // __BLUETOOTH_SDP_H
Note: See TracBrowser for help on using the repository browser.