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 #include "BluetoothSdp.h"
00040 #include "ariba/overlay/OverlayBootstrap.h"
00041
00042 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
00043
00044
00045
00046 #define SDP_SPOVNET_BASE 0x4000
00047 #define SDP_ATTR_SPOVNET_NAME 0x0000 + SDP_SPOVNET_BASE
00048 #define SDP_ATTR_SPOVNET_INFO1 0x0001 + SDP_SPOVNET_BASE
00049 #define SDP_ATTR_SPOVNET_INFO2 0x0002 + SDP_SPOVNET_BASE
00050 #define SDP_ATTR_SPOVNET_INFO3 0x0003 + SDP_SPOVNET_BASE
00051
00052
00053 const uint8_t svc_uuid_int[] = {0x59, 0x29, 0x24, 0x34, 0x69, 0x42, 0x11, 0xde, 0x94,
00054 0x3e, 0x00, 0x21, 0x5d, 0xb4, 0xd8, 0x54};
00055
00056 const char *service_name = "SpoVNet";
00057 const char *svc_dsc = "www.ariba-underlay.org";
00058 const char *service_prov = "ITM Uni Karlsruhe";
00059
00060 #endif // HAVE_BLUETOOTH_BLUETOOTH_H
00061
00062
00063 namespace ariba {
00064 namespace utility {
00065
00066 use_logging_cpp(BluetoothSdp);
00067 OverlayBootstrap* BluetoothSdp::CONNECTION_CHECKER = NULL;
00068
00069 BluetoothSdp::BluetoothSdp(BootstrapInformationCallback* _callback) :
00070 BootstrapModule(_callback), scan_timer_(io_service_) {
00071 srand( time(NULL) );
00072 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
00073
00074
00075
00076 channel_ = 1;
00077
00078 #endif // HAVE_BLUETOOTH_BLUETOOTH_H
00079 }
00080
00081 BluetoothSdp::~BluetoothSdp() {
00082 }
00083
00084 string BluetoothSdp::getName() {
00085 return "BluetoothSdp";
00086 }
00087
00088 string BluetoothSdp::getInformation() {
00089 return "bootstrap module based on bluetooth service discovery protocol";
00090 }
00091
00092 bool BluetoothSdp::isFunctional() {
00093 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
00094 return true;
00095 #else
00096 return false;
00097 #endif
00098 }
00099
00100 void BluetoothSdp::start() {
00101 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
00102
00103
00104
00105
00106
00107 io_service_.post(boost::bind(&BluetoothSdp::bt_scan, this));
00108 t_ = boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_));
00109
00110 #endif // HAVE_BLUETOOTH_BLUETOOTH_H
00111 }
00112
00113 void BluetoothSdp::stop() {
00114 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
00115
00116
00117
00118
00119
00120
00121 io_service_.stop();
00122 t_.join();
00123
00124 if(sdp_session_ != NULL)
00125 sdp_close(sdp_session_);
00126
00127 #endif // HAVE_BLUETOOTH_BLUETOOTH_H
00128 }
00129
00130 void BluetoothSdp::publishService(string name, string info1, string info2,
00131 string info3) {
00132 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
00133
00134
00135
00136
00137
00138
00139 logging_debug("registering SDP service");
00140
00141 uint8_t rfcomm_channel = channel_;
00142
00143 uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid, svc_class_uuid;
00144 sdp_list_t *l2cap_list = 0, *rfcomm_list = 0, *root_list = 0, *proto_list =
00145 0, *access_proto_list = 0, *svc_class_list = 0, *profile_list = 0;
00146 sdp_data_t *channel = 0;
00147 sdp_profile_desc_t profile;
00148 sdp_record_t record = {0};
00149 sdp_session_ = 0;
00150
00151 if((name.length() > 256) || (info1.length() > 256) || (info2.length() > 256) || (info3.length() > 256)) {
00152 logging_error("string argument too long, max size is 256");
00153 return;
00154 }
00155
00156
00157
00158 uint8_t namelen, info1len, info2len, info3len;
00159
00160 namelen = (uint8_t)name.length();
00161 info1len = (uint8_t)info1.length();
00162 info2len = (uint8_t)info2.length();
00163 info3len = (uint8_t)info3.length();
00164
00165
00166 sdp_uuid128_create(&svc_uuid, &svc_uuid_int);
00167 sdp_set_service_id(&record, svc_uuid);
00168
00169
00170 sdp_uuid16_create(&svc_class_uuid, SERIAL_PORT_SVCLASS_ID);
00171 svc_class_list = sdp_list_append(0, &svc_class_uuid);
00172 sdp_set_service_classes(&record, svc_class_list);
00173
00174
00175 sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID);
00176 profile.version = 0x0100;
00177 profile_list = sdp_list_append(0, &profile);
00178 sdp_set_profile_descs(&record, profile_list);
00179
00180
00181 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
00182 root_list = sdp_list_append(0, &root_uuid);
00183 sdp_set_browse_groups(&record, root_list);
00184
00185
00186 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
00187 l2cap_list = sdp_list_append(0, &l2cap_uuid);
00188 proto_list = sdp_list_append(0, l2cap_list);
00189
00190
00191 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
00192 channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel);
00193 rfcomm_list = sdp_list_append(0, &rfcomm_uuid);
00194 sdp_list_append(rfcomm_list, channel);
00195 sdp_list_append(proto_list, rfcomm_list);
00196
00197 access_proto_list = sdp_list_append(0, proto_list);
00198 sdp_set_access_protos(&record, access_proto_list);
00199
00200
00201 sdp_set_info_attr(&record, service_name, service_prov, svc_dsc);
00202
00203
00204 sdp_attr_add_new(&record, SDP_ATTR_SPOVNET_NAME, SDP_TEXT_STR8,
00205 name.data());
00206
00207 sdp_attr_add_new(&record, SDP_ATTR_SPOVNET_INFO1, SDP_TEXT_STR8,
00208 info1.data());
00209
00210 sdp_attr_add_new(&record, SDP_ATTR_SPOVNET_INFO2, SDP_TEXT_STR8,
00211 info2.data());
00212
00213 sdp_attr_add_new(&record, SDP_ATTR_SPOVNET_INFO3, SDP_TEXT_STR8,
00214 info3.data());
00215
00216
00217 if( sdp_session_ == NULL ){
00218 sdp_session_ = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
00219 }
00220
00221 if (sdp_session_ == NULL) {
00222 logging_error( "something is wrong with your SDP server, nothing registered: " << strerror(errno) );
00223 } else {
00224 int ret = sdp_record_register(sdp_session_, &record, 0);
00225
00226 if(ret < 0){
00227 logging_error("failed registering sdp record: " << strerror(errno));
00228 }else{
00229 logging_debug("sdp record registered using session " << sdp_session_);
00230 }
00231 }
00232
00233
00234 sdp_data_free(channel);
00235 sdp_list_free(l2cap_list, 0);
00236 sdp_list_free(rfcomm_list, 0);
00237 sdp_list_free(root_list, 0);
00238 sdp_list_free(access_proto_list, 0);
00239 sdp_list_free(svc_class_list, 0);
00240 sdp_list_free(profile_list, 0);
00241
00242 #endif // HAVE_BLUETOOTH_BLUETOOTH_H
00243 }
00244
00245 void BluetoothSdp::revokeService(string name) {
00246 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
00247
00248 logging_debug("unregistering SDP service");
00249 sdp_close(sdp_session_);
00250
00251 #endif // HAVE_BLUETOOTH_BLUETOOTH_H
00252 }
00253
00254 #ifdef HAVE_BLUETOOTH_BLUETOOTH_H
00255
00256 void BluetoothSdp::bt_scan() {
00257
00258
00259
00260
00261
00262
00263 if(!haveConnections()){
00264
00265
00266
00267
00268
00269 logging_debug("scanning for peers");
00270
00271 inquiry_info *ii = NULL;
00272 int max_rsp, num_rsp;
00273 int dev_id, sock, len, flags;
00274 int i;
00275
00276 bdaddr_t address;
00277 uint8_t channel;
00278
00279 dev_id = hci_get_route(NULL);
00280 sock = hci_open_dev(dev_id);
00281 if (dev_id < 0 || sock < 0) {
00282 logging_error("opening socket for device "
00283 << dev_id << " failed. can not scan for peers: " << strerror(errno));
00284 return;
00285 }
00286
00287 len = 8;
00288 max_rsp = 255;
00289 flags = IREQ_CACHE_FLUSH;
00290 ii = (inquiry_info*) malloc(max_rsp * sizeof(inquiry_info));
00291
00292 num_rsp = hci_inquiry(dev_id, len, max_rsp, NULL, &ii, flags);
00293 if (num_rsp < 0)
00294 logging_error("hci_inquiry failed with " << num_rsp << ": " << strerror(errno));
00295
00296 for (i = 0; i < num_rsp; i++) {
00297 address = (ii + i)->bdaddr;
00298
00299 string saddress = ba2string(&address);
00300 string sname = ba2name(&address, sock);
00301
00302 logging_debug("found peer [" << saddress << "] [" << sname << "]");
00303 sdp_search( address, sname );
00304 }
00305
00306 free(ii);
00307 close(sock);
00308
00309 } else {
00310 logging_debug("have active connections, no sdp searching");
00311 }
00312
00313 int nextscan = (rand() % 10) + 5;
00314 logging_debug("next sdp scan try in " << nextscan << " seconds");
00315
00316 scan_timer_.expires_from_now( boost::posix_time::seconds(nextscan) );
00317 scan_timer_.async_wait( boost::bind(&BluetoothSdp::bt_scan, this) );
00318 }
00319
00320 void BluetoothSdp::sdp_search(bdaddr_t target, string devicename) {
00321
00322
00323
00324
00325
00326
00327 int status;
00328 uuid_t svc_uuid;
00329 sdp_list_t *response_list, *search_list, *attrid_list;
00330 sdp_session_t *session = NULL;
00331 uint32_t range = 0x0000ffff;
00332 uint8_t port = 0;
00333
00334
00335 logging_debug("querying services from bt device ["
00336 << ba2string(&target) << "] [" << devicename << "]");
00337
00338
00339 char name[256], info1[256], info2[256], info3[256];
00340
00341 session = sdp_connect(BDADDR_ANY, &target, SDP_RETRY_IF_BUSY);
00342
00343 if (session == NULL) {
00344 logging_error("failed to connect to SDP server at "
00345 << ba2string(&target) << ": " << strerror(errno));
00346 return;
00347 }
00348
00349 sdp_uuid128_create(&svc_uuid, &svc_uuid_int);
00350 search_list = sdp_list_append(0, &svc_uuid);
00351 attrid_list = sdp_list_append(0, &range);
00352
00353
00354 response_list = NULL;
00355 status = sdp_service_search_attr_req(session, search_list,
00356 SDP_ATTR_REQ_RANGE, attrid_list, &response_list);
00357
00358 if (status == 0) {
00359 sdp_list_t *proto_list = NULL;
00360 sdp_list_t *r = response_list;
00361
00362
00363 for ( ; r != NULL; r = r->next) {
00364 sdp_record_t *rec = (sdp_record_t*) r->data;
00365
00366
00367 if (sdp_get_access_protos(rec, &proto_list) == 0) {
00368
00369
00370 port = sdp_get_proto_port(proto_list, RFCOMM_UUID);
00371
00372 sdp_list_free(proto_list, 0);
00373
00374 sdp_get_string_attr(rec, SDP_ATTR_SPOVNET_NAME, (char*)&name, 256);
00375 sdp_get_string_attr(rec, SDP_ATTR_SPOVNET_INFO1, (char*)&info1, 256);
00376 sdp_get_string_attr(rec, SDP_ATTR_SPOVNET_INFO2, (char*)&info2, 256);
00377 sdp_get_string_attr(rec, SDP_ATTR_SPOVNET_INFO3, (char*)&info3, 256);
00378
00379 logging_info("Remote peer name is: " << name);
00380 logging_info("Remote peer info1 is: " << info1);
00381 logging_info("Remote peer info2 is: " << info2);
00382 logging_info("Remote peer info3 is: " << info3);
00383
00384
00385 callback->onBootstrapServiceFound(name, info1, info2, info3);
00386 }
00387 sdp_record_free(rec);
00388 }
00389 } else {
00390 logging_error("sdp_service_search_attr_req failed with timeout: " << strerror(errno));
00391 }
00392
00393 sdp_list_free(response_list, 0);
00394 sdp_list_free(search_list, 0);
00395 sdp_list_free(attrid_list, 0);
00396 sdp_close(session);
00397 }
00398
00399 string BluetoothSdp::ba2string(bdaddr_t* ba) {
00400
00401
00402
00403 char addr[32] = { 0 };
00404 char str[32] = { 0 };
00405 ba2str(ba, str);
00406 string result = str;
00407 return result;
00408 }
00409
00410 string BluetoothSdp::ba2name(bdaddr_t* ba, int sock){
00411
00412 char name[256] = {0};
00413 memset(name, 0, sizeof(name));
00414
00415 if( hci_read_remote_name(sock, ba, sizeof(name), name, 0) < 0 )
00416 strcpy(name, "unknown");
00417
00418 string result = name;
00419 return result;
00420 }
00421
00422 bool BluetoothSdp::haveConnections(){
00423
00424
00425
00426 if(CONNECTION_CHECKER == NULL) return false;
00427 return CONNECTION_CHECKER->haveOverlayConnections();
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 }
00459
00460 #endif // HAVE_BLUETOOTH_BLUETOOTH_H
00461
00462 }}