An Overlay-based
Virtual Network Substrate
SpoVNet

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

Last change on this file since 5638 was 5638, checked in by Christoph Mayer, 14 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.