An Overlay-based
Virtual Network Substrate
SpoVNet

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

Last change on this file since 7468 was 6919, checked in by mies, 14 years ago

Fixed tons of warnings when using CXXFLAGS="-Wall"!

File size: 10.2 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                        : socket_v4(io_service), socket_v6(io_service),
200                          services(_services), servicesmutex(_servicesmutex) {
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
344                        try {
345
346                                PeriodicBroadcastMessage msg;
347
348                                Data data( (uint8_t*)buffer.data(), length*8 );
349                                data_deserialize( msg, data );
350
351                                { // insert new found service
352                                        boost::mutex::scoped_lock lock( *servicesmutex );
353
354                                        ServiceList::iterator it = services->find( msg.getName() );
355                                        if( it != services->end() ){
356                                                it->second.setLastseen( time(NULL) );
357                                        } else {
358                                                Service s( msg.getName(), msg.getInfo1(), msg.getInfo2(), msg.getInfo3(), time(NULL));
359                                                services->insert( std::make_pair(msg.getName(), s) );
360                                        }
361                                }
362
363                        }catch(...){
364                                /* ignore error */
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.