| [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 | 
 | 
|---|
 | 57 | using std::map;
 | 
|---|
 | 58 | using std::string;
 | 
|---|
| [4866] | 59 | using std::cout;
 | 
|---|
| [4853] | 60 | using boost::asio::ip::udp;
 | 
|---|
| [4850] | 61 | 
 | 
|---|
 | 62 | namespace ariba {
 | 
|---|
 | 63 | namespace utility {
 | 
|---|
 | 64 | 
 | 
|---|
 | 65 | class PeriodicBroadcast : public BootstrapModule, public Timer {
 | 
|---|
 | 66 |         use_logging_h(PeriodicBroadcast);
 | 
|---|
 | 67 | public:
 | 
|---|
 | 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 | 
 | 
|---|
 | 80 | protected:
 | 
|---|
 | 81 |         virtual void eventFunction();
 | 
|---|
 | 82 | 
 | 
|---|
 | 83 | private:
 | 
|---|
 | 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;
 | 
|---|
 | 115 | 
 | 
|---|
 | 116 |         class udp_server {
 | 
|---|
 | 117 |         private:
 | 
|---|
 | 118 |                 udp::socket socket_v4;
 | 
|---|
 | 119 |                 udp::socket socket_v6;
 | 
|---|
 | 120 |                 udp::endpoint remote_endpoint_;
 | 
|---|
 | 121 |                 boost::array<char, 1500> recv_buffer_;
 | 
|---|
 | 122 |                 ServiceList* services;
 | 
|---|
 | 123 |                 boost::mutex* servicesmutex;
 | 
|---|
 | 124 | 
 | 
|---|
 | 125 |         public:
 | 
|---|
 | 126 |                 udp_server(boost::asio::io_service& io_service, ServiceList* _services, boost::mutex* _servicesmutex)
 | 
|---|
| [4872] | 127 |                         : services(_services), servicesmutex(_servicesmutex),
 | 
|---|
 | 128 |                                 socket_v4(io_service), socket_v6(io_service) {
 | 
|---|
| [4853] | 129 | 
 | 
|---|
| [4872] | 130 |                         boost::asio::ip::udp::endpoint listen_endpoint_v4(
 | 
|---|
 | 131 |                                         boost::asio::ip::address_v4::broadcast(),
 | 
|---|
 | 132 |                                         PeriodicBroadcast::serverport_v4);
 | 
|---|
| [4853] | 133 | 
 | 
|---|
| [4872] | 134 |                         boost::asio::ip::udp::endpoint listen_endpoint_v6(
 | 
|---|
 | 135 |                                         boost::asio::ip::address_v6::from_string("ff02::1"),
 | 
|---|
 | 136 |                                         PeriodicBroadcast::serverport_v6);
 | 
|---|
 | 137 | 
 | 
|---|
| [4896] | 138 |                         boost::system::error_code err;
 | 
|---|
| [4872] | 139 | 
 | 
|---|
| [4896] | 140 |                         err = socket_v4.open( listen_endpoint_v4.protocol(), err );
 | 
|---|
 | 141 |                         if(err) logging_warn("failed opening ipv4 socket");
 | 
|---|
| [4872] | 142 | 
 | 
|---|
| [4896] | 143 |                         err = socket_v6.open( listen_endpoint_v6.protocol(), err );
 | 
|---|
 | 144 |                         if(err) logging_warn("failed opening ipv6 socket");
 | 
|---|
| [4872] | 145 | 
 | 
|---|
| [4896] | 146 |                         err = socket_v4.set_option( boost::asio::ip::udp::socket::reuse_address(true), err );
 | 
|---|
 | 147 |                         if(err) logging_warn("failed setting reuse address option on ipv4 socket");
 | 
|---|
 | 148 | 
 | 
|---|
 | 149 |                         err = socket_v6.set_option( boost::asio::ip::udp::socket::reuse_address(true), err );
 | 
|---|
 | 150 |                         if(err) logging_warn("failed setting reuse address option on ipv6 socket");
 | 
|---|
 | 151 | 
 | 
|---|
 | 152 |                         err = socket_v4.set_option( boost::asio::socket_base::broadcast(true), err );
 | 
|---|
 | 153 |                         if(err) logging_warn("failed setting broadcast option on ipv4 socket");
 | 
|---|
 | 154 | 
 | 
|---|
 | 155 |                         err = socket_v6.set_option( boost::asio::socket_base::broadcast(true), err );
 | 
|---|
 | 156 |                         if(err) logging_warn("failed setting broadcast option on ipv6 socket");
 | 
|---|
 | 157 | 
 | 
|---|
 | 158 |                         err = socket_v4.bind( listen_endpoint_v4, err );
 | 
|---|
 | 159 |                         if(err) logging_warn("failed binding ipv4 socket");
 | 
|---|
 | 160 |                         
 | 
|---|
| [4872] | 161 |                         //socket_v6.bind( listen_endpoint_v6 );
 | 
|---|
 | 162 | 
 | 
|---|
| [4853] | 163 |                         start_receive();
 | 
|---|
 | 164 |                 }
 | 
|---|
 | 165 | 
 | 
|---|
 | 166 |                 void sendservice(Service service){
 | 
|---|
 | 167 | 
 | 
|---|
 | 168 |                         PeriodicBroadcastMessage msg( service.name, service.info1, service.info2, service.info3 );
 | 
|---|
 | 169 |                         Data data = data_serialize( msg, DEFAULT_V );
 | 
|---|
 | 170 |                         uint8_t* pnt = data.getBuffer();
 | 
|---|
| [4866] | 171 |                         size_t len = data.getLength() / 8;
 | 
|---|
| [4853] | 172 |                         boost::system::error_code ignored_error;
 | 
|---|
 | 173 | 
 | 
|---|
| [4866] | 174 |                         cout << "-----------> sending out " << data << std::endl;
 | 
|---|
| [4896] | 175 |                         boost::system::error_code err;
 | 
|---|
| [4866] | 176 | 
 | 
|---|
| [4853] | 177 |                         {
 | 
|---|
 | 178 |                                 udp::endpoint endp(udp::v4(), PeriodicBroadcast::serverport_v4);
 | 
|---|
 | 179 |                                 endp.address( boost::asio::ip::address_v4::broadcast() );
 | 
|---|
| [4896] | 180 |                                 socket_v4.send_to( boost::asio::buffer(pnt, len), endp, 0, err );
 | 
|---|
 | 181 |                                 if(err) logging_warn("failed sending message through ipv4 socket");
 | 
|---|
| [4853] | 182 |                         }
 | 
|---|
| [4896] | 183 |                         {/*
 | 
|---|
| [4853] | 184 |                                 udp::endpoint endp(udp::v6(), PeriodicBroadcast::serverport_v6);
 | 
|---|
 | 185 |                                 endp.address( boost::asio::ip::address_v6::from_string("ff02::1") );
 | 
|---|
 | 186 |                                 socket_v6.send_to( boost::asio::buffer(pnt, len), endp, 0, ignored_error );
 | 
|---|
| [4896] | 187 |                         */}
 | 
|---|
| [4853] | 188 |                 }
 | 
|---|
 | 189 | 
 | 
|---|
 | 190 |         private:
 | 
|---|
 | 191 |                 void start_receive(){
 | 
|---|
 | 192 |                         socket_v4.async_receive_from(
 | 
|---|
 | 193 |                                         boost::asio::buffer(recv_buffer_), remote_endpoint_,
 | 
|---|
 | 194 |                                         boost::bind(&udp_server::handle_receive, this,
 | 
|---|
 | 195 |                                                         boost::asio::placeholders::error,
 | 
|---|
 | 196 |                                                         boost::asio::placeholders::bytes_transferred));
 | 
|---|
 | 197 | 
 | 
|---|
 | 198 |                         socket_v6.async_receive_from(
 | 
|---|
 | 199 |                                         boost::asio::buffer(recv_buffer_), remote_endpoint_,
 | 
|---|
 | 200 |                                         boost::bind(&udp_server::handle_receive, this,
 | 
|---|
 | 201 |                                                         boost::asio::placeholders::error,
 | 
|---|
 | 202 |                                                         boost::asio::placeholders::bytes_transferred));
 | 
|---|
 | 203 |                 }
 | 
|---|
 | 204 | 
 | 
|---|
 | 205 |                 void handle_receive(const boost::system::error_code& error,
 | 
|---|
 | 206 |                                 std::size_t bytes_transferred){
 | 
|---|
 | 207 | 
 | 
|---|
 | 208 |                         if (!error || error == boost::asio::error::message_size){
 | 
|---|
 | 209 | 
 | 
|---|
 | 210 |                                 PeriodicBroadcastMessage msg;
 | 
|---|
 | 211 |                                 Data data( (uint8_t*)recv_buffer_.data(), bytes_transferred*8 );
 | 
|---|
 | 212 |                                 data_deserialize( msg, data );
 | 
|---|
 | 213 | 
 | 
|---|
| [4866] | 214 |                                 cout << "-----------> received " << data << std::endl;
 | 
|---|
 | 215 | 
 | 
|---|
| [4853] | 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*/){
 | 
|---|
| [4896] | 241 |         
 | 
|---|
 | 242 |                         if(error)
 | 
|---|
 | 243 |                                 logging_warn("failed sending out message");
 | 
|---|
 | 244 |                 
 | 
|---|
| [4853] | 245 |                 }
 | 
|---|
 | 246 | 
 | 
|---|
 | 247 |         };
 | 
|---|
 | 248 | 
 | 
|---|
 | 249 |         udp_server server;
 | 
|---|
 | 250 | 
 | 
|---|
| [4850] | 251 | };
 | 
|---|
 | 252 | 
 | 
|---|
 | 253 | }} //namespace ariba, utility
 | 
|---|
 | 254 | 
 | 
|---|
 | 255 | #endif // __BLUETOOTH_SDP_H
 | 
|---|