00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef __PERIODIC_BROADCAST_H
00040 #define __PERIODIC_BROADCAST_H
00041
00042 #include "ariba/config.h"
00043
00044 #include <map>
00045 #include <string>
00046 #include <ctime>
00047 #include <iostream>
00048 #include <boost/asio.hpp>
00049 #include <boost/foreach.hpp>
00050 #include <boost/thread/mutex.hpp>
00051 #include <boost/thread/thread.hpp>
00052 #include "ariba/utility/bootstrap/modules/BootstrapModule.h"
00053 #include "ariba/utility/logging/Logging.h"
00054 #include "ariba/utility/system/Timer.h"
00055 #include "PeriodicBroadcastMessage.h"
00056
00057 using std::map;
00058 using std::string;
00059 using std::cout;
00060 using boost::asio::ip::udp;
00061
00062 namespace ariba {
00063 namespace utility {
00064
00065 class PeriodicBroadcast : public BootstrapModule, public Timer {
00066 use_logging_h(PeriodicBroadcast);
00067 public:
00068 PeriodicBroadcast(BootstrapInformationCallback* _callback);
00069 virtual ~PeriodicBroadcast();
00070
00071 virtual void start();
00072 virtual void stop();
00073
00074 virtual string getName();
00075 virtual string getInformation();
00076 virtual bool isFunctional();
00077 virtual void publishService(string name, string info1, string info2, string info3);
00078 virtual void revokeService(string name);
00079
00080 protected:
00081 virtual void eventFunction();
00082
00083 private:
00084 void sendLocalServices();
00085 void updateRemoteServices();
00086
00087 static const long timerinterval;
00088 static const long servicetimeout;
00089 static const unsigned int serverport_v4;
00090 static const unsigned int serverport_v6;
00091
00092 class Service {
00093 private:
00094 string name;
00095 string info1;
00096 string info2;
00097 string info3;
00098 time_t lastseen;
00099
00100 public:
00101 Service()
00102 : name(""), info1(""), info2(""), info3(""), lastseen(0){
00103 }
00104
00105 Service(const string& _name, const string& _info1,
00106 const string& _info2, const string& _info3, const time_t& _lastseen = 0){
00107 name.assign (_name);
00108 info1.assign(_info1);
00109 info2.assign(_info2);
00110 info3.assign(_info3);
00111 lastseen = _lastseen;
00112 }
00113
00114 Service(const Service& rh){
00115 name.assign (rh.name);
00116 info1.assign(rh.info1);
00117 info2.assign(rh.info2);
00118 info3.assign(rh.info3);
00119 lastseen = rh.lastseen;
00120 }
00121
00122 string getName() const {
00123 return name;
00124 }
00125
00126 string getInfo1() const {
00127 return info1;
00128 }
00129
00130 string getInfo2() const {
00131 return info2;
00132 }
00133
00134 string getInfo3() const {
00135 return info3;
00136 }
00137
00138 time_t getLastseen() const {
00139 return lastseen;
00140 }
00141
00142 void setName(string _name){
00143 name.assign(_name);
00144 }
00145
00146 void setInfo1(string _info1){
00147 info1.assign(_info1);
00148 }
00149
00150 void setInfo2(string _info2){
00151 info2.assign(_info2);
00152 }
00153
00154 void setInfo3(string _info3){
00155 info3.assign(_info3);
00156 }
00157
00158 void setLastseen(time_t _lastseen){
00159 lastseen = _lastseen;
00160 }
00161
00162 Service& operator=(const Service& rh){
00163 this->name.assign( rh.getName() );
00164 this->info1.assign( rh.getInfo1() );
00165 this->info2.assign( rh.getInfo2() );
00166 this->info3.assign( rh.getInfo3() );
00167 this->lastseen = rh.lastseen;
00168 return *this;
00169 }
00170 };
00171
00172 typedef map<string,Service> ServiceList;
00173
00174 ServiceList localServices;
00175 boost::mutex localServicesMutex;
00176
00177 ServiceList remoteServices;
00178 boost::mutex remoteServicesMutex;
00179
00180 ServiceList newRemoteServices;
00181 boost::mutex newRemoteServicesMutex;
00182
00183 boost::asio::io_service io_service;
00184 boost::thread* io_service_thread;
00185 static void threadFunc(PeriodicBroadcast* obj);
00186
00187 class udp_server {
00188 private:
00189 udp::socket socket_v4;
00190 udp::socket socket_v6;
00191 udp::endpoint remote_endpoint_;
00192 boost::array<char, 1500> recv_buffer_4;
00193 boost::array<char, 1500> recv_buffer_6;
00194 ServiceList* services;
00195 boost::mutex* servicesmutex;
00196
00197 public:
00198 udp_server(boost::asio::io_service& io_service, ServiceList* _services, boost::mutex* _servicesmutex)
00199 : services(_services), servicesmutex(_servicesmutex),
00200 socket_v4(io_service), socket_v6(io_service) {
00201
00202 if( open4() ) start_receive_4();
00203 if( open6() ) start_receive_6();
00204 }
00205
00206 bool open4(){
00207 boost::system::error_code err;
00208
00209 boost::asio::ip::udp::endpoint listen_endpoint_v4(
00210 boost::asio::ip::address_v4::any(),
00211 PeriodicBroadcast::serverport_v4);
00212
00213 err = socket_v4.open( listen_endpoint_v4.protocol(), err );
00214 if(err){
00215 logging_warn("failed opening ipv4 socket");
00216 return false;
00217 }
00218
00219 err = socket_v4.set_option( boost::asio::ip::udp::socket::reuse_address(true), err );
00220 if(err){
00221 logging_warn("failed setting reuse address option on ipv4 socket");
00222 return false;
00223 }
00224
00225 err = socket_v4.set_option( boost::asio::socket_base::broadcast(true), err );
00226 if(err){
00227 logging_warn("failed setting broadcast option on ipv4 socket");
00228 return false;
00229 }
00230
00231 err = socket_v4.bind( listen_endpoint_v4, err );
00232 if(err){
00233 logging_warn("failed binding ipv4 socket");
00234 return false;
00235 }
00236
00237 return true;
00238 }
00239
00240 bool open6(){
00241 boost::system::error_code err;
00242
00243 boost::asio::ip::udp::endpoint listen_endpoint_v6(
00244 boost::asio::ip::address_v6::any(),
00245 PeriodicBroadcast::serverport_v6);
00246
00247 err = socket_v6.open( listen_endpoint_v6.protocol(), err );
00248 if(err){
00249 logging_warn("failed opening ipv6 socket");
00250 return false;
00251 }
00252
00253 err = socket_v6.set_option( boost::asio::ip::udp::socket::reuse_address(true), err );
00254 if(err){
00255 logging_warn("failed setting reuse address option on ipv6 socket");
00256 return false;
00257 }
00258
00259 err = socket_v6.set_option( boost::asio::socket_base::broadcast(true), err );
00260 if(err){
00261 logging_warn("failed setting broadcast option on ipv6 socket");
00262 return false;
00263 }
00264
00265 err = socket_v6.bind( listen_endpoint_v6, err );
00266 if(err){
00267 logging_warn("failed binding ipv6 socket");
00268 return false;
00269 }
00270
00271 return true;
00272 }
00273
00274 void sendservice(Service service){
00275
00276 PeriodicBroadcastMessage msg;
00277
00278 msg.setName( service.getName() );
00279 msg.setInfo1( service.getInfo1() );
00280 msg.setInfo2( service.getInfo2() );
00281 msg.setInfo3( service.getInfo3() );
00282
00283 Data data = data_serialize( msg, DEFAULT_V );
00284 uint8_t* pnt = data.getBuffer();
00285 size_t len = data.getLength() / 8;
00286
00287 boost::system::error_code err;
00288
00289 {
00290 udp::endpoint endp(udp::v4(), PeriodicBroadcast::serverport_v4);
00291 endp.address( boost::asio::ip::address_v4::broadcast() );
00292 socket_v4.send_to( boost::asio::buffer(pnt, len), endp, 0, err );
00293 if(err) logging_warn("failed sending message through ipv4 socket");
00294 }
00295 {
00296 udp::endpoint endp(udp::v6(), PeriodicBroadcast::serverport_v6);
00297 endp.address( boost::asio::ip::address_v6::from_string("ff02::1") );
00298 socket_v6.send_to( boost::asio::buffer(pnt, len), endp, 0, err );
00299 if(err) logging_warn("failed sending message through ipv6 socket");
00300 }
00301 }
00302
00303 private:
00304 void start_receive_4(){
00305 socket_v4.async_receive_from(
00306 boost::asio::buffer(recv_buffer_4), remote_endpoint_,
00307 boost::bind(&udp_server::handle_receive_4, this,
00308 boost::asio::placeholders::error,
00309 boost::asio::placeholders::bytes_transferred));
00310 }
00311
00312 void start_receive_6(){
00313 socket_v6.async_receive_from(
00314 boost::asio::buffer(recv_buffer_6), remote_endpoint_,
00315 boost::bind(&udp_server::handle_receive_6, this,
00316 boost::asio::placeholders::error,
00317 boost::asio::placeholders::bytes_transferred));
00318 }
00319
00320 void handle_receive_4(const boost::system::error_code& error,
00321 std::size_t bytes_transferred){
00322
00323 if (!error || error == boost::asio::error::message_size)
00324 handle_info(recv_buffer_4, bytes_transferred);
00325 else
00326 logging_warn("failed receiving broadcast data: " << error.message());
00327
00328 start_receive_4();
00329 }
00330
00331 void handle_receive_6(const boost::system::error_code& error,
00332 std::size_t bytes_transferred){
00333
00334 if (!error || error == boost::asio::error::message_size)
00335 handle_info(recv_buffer_6, bytes_transferred);
00336 else
00337 logging_warn("failed receiving broadcast data: " << error.message());
00338
00339 start_receive_6();
00340 }
00341
00342 void handle_info(boost::array<char, 1500>& buffer, std::size_t length){
00343
00344 try {
00345
00346 PeriodicBroadcastMessage msg;
00347
00348 Data data( (uint8_t*)buffer.data(), length*8 );
00349 data_deserialize( msg, data );
00350
00351 {
00352 boost::mutex::scoped_lock( *servicesmutex );
00353
00354 ServiceList::iterator it = services->find( msg.getName() );
00355 if( it != services->end() ){
00356 it->second.setLastseen( time(NULL) );
00357 } else {
00358 Service s( msg.getName(), msg.getInfo1(), msg.getInfo2(), msg.getInfo3(), time(NULL));
00359 services->insert( std::make_pair(msg.getName(), s) );
00360 }
00361 }
00362
00363 }catch(...){
00364
00365 }
00366 }
00367
00368 void handle_send(boost::shared_ptr<std::string> ,
00369 const boost::system::error_code& error,
00370 std::size_t ){
00371
00372 if(error)
00373 logging_warn("failed sending out message");
00374 }
00375 };
00376
00377 udp_server server;
00378 };
00379
00380 }}
00381
00382 #endif // __BLUETOOTH_SDP_H