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, string info);
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 : socket_v4(io_service), socket_v6(io_service),
00200 services(_services), servicesmutex(_servicesmutex) {
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 if(service.getName().empty()) return;
00278
00279 msg.setName( service.getName() );
00280 msg.setInfo1( service.getInfo1() );
00281 msg.setInfo2( service.getInfo2() );
00282 msg.setInfo3( service.getInfo3() );
00283
00284 Data data = data_serialize( msg, DEFAULT_V );
00285 uint8_t* pnt = data.getBuffer();
00286 size_t len = data.getLength() / 8;
00287
00288 boost::system::error_code err;
00289
00290 {
00291 udp::endpoint endp(udp::v4(), PeriodicBroadcast::serverport_v4);
00292 endp.address( boost::asio::ip::address_v4::broadcast() );
00293 socket_v4.send_to( boost::asio::buffer(pnt, len), endp, 0, err );
00294 if(err) logging_warn("failed sending message through ipv4 socket");
00295 }
00296 {
00297 udp::endpoint endp(udp::v6(), PeriodicBroadcast::serverport_v6);
00298 endp.address( boost::asio::ip::address_v6::from_string("ff02::1") );
00299 socket_v6.send_to( boost::asio::buffer(pnt, len), endp, 0, err );
00300 if(err) logging_warn("failed sending message through ipv6 socket");
00301 }
00302 }
00303
00304 private:
00305 void start_receive_4(){
00306 socket_v4.async_receive_from(
00307 boost::asio::buffer(recv_buffer_4), remote_endpoint_,
00308 boost::bind(&udp_server::handle_receive_4, this,
00309 boost::asio::placeholders::error,
00310 boost::asio::placeholders::bytes_transferred));
00311 }
00312
00313 void start_receive_6(){
00314 socket_v6.async_receive_from(
00315 boost::asio::buffer(recv_buffer_6), remote_endpoint_,
00316 boost::bind(&udp_server::handle_receive_6, this,
00317 boost::asio::placeholders::error,
00318 boost::asio::placeholders::bytes_transferred));
00319 }
00320
00321 void handle_receive_4(const boost::system::error_code& error,
00322 std::size_t bytes_transferred){
00323
00324 if (!error || error == boost::asio::error::message_size)
00325 handle_info(recv_buffer_4, bytes_transferred);
00326 else
00327 logging_warn("failed receiving broadcast data: " << error.message());
00328
00329 start_receive_4();
00330 }
00331
00332 void handle_receive_6(const boost::system::error_code& error,
00333 std::size_t bytes_transferred){
00334
00335 if (!error || error == boost::asio::error::message_size)
00336 handle_info(recv_buffer_6, bytes_transferred);
00337 else
00338 logging_warn("failed receiving broadcast data: " << error.message());
00339
00340 start_receive_6();
00341 }
00342
00343 void handle_info(boost::array<char, 1500>& buffer, std::size_t length){
00344
00345 try {
00346
00347 PeriodicBroadcastMessage msg;
00348
00349 Data data( (uint8_t*)buffer.data(), length*8 );
00350 data_deserialize( msg, data );
00351
00352 {
00353 boost::mutex::scoped_lock lock( *servicesmutex );
00354 if(msg.getName().empty()) return;
00355
00356 ServiceList::iterator it = services->find( msg.getName() );
00357 if( it != services->end() ){
00358 it->second.setLastseen( time(NULL) );
00359 } else {
00360 Service s( msg.getName(), msg.getInfo1(), msg.getInfo2(), msg.getInfo3(), time(NULL));
00361 services->insert( std::make_pair(msg.getName(), s) );
00362 }
00363 }
00364
00365 }catch(...){
00366
00367 }
00368 }
00369
00370 void handle_send(boost::shared_ptr<std::string> ,
00371 const boost::system::error_code& error,
00372 std::size_t ){
00373
00374 if(error)
00375 logging_warn("failed sending out message");
00376 }
00377 };
00378
00379 udp_server server;
00380 };
00381
00382 }}
00383
00384 #endif // __BLUETOOTH_SDP_H