Ignore:
Timestamp:
Jul 13, 2009, 12:13:24 PM (15 years ago)
Author:
stud-florian
Message:

Implemented most SDP stuff, but didn't test it.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • source/ariba/utility/bootstrap/modules/bluetoothsdp/BluetoothSdp.cpp

    r4840 r4870  
    3939#include "BluetoothSdp.h"
    4040
     41#ifdef HAVE_BLUETOOTH_BLUETOOTH_H
     42
     43// Attribute descriptors for SDP
     44// base was chosen randomly
     45#define SDP_SPOVNET_BASE                0x4000
     46#define SDP_ATTR_SPOVNET_NAME           0x0000 + SDP_SPOVNET_BASE
     47#define SDP_ATTR_SPOVNET_INFO1          0x0001 + SDP_SPOVNET_BASE
     48#define SDP_ATTR_SPOVNET_INFO2          0x0002 + SDP_SPOVNET_BASE
     49#define SDP_ATTR_SPOVNET_INFO3          0x0003 + SDP_SPOVNET_BASE
     50
     51// The SpoVNet unique identifier, this should be the same for all SpoVNet implementations
     52const uint8_t svc_uuid_int[] = {0x59, 0x29, 0x24, 0x34, 0x69, 0x42, 0x11, 0xde, 0x94,
     53        0x3e, 0x00, 0x21, 0x5d, 0xb4, 0xd8, 0x54};
     54
     55const char *service_name = "SpoVNet";
     56const char *svc_dsc = "Spontaneous Virtual Network";
     57const char *service_prov = "ITM Uni Karlsruhe";
     58
     59#endif // HAVE_BLUETOOTH_BLUETOOTH_H
     60
     61
    4162namespace ariba {
    4263namespace utility {
    43 
    44 use_logging_cpp(BluetoothSdp);
    45 
    46 BluetoothSdp::BluetoothSdp(BootstrapInformationCallback* _callback) : BootstrapModule(_callback) {
    47 }
    48 
    49 BluetoothSdp::~BluetoothSdp(){
    50 }
    51 
    52 string BluetoothSdp::getName(){
     64use_logging_cpp(BluetoothSdp)
     65;
     66
     67//TODO: figure out this compiler flag stuff
     68
     69BluetoothSdp::BluetoothSdp(BootstrapInformationCallback* _callback) :
     70        BootstrapModule(_callback), scan_timer_(io_service_) {
     71#ifdef HAVE_BLUETOOTH_BLUETOOTH_H
     72
     73        // TODO: think about this!
     74        channel_ = 7;
     75        // TODO: what about the callback?
     76
     77#endif // HAVE_BLUETOOTH_BLUETOOTH_H
     78}
     79
     80BluetoothSdp::~BluetoothSdp() {
     81}
     82
     83string BluetoothSdp::getName() {
    5384        return "BluetoothSdp";
    5485}
    5586
    56 string BluetoothSdp::getInformation(){
     87string BluetoothSdp::getInformation() {
    5788        return "bootstrap module based on bluetooth service discovery protocol";
    5889}
    5990
    60 bool BluetoothSdp::isFunctional(){
     91bool BluetoothSdp::isFunctional() {
     92#ifdef HAVE_BLUETOOTH_BLUETOOTH_H
     93        return false; // Not tested yet :)
     94#else
    6195        return false;
    62 }
    63 
    64 void BluetoothSdp::start(){
    65 }
    66 
    67 void BluetoothSdp::stop(){
    68 }
    69 
    70 void BluetoothSdp::publishService(string name, string info1, string info2, string info3){
    71 }
    72 
    73 void BluetoothSdp::revokeService(string name){
    74 }
    75 
    76 }} //namespace ariba, utility
     96#endif
     97}
     98
     99void BluetoothSdp::start() {
     100#ifdef HAVE_BLUETOOTH_BLUETOOTH_H
     101
     102        /*
     103         * Initializes and forks the scanner.
     104         */
     105
     106        io_service_.post(boost::bind(&BluetoothSdp::bt_scan, this));
     107        t_ = boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_));
     108
     109#endif // HAVE_BLUETOOTH_BLUETOOTH_H
     110}
     111
     112void BluetoothSdp::stop() {
     113#ifdef HAVE_BLUETOOTH_BLUETOOTH_H
     114
     115        /*
     116         * Stops the scanner.
     117         */
     118
     119        // not sure if this is thread safe
     120        io_service_.stop();
     121        t_.join();
     122
     123#endif // HAVE_BLUETOOTH_BLUETOOTH_H
     124}
     125
     126void BluetoothSdp::publishService(string name, string info1, string info2,
     127                string info3) {
     128#ifdef HAVE_BLUETOOTH_BLUETOOTH_H
     129
     130        /*
     131         * Publishes an SpoVNet SDP Service and
     132         * adds the arguments as info attributes.
     133         */
     134
     135        logging_info("Registering SDP service.\n");
     136
     137        uint8_t rfcomm_channel = channel_;
     138
     139        uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid, svc_class_uuid;
     140        sdp_list_t *l2cap_list = 0, *rfcomm_list = 0, *root_list = 0, *proto_list =
     141        0, *access_proto_list = 0, *svc_class_list = 0, *profile_list = 0;
     142        sdp_data_t *channel = 0;
     143        sdp_profile_desc_t profile;
     144        sdp_record_t record = {0};
     145        sdp_session_ = 0;
     146
     147        bdaddr_t bdaddr_any = (bdaddr_t) { {0, 0, 0, 0, 0, 0}};
     148        bdaddr_t bdaddr_local = (bdaddr_t) { {0, 0, 0, 0xff, 0xff, 0xff}};
     149
     150        // prepare the info attribute buffers
     151        namelen = (uint8_t)name.length();
     152        info1len = (uint8_t)info1.length();
     153        info2len = (uint8_t)info2.length();
     154        info3len = (uint8_t)info3.length();
     155
     156        if((namelen > 256) || (info1len > 256) || (info2len > 256) || (info3len > 256)) {
     157                logging_error("String Argument too long, max size is 256!");
     158                return;
     159        }
     160
     161        // we need to save the string len for sdp
     162        namebuf = (char)namelen;
     163        namebuf.append(name);
     164        info1buf = (char)info1len;
     165        info1buf.append(info1);
     166        info2buf = (char)info2len;
     167        info2buf.append(info2);
     168        info3buf = (char)info3len;
     169        info3buf.append(info3);
     170
     171        // set the general service ID
     172        sdp_uuid128_create(&svc_uuid, &svc_uuid_int);
     173        sdp_set_service_id(&record, svc_uuid);
     174
     175        // set the service class
     176        sdp_uuid16_create(&svc_class_uuid, SERIAL_PORT_SVCLASS_ID);
     177        svc_class_list = sdp_list_append(0, &svc_class_uuid);
     178        sdp_set_service_classes(&record, svc_class_list);
     179
     180        // set the Bluetooth profile information
     181        sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID);
     182        profile.version = 0x0100;
     183        profile_list = sdp_list_append(0, &profile);
     184        sdp_set_profile_descs(&record, profile_list);
     185
     186        // make the service record publicly browsable
     187        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
     188        root_list = sdp_list_append(0, &root_uuid);
     189        sdp_set_browse_groups(&record, root_list);
     190
     191        // set l2cap informatiint argc, char* argv[]on
     192        sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
     193        l2cap_list = sdp_list_append(0, &l2cap_uuid);
     194        proto_list = sdp_list_append(0, l2cap_list);
     195
     196        // register the RFCOMM channel for RFCOMM sockets
     197        sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
     198        channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel);
     199        rfcomm_list = sdp_list_append(0, &rfcomm_uuid);
     200        sdp_list_append(rfcomm_list, channel);
     201        sdp_list_append(proto_list, rfcomm_list);
     202
     203        access_proto_list = sdp_list_append(0, proto_list);
     204        sdp_set_access_protos(&record, access_proto_list);
     205
     206        // set the name, provider, and description
     207        sdp_set_info_attr(&record, service_name, service_prov, svc_dsc);
     208
     209
     210        // add the info attributes
     211        uint8_t namelen, info1len, info2len, info3len;
     212        string namebuf, info1buf, info2buf, info3buf;
     213
     214
     215        sdp_attr_add_new(&record, SDP_ATTR_SPOVNET_NAME, SDP_TEXT_STR32,
     216                        namebuf.data());
     217
     218        info1len = info1.length();
     219        info1buf.append((const char*) &info1len, 4);
     220        info1buf.append(info1);
     221        sdp_attr_add_new(&record, SDP_ATTR_SPOVNET_INFO1, SDP_TEXT_STR32,
     222                        info1buf.data());
     223
     224        info2len = info2.length();
     225        info2buf.append((const char*) &info2len, 4);
     226        info2buf.append(info2);
     227        sdp_attr_add_new(&record, SDP_ATTR_SPOVNET_INFO2, SDP_TEXT_STR32,
     228                        info2buf.data());
     229
     230        info3len = info3.length();
     231        info3buf.append((const char*) &info3len, 4);
     232        info3buf.append(info3);
     233        sdp_attr_add_new(&record, SDP_ATTR_SPOVNET_INFO3, SDP_TEXT_STR32,
     234                        info3buf.data());
     235
     236        // connect to the local SDP server, register the service record,
     237        // and disconnect
     238        sdp_session_ = sdp_connect(&bdaddr_any, &bdaddr_local, SDP_RETRY_IF_BUSY);
     239
     240        if (sdp_session_ == 0) {
     241                std::cout
     242                << "Something is wrong with your SDP server, nothing registered.";
     243        } else {
     244                sdp_record_register(sdp_session_, &record, 0);
     245        }
     246
     247        // cleanup
     248        sdp_data_free(channel);
     249        sdp_list_free(l2cap_list, 0);
     250        sdp_list_free(rfcomm_list, 0);
     251        sdp_list_free(root_list, 0);
     252        sdp_list_free(access_proto_list, 0);
     253        sdp_list_free(svc_class_list, 0);
     254        sdp_list_free(profile_list, 0);
     255
     256#endif // HAVE_BLUETOOTH_BLUETOOTH_H
     257}
     258
     259void BluetoothSdp::revokeService(string name) {
     260#ifdef HAVE_BLUETOOTH_BLUETOOTH_H
     261
     262        logging_info("Unregistering SDP service.\n");
     263        sdp_close(sdp_session_);
     264
     265#endif // HAVE_BLUETOOTH_BLUETOOTH_H
     266}
     267
     268#ifdef HAVE_BLUETOOTH_BLUETOOTH_H
     269
     270void BluetoothSdp::bt_scan() {
     271
     272
     273        /*
     274         * Scans for other bluetooth devices and starts a SDP search on them.
     275         * Repeats 20 seconds after the end of the scan.
     276         */
     277
     278        logging_info("Scanning for peers.\n");
     279
     280        inquiry_info *ii = NULL;
     281        int max_rsp, num_rsp;
     282        int dev_id, sock, len, flags;
     283        int i;
     284
     285        /*
     286         char addr[19] = { 0 };
     287         char name[248] = { 0 };
     288         */
     289        bdaddr_t address;
     290        uint8_t channel;
     291
     292        dev_id = hci_get_route(NULL);
     293        sock = hci_open_dev(dev_id);
     294        if (dev_id < 0 || sock < 0) {
     295                perror("opening socket");
     296                exit(1);
     297        }
     298
     299        len = 8;
     300        max_rsp = 255;
     301        flags = IREQ_CACHE_FLUSH;
     302        ii = (inquiry_info*) malloc(max_rsp * sizeof(inquiry_info));
     303
     304        num_rsp = hci_inquiry(dev_id, len, max_rsp, NULL, &ii, flags);
     305        if (num_rsp < 0)
     306        perror("hci_inquiry");
     307
     308        for (i = 0; i < num_rsp; i++) {
     309                /*
     310                 ba2str(&(ii + i)->bdaddr, addr);
     311                 memset(name, 0, sizeof(name));
     312                 if (hci_read_remote_name(sock, &(ii + i)->bdaddr, sizeof(name),
     313                 name, 0) < 0)
     314                 strcpy(name, "[unknown]");
     315                 printf("%s  %s\n", addr, name);
     316                 */
     317
     318                address = (ii + i)->bdaddr;
     319                // TODO: sdp_search can be very slow, fork it!
     320                sdp_search(address);
     321        }
     322
     323        free(ii);
     324        close(sock);
     325
     326        logging_info("Next scan in 20 seconds.\n");
     327
     328        scan_timer_.expires_from_now(boost::posix_time::seconds(20));
     329        scan_timer_.async_wait(boost::bind(&BluetoothSdp::bt_scan, this));
     330
     331
     332}
     333
     334void BluetoothSdp::sdp_search(bdaddr_t target) {
     335
     336        /*
     337         * Searches target for SDP records with the SpoVnet uuid
     338         * and extracts its info attributes.
     339         */
     340
     341        int status;
     342        uuid_t svc_uuid;
     343        sdp_list_t *response_list, *search_list, *attrid_list;
     344        sdp_session_t *session = 0;
     345        uint32_t range = 0x0000ffff;
     346        uint8_t port = 0;
     347        bdaddr_t any_addr = (bdaddr_t) { {0, 0, 0, 0, 0, 0}};
     348
     349        // prepare the buffers for the attributes
     350        string name, info1, info2, info3;
     351        name.reserve(2**32);
     352
     353        // connect to the SDP server running on the remote machine
     354        session = sdp_connect(&any_addr, &target, 0);
     355
     356        if (session == 0) {
     357                // TODO: put the remote's address here
     358                logging_error("Failed to connect to remote SDP server.");
     359                return;
     360        }
     361
     362        sdp_uuid128_create(&svc_uuid, &svc_uuid_int);
     363        search_list = sdp_list_append(0, &svc_uuid);
     364        attrid_list = sdp_list_append(0, &range);
     365
     366        // get a list of service records that have UUID uuid_
     367        response_list = NULL;
     368        status = sdp_service_search_attr_req(session, search_list,
     369                        SDP_ATTR_REQ_RANGE, attrid_list, &response_list);
     370
     371        if (status == 0) {
     372                sdp_list_t *proto_list = NULL;
     373                sdp_list_t *r = response_list;
     374
     375                // go through each of the service records
     376                for (; r; r = r->next) {
     377                        sdp_record_t *rec = (sdp_record_t*) r->data;
     378
     379                        // get a list of the protocol sequences
     380                        if (sdp_get_access_protos(rec, &proto_list) == 0) {
     381
     382                                // get the RFCOMM port number
     383                                port = sdp_get_proto_port(proto_list, RFCOMM_UUID);
     384
     385                                sdp_list_free(proto_list, 0);
     386
     387                                //TODO: callback here + extract info's and stuff
     388                        }
     389                        sdp_record_free(rec);
     390                }
     391        }
     392        sdp_list_free(response_list, 0);
     393        sdp_list_free(search_list, 0);
     394        sdp_list_free(attrid_list, 0);
     395        sdp_close(session);
     396
     397}
     398
     399#endif // HAVE_BLUETOOTH_BLUETOOTH_H
     400
     401}
     402} //namespace ariba, utility
Note: See TracChangeset for help on using the changeset viewer.