BluetoothSDP.cc

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2006 Baylor University
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
00015  */
00016 
00017 #include <config.h>
00018 #ifdef OASYS_BLUETOOTH_ENABLED
00019 
00020 #include "io/IO.h"
00021 
00022 #include "Bluetooth.h"
00023 #include "BluetoothSDP.h"
00024 
00025 #include <errno.h>
00026 extern int errno;
00027 
00028 namespace oasys {
00029 
00030 BluetoothServiceDiscoveryClient::
00031 BluetoothServiceDiscoveryClient(const char* logpath) :
00032     Logger("BluetoothServiceDiscoveryClient",logpath)
00033 {
00034     Bluetooth::hci_get_bdaddr(&local_addr_);
00035     channel_ = 0;
00036 }
00037 
00038 BluetoothServiceDiscoveryClient::
00039 ~BluetoothServiceDiscoveryClient()
00040 {
00041 }
00042 
00043 bool
00044 BluetoothServiceDiscoveryClient::
00045 is_dtn_router(bdaddr_t remote)
00046 {
00047     // connect to the SDP server running on the remote machine
00048     sdp_session_t* sess =
00049         sdp_connect(&local_addr_, /* bind to specified local adapter */
00050                     &remote,
00051                     0); // formerly SDP_RETRY_IF_BUSY);
00052 
00053     if (!sess) {
00054         log_debug("Failed to connect to SDP server on %s: %s\n",
00055                   bd2str(remote),strerror(errno));
00056         return false;
00057     }
00058 
00059     // specify Universally Unique Identifier of service to query for
00060     const uint32_t svc_uuid_int[] = OASYS_BLUETOOTH_SDP_UUID;
00061     uuid_t svc_uuid;
00062 
00063     // hi-order (0x0000) specifies start of search range;
00064     // lo-order (0xffff) specifies end of range;
00065     // 0x0000ffff specifies a search of full range of attributes
00066     uint32_t range = 0x0000ffff;
00067 
00068     // specify UUID of the application we're searching for
00069     sdp_uuid128_create(&svc_uuid,&svc_uuid_int);
00070 
00071     // initialize the linked list with UUID to limit SDP
00072     // search scope on remote host
00073     sdp_list_t *search = sdp_list_append(NULL,&svc_uuid);
00074 
00075     // search all attributes by specifying full range
00076     sdp_list_t *attrid = sdp_list_append(NULL,&range);
00077 
00078     // list of service records returned by search request
00079     sdp_list_t *seq = NULL;
00080 
00081     // get a list of service records that have matching UUID
00082     int err = sdp_service_search_attr_req(
00083                         sess,                /* open session handle        */
00084                         search,              /* define the search (UUID)   */
00085                         SDP_ATTR_REQ_RANGE,  /* type of search             */
00086                         attrid,              /* search mask for attributes */
00087                         &seq);               /* linked list of responses   */
00088 
00089     // manage the malloc()'s flying around like crazy in BlueZ
00090     sdp_list_free(attrid,0);
00091     sdp_list_free(search,0);
00092 
00093     if (err != 0) {
00094         if(sess)
00095             sdp_close(sess);
00096         log_debug("Service Search failed: %s\n",
00097                   strerror(errno));
00098         return false;
00099     }
00100 
00101     int found = 0;
00102     // similar to bluez-utils-2.25/tools/sdptool.c:2896
00103     sdp_list_t *next;
00104     for (; seq; seq = next) {
00105 
00106         sdp_record_t *record = (sdp_record_t*) seq->data;
00107 
00108         // pull out name, desc, provider of this record
00109         sdp_data_t *d = sdp_data_get(record,SDP_ATTR_SVCNAME_PRIMARY);
00110         if(d)
00111             remote_eid_.assign(d->val.str,d->unitSize);
00112 
00113         // success returns 0
00114         sdp_list_t *proto; 
00115         if (sdp_get_access_protos(record,&proto) == 0) {
00116 
00117             sdp_list_t* next_proto;
00118             // iterate over the elements of proto_list
00119             // sdptool.c:1095 - sdp_list_foreach(proto, print_access_protos, 0);
00120             for (; proto; proto = next_proto) {
00121 
00122                 sdp_list_t* proto_desc = (sdp_list_t*) proto->data;
00123                 sdp_list_t* next_desc;
00124                 // sdptool.c:1061
00125                 // sdp_list_foreach(protDescSeq, print_service_desc, 0);
00126                 for (; proto_desc; proto_desc = next_desc) {
00127 
00128                     sdp_data_t *nextp, *p =
00129                         (sdp_data_t*) proto_desc->data;
00130 
00131                     int proto = 0;
00132 
00133                     for (; p; p = nextp) {
00134                         switch(p->dtd) {
00135                             case SDP_UUID16:
00136                             case SDP_UUID32:
00137                             case SDP_UUID128:
00138                                 proto = sdp_uuid_to_proto(
00139                                             &p->val.uuid);
00140                                 if (proto == RFCOMM_UUID) {
00141                                     found++;
00142                                 }
00143                                 break;
00144                             case SDP_UINT8:
00145                                 if (proto == RFCOMM_UUID)
00146                                     channel_ = p->val.uint8;
00147                                 break;
00148                             default:
00149                                 break;
00150                         } // switch
00151 
00152                         nextp = p->next;
00153 
00154                     } // p
00155 
00156                     // advance to next element
00157                     next_desc = proto_desc->next;
00158                     // free each element after visiting
00159                     //sdp_list_free(proto_desc,0);
00160 
00161                 } // proto_desc
00162 
00163                 next_proto = proto->next;
00164                 // free each element after visiting
00165                 //sdp_list_free(proto,0);
00166                 // advance to next element in linked list
00167                 proto = next_proto;
00168 
00169             } // proto
00170 
00171             next = seq->next;
00172             //free(seq);
00173             sdp_record_free(record);
00174 
00175         } else {
00176             // error, bail!
00177             next = 0;
00178             found = -1;
00179         } // sdp_get_access_protos
00180 
00181     } // for()
00182 
00183     sdp_close(sess);
00184     return (found>0);
00185 }
00186 
00187 BluetoothServiceRegistration::
00188 BluetoothServiceRegistration(const char* name,
00189                              const char* logpath) :
00190     Logger("BluetoothServiceRegistration",logpath),
00191     sess_(NULL)
00192 {
00193     Bluetooth::hci_get_bdaddr(&local_addr_);
00194     status_ = register_service(name);
00195 }
00196 
00197 BluetoothServiceRegistration::
00198 ~BluetoothServiceRegistration()
00199 {
00200     if (sess_) 
00201         sdp_close(sess_);
00202 }
00203 
00204 bool
00205 BluetoothServiceRegistration::
00206 register_service(const char *service_name)
00207 {
00208     uint32_t service_uuid_int[] = OASYS_BLUETOOTH_SDP_UUID;
00209     uint8_t rfcomm_channel = 10;
00210 
00211     uuid_t root_uuid,
00212            l2cap_uuid,
00213            rfcomm_uuid,
00214            svc_uuid;
00215     sdp_list_t *l2cap_list = 0,
00216                *rfcomm_list = 0,
00217                *root_list = 0,
00218                *proto_list = 0,
00219                *access_proto_list = 0;
00220     sdp_data_t *channel = 0;
00221     int err = 0;
00222 
00223     // memset(0) happens within sdp_record_alloc()
00224     sdp_record_t *record = sdp_record_alloc();
00225 
00226     // set the general service ID
00227     sdp_uuid128_create(&svc_uuid,&service_uuid_int);
00228     sdp_set_service_id(record,svc_uuid);
00229 
00230     // make the service record publicly browsable
00231     sdp_uuid16_create(&root_uuid,PUBLIC_BROWSE_GROUP);
00232     root_list = sdp_list_append(0,&root_uuid);
00233     sdp_set_browse_groups(record,root_list);
00234 
00235     // set l2cap information
00236     sdp_uuid16_create(&l2cap_uuid,L2CAP_UUID);
00237     l2cap_list = sdp_list_append(0,&l2cap_uuid);
00238     proto_list = sdp_list_append(0,l2cap_list);
00239 
00240     // set rfcomm information
00241     sdp_uuid16_create(&rfcomm_uuid,RFCOMM_UUID);
00242     channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel);
00243     rfcomm_list = sdp_list_append(0,&rfcomm_uuid);
00244     sdp_list_append(rfcomm_list, channel);
00245     sdp_list_append(proto_list,rfcomm_list);
00246 
00247     // attach protocol information to service record
00248     access_proto_list = sdp_list_append(0,proto_list);
00249     sdp_set_access_protos(record,access_proto_list);
00250 
00251     // set the name, provider, and description
00252     sdp_set_info_attr(record,service_name,0,0);
00253 
00254     // connect to the local SDP server, register the service record, and
00255     // disconnect
00256     sess_ = sdp_connect(&local_addr_, /* bind to specified adapter */
00257                         BDADDR_LOCAL, /* connect to local server */
00258                         SDP_RETRY_IF_BUSY);
00259     err = sdp_record_register(sess_,record,0);
00260 
00261     // cleanup
00262     sdp_data_free(channel);
00263     sdp_list_free(l2cap_list,0);
00264     sdp_list_free(rfcomm_list,0);
00265     sdp_list_free(root_list,0);
00266     sdp_list_free(proto_list,0);
00267     sdp_list_free(access_proto_list,0);
00268     sdp_record_free(record);
00269 
00270     return (err == 0);
00271 }
00272 
00273 } // namespace oasys
00274 #endif // OASYS_BLUETOOTH_ENABLED

Generated on Sat Sep 8 08:36:15 2007 for DTN Reference Implementation by  doxygen 1.5.3