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

Last change on this file since 5308 was 4933, checked in by Christoph Mayer, 15 years ago
File size: 8.0 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
92 typedef struct _Service {
93 string name;
94 string info1;
95 string info2;
96 string info3;
[4866]97 time_t lastseen;
98
99 _Service()
100 : name(""), info1(""), info2(""), info3(""), lastseen(0){
101 }
[4850]102 } Service;
103
104 typedef map<string,Service> ServiceList;
105 ServiceList localServices;
106 boost::mutex localServicesMutex;
107
[4853]108 ServiceList remoteServices;
109 boost::mutex remoteServicesMutex;
110
111 ServiceList newRemoteServices;
112 boost::mutex newRemoteServicesMutex;
113
114 boost::asio::io_service io_service;
[4924]115 boost::thread* io_service_thread;
116 static void threadFunc(PeriodicBroadcast* obj);
[4853]117
118 class udp_server {
119 private:
[4920]120 udp::socket socket_v4;
121 udp::socket socket_v6;
[4853]122 udp::endpoint remote_endpoint_;
123 boost::array<char, 1500> recv_buffer_;
124 ServiceList* services;
125 boost::mutex* servicesmutex;
126
127 public:
128 udp_server(boost::asio::io_service& io_service, ServiceList* _services, boost::mutex* _servicesmutex)
[4872]129 : services(_services), servicesmutex(_servicesmutex),
[4920]130 socket_v4(io_service), socket_v6(io_service) {
[4853]131
[4872]132 boost::asio::ip::udp::endpoint listen_endpoint_v4(
[4920]133 boost::asio::ip::address_v4::any(),
[4872]134 PeriodicBroadcast::serverport_v4);
[4853]135
[4872]136 boost::asio::ip::udp::endpoint listen_endpoint_v6(
[4920]137 boost::asio::ip::address_v6::any(),
[4872]138 PeriodicBroadcast::serverport_v6);
139
[4896]140 boost::system::error_code err;
[4872]141
[4920]142 err = socket_v4.open( listen_endpoint_v4.protocol(), err );
143 if(err) logging_warn("failed opening ipv4 socket");
[4872]144
[4920]145 err = socket_v6.open( listen_endpoint_v6.protocol(), err );
146 if(err) logging_warn("failed opening ipv6 socket");
[4872]147
[4920]148 err = socket_v4.set_option( boost::asio::ip::udp::socket::reuse_address(true), err );
149 if(err) logging_warn("failed setting reuse address option on ipv4 socket");
[4896]150
[4920]151 err = socket_v6.set_option( boost::asio::ip::udp::socket::reuse_address(true), err );
152 if(err) logging_warn("failed setting reuse address option on ipv6 socket");
[4896]153
[4920]154 err = socket_v4.set_option( boost::asio::socket_base::broadcast(true), err );
155 if(err) logging_warn("failed setting broadcast option on ipv4 socket");
[4896]156
[4920]157 err = socket_v6.set_option( boost::asio::socket_base::broadcast(true), err );
158 if(err) logging_warn("failed setting broadcast option on ipv6 socket");
[4896]159
[4920]160 err = socket_v4.bind( listen_endpoint_v4, err );
161 if(err) logging_warn("failed binding ipv4 socket");
[4872]162
[4921]163 err = socket_v6.bind( listen_endpoint_v6, err );
[4920]164 if(err) logging_warn("failed binding ipv6 socket");
165
[4853]166 start_receive();
167 }
168
169 void sendservice(Service service){
170
171 PeriodicBroadcastMessage msg( service.name, service.info1, service.info2, service.info3 );
172 Data data = data_serialize( msg, DEFAULT_V );
173 uint8_t* pnt = data.getBuffer();
[4866]174 size_t len = data.getLength() / 8;
[4853]175
[4896]176 boost::system::error_code err;
[4866]177
[4853]178 {
179 udp::endpoint endp(udp::v4(), PeriodicBroadcast::serverport_v4);
180 endp.address( boost::asio::ip::address_v4::broadcast() );
[4920]181 socket_v4.send_to( boost::asio::buffer(pnt, len), endp, 0, err );
[4896]182 if(err) logging_warn("failed sending message through ipv4 socket");
[4853]183 }
[4920]184 {
[4853]185 udp::endpoint endp(udp::v6(), PeriodicBroadcast::serverport_v6);
186 endp.address( boost::asio::ip::address_v6::from_string("ff02::1") );
[4933]187 socket_v6.send_to( boost::asio::buffer(pnt, len), endp, 0, err );
188 if(err) logging_warn("failed sending message through ipv6 socket");
[4920]189 }
[4853]190 }
191
192 private:
193 void start_receive(){
[4920]194 socket_v4.async_receive_from(
[4853]195 boost::asio::buffer(recv_buffer_), remote_endpoint_,
196 boost::bind(&udp_server::handle_receive, this,
197 boost::asio::placeholders::error,
198 boost::asio::placeholders::bytes_transferred));
[4920]199
[4853]200 socket_v6.async_receive_from(
201 boost::asio::buffer(recv_buffer_), remote_endpoint_,
202 boost::bind(&udp_server::handle_receive, this,
203 boost::asio::placeholders::error,
204 boost::asio::placeholders::bytes_transferred));
205 }
206
207 void handle_receive(const boost::system::error_code& error,
208 std::size_t bytes_transferred){
209
210 if (!error || error == boost::asio::error::message_size){
211
212 PeriodicBroadcastMessage msg;
213 Data data( (uint8_t*)recv_buffer_.data(), bytes_transferred*8 );
214 data_deserialize( msg, data );
215
216 { // insert new found service
217 boost::mutex::scoped_lock( *servicesmutex );
218
219 ServiceList::iterator it = services->find( msg.getName() );
220 if( it != services->end() ) services->erase( it );
221
222 Service s;
223 s.info1 = msg.getInfo1();
224 s.info2 = msg.getInfo2();
225 s.info3 = msg.getInfo3();
[4866]226 s.lastseen = time(NULL);
[4853]227 services->insert( std::make_pair(msg.getName(), s) );
228 }
229
230 start_receive();
[4896]231 } else {
232
233 logging_warn("failed receiving message on ipv4 socket" << error);
234
[4853]235 }
236 }
237
238 void handle_send(boost::shared_ptr<std::string> /*message*/,
[4896]239 const boost::system::error_code& error,
[4853]240 std::size_t /*bytes_transferred*/){
[4920]241
[4896]242 if(error)
243 logging_warn("failed sending out message");
[4920]244
[4853]245 }
246
247 };
248
249 udp_server server;
[4920]250
[4850]251};
252
253}} //namespace ariba, utility
254
255#endif // __BLUETOOTH_SDP_H
Note: See TracBrowser for help on using the repository browser.