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

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

periodic broadcast hopefully fixed

File size: 9.5 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 typedef struct _Service {
93 string name;
94 string info1;
95 string info2;
96 string info3;
97 time_t lastseen;
98
99 _Service()
100 : name(""), info1(""), info2(""), info3(""), lastseen(0){
101 }
102
103 _Service(const string& _name, const string& _info1,
104 const string& _info2, const string& _info3, const time_t& _lastseen = 0){
105 name.assign (_name);
106 info1.assign(_info1);
107 info2.assign(_info2);
108 info3.assign(_info3);
109 lastseen = _lastseen;
110 }
111
112 _Service(const _Service& rh){
113 name.assign (rh.name);
114 info1.assign(rh.info1);
115 info2.assign(rh.info2);
116 info3.assign(rh.info3);
117 lastseen = rh.lastseen;
118 }
119 } Service;
120
121 typedef map<string,Service> ServiceList;
122
123 ServiceList localServices;
124 boost::mutex localServicesMutex;
125
126 ServiceList remoteServices;
127 boost::mutex remoteServicesMutex;
128
129 ServiceList newRemoteServices;
130 boost::mutex newRemoteServicesMutex;
131
132 boost::asio::io_service io_service;
133 boost::thread* io_service_thread;
134 static void threadFunc(PeriodicBroadcast* obj);
135
136 class udp_server {
137 private:
138 udp::socket socket_v4;
139 udp::socket socket_v6;
140 udp::endpoint remote_endpoint_;
141 boost::array<char, 1500> recv_buffer_4;
142 boost::array<char, 1500> recv_buffer_6;
143 ServiceList* services;
144 boost::mutex* servicesmutex;
145
146 public:
147 udp_server(boost::asio::io_service& io_service, ServiceList* _services, boost::mutex* _servicesmutex)
148 : services(_services), servicesmutex(_servicesmutex),
149 socket_v4(io_service), socket_v6(io_service) {
150
151 if( open4() ) start_receive_4();
152 if( open6() ) start_receive_6();
153 }
154
155 bool open4(){
156 boost::system::error_code err;
157
158 boost::asio::ip::udp::endpoint listen_endpoint_v4(
159 boost::asio::ip::address_v4::any(),
160 PeriodicBroadcast::serverport_v4);
161
162 err = socket_v4.open( listen_endpoint_v4.protocol(), err );
163 if(err){
164 logging_warn("failed opening ipv4 socket");
165 return false;
166 }
167
168 err = socket_v4.set_option( boost::asio::ip::udp::socket::reuse_address(true), err );
169 if(err){
170 logging_warn("failed setting reuse address option on ipv4 socket");
171 return false;
172 }
173
174 err = socket_v4.set_option( boost::asio::socket_base::broadcast(true), err );
175 if(err){
176 logging_warn("failed setting broadcast option on ipv4 socket");
177 return false;
178 }
179
180 err = socket_v4.bind( listen_endpoint_v4, err );
181 if(err){
182 logging_warn("failed binding ipv4 socket");
183 return false;
184 }
185
186 return true;
187 }
188
189 bool open6(){
190 boost::system::error_code err;
191
192 boost::asio::ip::udp::endpoint listen_endpoint_v6(
193 boost::asio::ip::address_v6::any(),
194 PeriodicBroadcast::serverport_v6);
195
196 err = socket_v6.open( listen_endpoint_v6.protocol(), err );
197 if(err){
198 logging_warn("failed opening ipv6 socket");
199 return false;
200 }
201
202 err = socket_v6.set_option( boost::asio::ip::udp::socket::reuse_address(true), err );
203 if(err){
204 logging_warn("failed setting reuse address option on ipv6 socket");
205 return false;
206 }
207
208 err = socket_v6.set_option( boost::asio::socket_base::broadcast(true), err );
209 if(err){
210 logging_warn("failed setting broadcast option on ipv6 socket");
211 return false;
212 }
213
214 err = socket_v6.bind( listen_endpoint_v6, err );
215 if(err){
216 logging_warn("failed binding ipv6 socket");
217 return false;
218 }
219
220 return true;
221 }
222
223 void sendservice(Service service){
224
225 PeriodicBroadcastMessage msg;
226
227 msg.setName( service.name );
228 msg.setInfo1( service.info1 );
229 msg.setInfo2( service.info2 );
230 msg.setInfo3( service.info3 );
231
232 Data data = data_serialize( msg, DEFAULT_V );
233 uint8_t* pnt = data.getBuffer();
234 size_t len = data.getLength() / 8;
235
236 boost::system::error_code err;
237
238 {
239 udp::endpoint endp(udp::v4(), PeriodicBroadcast::serverport_v4);
240 endp.address( boost::asio::ip::address_v4::broadcast() );
241 socket_v4.send_to( boost::asio::buffer(pnt, len), endp, 0, err );
242 if(err) logging_warn("failed sending message through ipv4 socket");
243 }
244 {
245 udp::endpoint endp(udp::v6(), PeriodicBroadcast::serverport_v6);
246 endp.address( boost::asio::ip::address_v6::from_string("ff02::1") );
247 socket_v6.send_to( boost::asio::buffer(pnt, len), endp, 0, err );
248 if(err) logging_warn("failed sending message through ipv6 socket");
249 }
250 }
251
252 private:
253 void start_receive_4(){
254 socket_v4.async_receive_from(
255 boost::asio::buffer(recv_buffer_4), remote_endpoint_,
256 boost::bind(&udp_server::handle_receive_4, this,
257 boost::asio::placeholders::error,
258 boost::asio::placeholders::bytes_transferred));
259 }
260
261 void start_receive_6(){
262 socket_v6.async_receive_from(
263 boost::asio::buffer(recv_buffer_6), remote_endpoint_,
264 boost::bind(&udp_server::handle_receive_6, this,
265 boost::asio::placeholders::error,
266 boost::asio::placeholders::bytes_transferred));
267 }
268
269 void handle_receive_4(const boost::system::error_code& error,
270 std::size_t bytes_transferred){
271
272 if (!error || error == boost::asio::error::message_size)
273 handle_info(recv_buffer_4, bytes_transferred);
274 else
275 logging_warn("failed receiving broadcast data: " << error.message());
276
277 start_receive_4();
278 }
279
280 void handle_receive_6(const boost::system::error_code& error,
281 std::size_t bytes_transferred){
282
283 if (!error || error == boost::asio::error::message_size)
284 handle_info(recv_buffer_6, bytes_transferred);
285 else
286 logging_warn("failed receiving broadcast data: " << error.message());
287
288 start_receive_6();
289 }
290
291 void handle_info(boost::array<char, 1500>& buffer, std::size_t length){
292 PeriodicBroadcastMessage msg;
293
294 Data data( (uint8_t*)buffer.data(), length*8 );
295 data_deserialize( msg, data );
296
297 { // insert new found service
298 boost::mutex::scoped_lock( *servicesmutex );
299
300 ServiceList::iterator it = services->find( msg.getName() );
301 if( it != services->end() ){
302
303 it->second.info1.assign( msg.getInfo1() );
304 it->second.info2.assign( msg.getInfo2() );
305 it->second.info3.assign( msg.getInfo3() );
306 it->second.lastseen = time(NULL);
307
308 } else {
309 Service s( msg.getName(), msg.getInfo1(), msg.getInfo2(), msg.getInfo3(), time(NULL));
310 services->insert( std::make_pair(msg.getName(), s) );
311 }
312 }
313 }
314
315 void handle_send(boost::shared_ptr<std::string> /*message*/,
316 const boost::system::error_code& error,
317 std::size_t /*bytes_transferred*/){
318
319 if(error)
320 logging_warn("failed sending out message");
321 }
322 };
323
324 udp_server server;
325};
326
327}} //namespace ariba, utility
328
329#endif // __BLUETOOTH_SDP_H
Note: See TracBrowser for help on using the repository browser.