BluetoothSDP.cc

Go to the documentation of this file.
00001 #include <config.h>
00002 #ifdef OASYS_BLUETOOTH_ENABLED
00003 
00004 #include <errno.h>
00005 #include <stdio.h>
00006 #include <stdlib.h>
00007 
00008 extern int errno;
00009 
00010 #include <sys/socket.h>
00011 #include <bluetooth/bluetooth.h>
00012 #include <bluetooth/hci.h>
00013 #include <bluetooth/rfcomm.h>
00014 
00015 #include "BluetoothSDP.h"
00016 //#include <debug/Logger.h>
00017 
00018 namespace oasys {
00019 
00020 BluetoothServiceDiscoveryClient::
00021 BluetoothServiceDiscoveryClient(const char* logpath) :
00022     Logger("BluetoothServiceDiscoveryClient",logpath),
00023     response_list_(NULL),
00024     session_handle_(NULL)
00025 {
00026     bacpy(&local_addr_,BDADDR_ANY);
00027 }
00028 
00029 BluetoothServiceDiscoveryClient::
00030 ~BluetoothServiceDiscoveryClient()
00031 {
00032     // terminate connection to remote service
00033     close();
00034 
00035     // clean up internal data structures
00036     if (response_list_) {
00037         delete response_list_;
00038         response_list_ = NULL;
00039     }
00040 }
00041 
00042 bool
00043 BluetoothServiceDiscoveryClient::
00044 connect()
00045 {
00046     if (session_handle_ != NULL) return true;
00047 
00048     // connect to the SDP server running on the remote machine
00049     session_handle_ = sdp_connect(
00050                         &local_addr_, /* bind to specified local adapter */
00051                         &remote_addr_,
00052                         SDP_RETRY_IF_BUSY);
00053 
00054     if ( ! session_handle_ ) {
00055         // could be a device that does not implement SDP
00056         log_debug("failed to connect to SDP server: %s (%d)\n",
00057                   strerror(errno), errno);
00058         return false;
00059     }
00060 
00061     return true;
00062 }
00063 
00064 bool
00065 BluetoothServiceDiscoveryClient::
00066 close()
00067 {
00068     if (session_handle_) {
00069         sdp_close(session_handle_);
00070         session_handle_ = NULL;
00071         return true;
00072     }
00073     return false;
00074 }
00075 
00076 sdp_list_t*
00077 BluetoothServiceDiscoveryClient::
00078 do_search() {
00079 
00080     // connect to SDP service on remote system
00081     if (connect()) {
00082 
00083         // specify Universally Unique Identifier of service to query for
00084         const uint32_t dtn_svc_uuid_int[] = OASYS_BLUETOOTH_SDP_UUID;
00085         uuid_t svc_uuid;
00086 
00087         // hi-order (0x0000) specifies start of search range;
00088         // lo-order (0xffff) specifies end of range;
00089         // 0x0000ffff specifies a search of full range of attributes
00090         uint32_t range = 0x0000ffff;
00091 
00092         // specify DTN's UUID, which is the application we're searching for
00093         sdp_uuid128_create(&svc_uuid,&dtn_svc_uuid_int);
00094 
00095         // initialize the linked list with DTN's UUID to limit SDP 
00096         // search scope on remote host
00097         sdp_list_t *search = sdp_list_append(NULL,&svc_uuid);
00098 
00099         // search all attributes by specifying full range
00100         sdp_list_t *attrid = sdp_list_append(NULL,&range);
00101 
00102         // list of service records returned by search request
00103         sdp_list_t *response_list;
00104 
00105         // get a list of service records that have matching UUID
00106         int err = sdp_service_search_attr_req(
00107                     session_handle_,     /* open session handle        */
00108                     search,              /* define the search (UUID)   */
00109                     SDP_ATTR_REQ_RANGE,  /* type of search             */
00110                     attrid,              /* search mask for attributes */      
00111                     &response_list);     /* linked list of responses   */
00112 
00113         // that's all that we do with this connection
00114         //close();
00115 
00116         // manage the malloc()'s flying around like crazy in BlueZ
00117         sdp_list_free(attrid,0);
00118         sdp_list_free(search,0);
00119 
00120         if (err != 0) {
00121             log_debug("problems with sdp search: %s (%d)\n",
00122                       strerror(errno),errno);
00123             return NULL;
00124         }
00125 
00126         return response_list;
00127     }
00128 
00129     // connect() already reported error
00130     return NULL;
00131 }
00132 
00133 sdp_record_t *
00134 BluetoothServiceDiscoveryClient::
00135 get_next_service_record()
00136 {
00137 
00138     // response_list_ points to the head of the linked list of records
00139     // if this is the first call, then connect and initiate the search
00140     if (response_list_ == NULL) {
00141         sdp_list_t* search = do_search();
00142         if (search == NULL) return NULL;
00143         response_list_ = new SDPListHead(search);
00144         //response_list_->set_free_func((sdp_free_func_t)sdp_record_free);
00145     }
00146 
00147     // Pull off the next record from the linked list
00148     if (sdp_list_t* record_elem = response_list_->next()) {
00149         // copy out the service record
00150         sdp_record_t *service_record = (sdp_record_t*) record_elem->data;
00151         return service_record;
00152     }
00153 
00154     // fell off the end of the linked list
00155 
00156     // reset data structs
00157     delete response_list_;
00158     response_list_ = NULL;
00159 
00160     // nothing to return
00161     return NULL;
00162 }
00163 
00164 bool
00165 BluetoothServiceDiscoveryClient::
00166 is_dtn_router(bdaddr_t addr)
00167 {
00168     bacpy(&remote_addr_,&addr);
00169     int is_dtn_host = 0;
00170 
00171     // walk through the service records on the remote host
00172     while (sdp_record_t *record = get_next_service_record()) {
00173 
00174         // fetch the list of protocol sequences
00175         sdp_list_t *proto_list;
00176 
00177         // success returns 0
00178         if (sdp_get_access_protos(record,&proto_list) == 0) {
00179 
00180             sdp_list_t* proto_seq_iter = proto_list;
00181             // Iterate over the elements of proto_seq_list
00182             // Each element's data pointer is a linked list of protocols
00183             while (proto_seq_iter) {
00184 
00185                 sdp_list_t* ps_list_iter = (sdp_list_t*)proto_seq_iter->data;
00186                 // Iterate over the elements of ps_list (via ps_list_head)
00187                 // Each element's data pointer is a linked list
00188                 // of type sdp_data_t* (attributes for each protocol)
00189                 while (ps_list_iter) {
00190 
00191                     sdp_data_t* attr_list_iter =
00192                         (sdp_data_t*) ps_list_iter->data;
00193                     int proto = 0;
00194 
00195                     while (attr_list_iter) {
00196 
00197                         switch( attr_list_iter->dtd ) {
00198                             case SDP_UUID16:
00199                             case SDP_UUID32:
00200                             case SDP_UUID128:
00201                                 proto = sdp_uuid_to_proto(
00202                                             &attr_list_iter->val.uuid);
00203                                 if (proto == RFCOMM_UUID) {
00204                                     is_dtn_host++;
00205                                 }
00206                                 break; 
00207                         } // switch
00208 
00209                         sdp_data_t* ali_next = attr_list_iter->next;
00210                         // free each element after visiting
00211                         sdp_data_free(attr_list_iter);
00212                         // advance to next element in linked list
00213                         attr_list_iter = ali_next;
00214 
00215                     } // attr_list_iter
00216 
00217                     sdp_list_t* pli_next = ps_list_iter->next;
00218                     // free each element after visiting
00219                     free(ps_list_iter);
00220                     // advance to next element in linked list
00221                     ps_list_iter = pli_next;
00222 
00223                 } // ps_list_iter
00224 
00225                 sdp_list_t* psi_next = proto_seq_iter->next;
00226                 // free each element after visiting
00227                 free(proto_seq_iter);
00228                 // advance to next element in linked list
00229                 proto_seq_iter = psi_next;
00230 
00231             } // proto_seq_iter 
00232         } else {
00233             log_debug("Failed to retrieve list of protocol sequences: "
00234                       "%s (%d)\n", strerror(errno),errno);
00235             return false;
00236         } // sdp_get_access_protos
00237 
00238     } // service record
00239  
00240     return (is_dtn_host > 0);
00241 }
00242 
00243 BluetoothServiceRegistration::
00244 BluetoothServiceRegistration(bdaddr_t* local, const char* logpath) :
00245     Logger("BluetoothServiceRegistration",logpath),
00246     session_handle_(NULL)
00247 {
00248     bacpy(&local_addr_,local);
00249     status_ = register_service();
00250 }
00251 
00252 BluetoothServiceRegistration::
00253 ~BluetoothServiceRegistration()
00254 {
00255     if (session_handle_) 
00256         sdp_close(session_handle_);
00257 }
00258 
00259 bool
00260 BluetoothServiceRegistration::
00261 register_service()
00262 {
00263     uint32_t service_uuid_int[] = OASYS_BLUETOOTH_SDP_UUID;
00264     const char *service_name    = OASYS_BLUETOOTH_SDP_NAME;
00265     const char *service_dsc     = OASYS_BLUETOOTH_SDP_DESC;
00266     const char *service_prov    = OASYS_BLUETOOTH_SDP_PROV;
00267 
00268     uuid_t root_uuid,
00269            l2cap_uuid,
00270            rfcomm_uuid,
00271            svc_uuid;
00272     sdp_list_t *l2cap_list = 0,
00273                *rfcomm_list = 0,
00274                *root_list = 0,
00275                *proto_list = 0,
00276                *access_proto_list = 0;
00277     int err = 0;
00278 
00279     sdp_record_t *record = sdp_record_alloc();
00280 
00281     // set the general service ID
00282     sdp_uuid128_create(&svc_uuid,&service_uuid_int);
00283     sdp_set_service_id(record,svc_uuid);
00284 
00285     // make the service record publicly browsable
00286     sdp_uuid16_create(&root_uuid,PUBLIC_BROWSE_GROUP);
00287     root_list = sdp_list_append(0,&root_uuid);
00288     sdp_set_browse_groups(record,root_list);
00289 
00290     // set l2cap information
00291     sdp_uuid16_create(&l2cap_uuid,L2CAP_UUID);
00292     l2cap_list = sdp_list_append(0,&l2cap_uuid);
00293     proto_list = sdp_list_append(0,l2cap_list);
00294 
00295     // set rfcomm information
00296     sdp_uuid16_create(&rfcomm_uuid,RFCOMM_UUID);
00297     rfcomm_list = sdp_list_append(0,&rfcomm_uuid);
00298     sdp_list_append(proto_list,rfcomm_list);
00299 
00300     // attach protocol information to service record
00301     access_proto_list = sdp_list_append(0,proto_list);
00302     sdp_set_access_protos(record,access_proto_list);
00303 
00304     // set the name, provider, and description
00305     sdp_set_info_attr(record,service_name,service_prov,service_dsc);
00306 
00307     // connect to the local SDP server, register the service record, and
00308     // disconnect
00309     session_handle_ = sdp_connect(
00310                         &local_addr_, /* bind to specified adapter */
00311                         BDADDR_LOCAL, /* connect to local server */
00312                         SDP_RETRY_IF_BUSY);
00313     err = sdp_record_register(session_handle_,record,0);
00314 
00315     // cleanup
00316     sdp_list_free(l2cap_list,0);
00317     sdp_list_free(rfcomm_list,0);
00318     sdp_list_free(root_list,0);
00319     sdp_list_free(proto_list,0);
00320     sdp_list_free(access_proto_list,0);
00321     sdp_record_free(record);
00322 
00323     return (err == 0);
00324 }
00325 
00326 } // namespace oasys
00327 #endif // OASYS_BLUETOOTH_ENABLED

Generated on Fri Dec 22 14:47:57 2006 for DTN Reference Implementation by  doxygen 1.5.1