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