Main Page | Class Hierarchy | Data Structures | File List | Data Fields | Globals

bluetoothcommunicator.cpp

Go to the documentation of this file.
00001 /*
00002  * bluetoothcommunicator.cpp,v 1.33 2003/11/25 19:29:56 mattid Exp
00003  *
00004  * COBAIN - Communications API for EPOC Environments
00005  * Copyright (C) 2002-2003 Matti Dahlbom, Matti Kokkola
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  * Contact: Matti Dahlbom <matti@777-team.org>
00022  *          Matti Kokkola <matti.kokkola@iki.fi>
00023  */
00024 
00025 #include <es_sock.h>
00026 #include <bt_sock.h>
00027 #include <btmanclient.h>
00028 
00029 #include "bluetoothcommunicator.h"
00030 #include "cobainserver.h"
00031 #include "serversession.h"
00032 #include "btdiscoverer.h"
00033 #include "concreteconnection.h"
00034 #include "Log.h"
00035 
00036 CBTCommunicator::CBTCommunicator(CServerSession *aSession)
00037     : iIsListening(EFalse),
00038       iListeningConnection(NULL)
00039 {
00040     iServerSession = aSession;
00041 }
00042 
00043 CBTCommunicator::~CBTCommunicator()
00044 {
00045     delete iDiscoverer;
00046 
00047     if( iIsListening ) {
00048         StopListeningL();
00049 
00050         // close service discovery related resources
00051         iSdpDB.Close();
00052         iSdpSession.Close();
00053     }
00054 
00055     // disconnect from socket server
00056     Log::Print(_L("closing socket server.."));
00057     iSocketServ.Close();
00058 }
00059 
00060 void CBTCommunicator::ConstructL()
00061 {
00062     // connect to the socket server
00063     iSocketServ.Connect();
00064 }
00065 
00066 CBTCommunicator * CBTCommunicator::NewL(CServerSession *aSession)
00067 {
00068     CBTCommunicator *c = new CBTCommunicator(aSession);
00069     CleanupStack::PushL(c);
00070     c->ConstructL();
00071     CleanupStack::Pop(); // c
00072 
00073     return c;
00074 }
00075 
00076 void CBTCommunicator::DiscoverPeersL(const RMessage &aMessage,
00077                                      CServerSession &aSession)
00078 {
00079 #ifdef __WINS__
00080 
00081     // foobar test code for emulator
00083 
00084     //jolla's btdevaddr
00085     TUint8 btaddr[] = { 0x00, 0x04, 0x61, 0x80, 0x2f, 0xfd };
00086     TBuf8<6> addrbuf;
00087     addrbuf.Copy(btaddr, 6);
00088     TUint8 sid[] = { 0x01, 0x02, 0x03, 0x04 };
00089 
00090     TPeerDataList *peers = new (ELeave) TPeerDataList();
00091     TPeerData *data = new TPeerData;
00092     data->iDeviceName = _L("device1");
00093     data->iDeviceAddress = addrbuf;
00094     data->iServiceID.Copy(sid, 4);
00095     data->iPort = 1;
00096     peers->Append(data);
00097     data = new TPeerData;
00098     data->iDeviceName = _L("device2");
00099     data->iDeviceAddress = addrbuf;
00100     data->iServiceID.Copy(sid, 4);
00101     data->iPort = 2;
00102     peers->Append(data);
00103     TInt size = 2;
00104 
00105     // set peerlist and complete call
00106     aSession.SetPeerList(peers);
00107     TBuf8<sizeof(TInt)> buf;
00108     buf.Copy((const TUint8 *)(&size), sizeof(TInt));
00109     aMessage.WriteL(aMessage.Ptr1(), buf);
00110     aMessage.Complete(KErrNone);
00111 #else
00112 
00113     // real discovery code for actual device
00115 
00116     if( iDiscoverer != NULL ) {
00117         delete iDiscoverer;
00118         iDiscoverer = NULL;
00119     }
00120 
00121     // start new discoverer
00122     iDiscoverer = CBTDiscoverer::NewL(aMessage, aSession);
00123     iDiscoverer->StartL(iSocketServ);
00124 
00125 #endif
00126 }
00127 
00128 // synchronously connects to the service
00129 RSocket* CBTCommunicator::ConnectL(TPeerData *aPeerData)
00130 {
00131     //Log::Print(_L("CBTCommunicator::ConnectL()"));
00132 
00133     RSocket *socket = new (ELeave) RSocket();
00134     CleanupStack::PushL(socket);
00135 
00136     /*
00137     User::LeaveIfError(socket->Open(iSocketServ,
00138                                     KBTAddrFamily,
00139                                     KSockStream,
00140                                     KRFCOMM));
00141 */
00142     //Log::Print(_L("calling socket->Open()"));
00143     User::LeaveIfError(socket->Open(iSocketServ,
00144                                     KBTAddrFamily,
00145                                     KSockSeqPacket, //KSockStream,
00146                                     KL2CAP));
00147 
00148     //Log::Print(_L("constructing remote address"));
00149 
00150     // construct the address to connect to
00151     TBTDevAddr devaddr(aPeerData->iDeviceAddress);
00152     TBTSockAddr address;
00153     address.SetBTAddr(devaddr);
00154     address.SetPort(aPeerData->iPort);
00155 
00156     //Log::Print(_L("calling socket->Connect()"));
00157 
00158     // connect the socket
00159     TRequestStatus status;
00160     socket->Connect(address, status);
00161     User::WaitForRequest(status);
00162 
00163     User::LeaveIfError(status.Int());    
00164 
00165     CleanupStack::Pop(); // socket
00166 
00167     //Log::Print(_L("CBTCommunicator::ConnectL() exiting.."));
00168 
00169     return socket;
00170 }
00171 
00172 // closes listening socket and stops advertising the service
00173 void CBTCommunicator::StopListeningL()
00174 {
00175     if( !iIsListening ) {
00176         return;
00177     }
00178 
00179     // delete listening connection entity 
00180     delete iListeningConnection;
00181     iListeningConnection = NULL;
00182 
00183     // stop advertising - nevermind errors
00184     TRAPD(err, iSdpDB.DeleteRecordL(iRecord));
00185     if( err != KErrNone ) {
00186         Log::Print(_L("StopListeningL(): err %d"), err);
00187     }
00188 
00189     iRecord = 0;
00190 
00191     iIsListening = EFalse;
00192 }
00193 
00194 void CBTCommunicator::StartAdvertisingL(TInt aPort,
00195                                         const TInt aServiceClassID,
00196                                         const TInt aApplicationID,
00197                                         const TDesC8 &aServiceName,
00198                                         const TDesC8 &aServiceDesc) 
00199 {
00200     //Log::Print(_L("StartAdvertisingL()"));
00201 
00202     // Connects to the SDP database
00203     User::LeaveIfError(iSdpSession.Connect());
00204     User::LeaveIfError(iSdpDB.Open(iSdpSession));
00205 
00206     // Creates the service record
00207     iSdpDB.CreateServiceRecordL(aServiceClassID, iRecord);
00208 
00209     // Defines the protocol that should be used to connect
00210     // with the advertised service
00211     CSdpAttrValueDES* protocolDescriptorList = CSdpAttrValueDES::NewDESL(NULL);
00212     CleanupStack::PushL(protocolDescriptorList);
00213 
00214     TBuf8<1> channel;
00215     channel.Append((TChar)aPort);
00216     /*
00217     protocolDescriptorList
00218     ->StartListL()   //  List of protocols required for this method
00219         ->BuildDESL()
00220         ->StartListL()
00221             ->BuildUUIDL(KL2CAP)
00222         ->EndListL()
00223     
00224         ->BuildDESL()
00225         ->StartListL()
00226             ->BuildUUIDL(KRFCOMM) 
00227             ->BuildUintL(channel)
00228         ->EndListL()
00229     ->EndListL();
00230 */
00231     protocolDescriptorList
00232     ->StartListL()   //  List of protocols required for this method
00233         ->BuildDESL()
00234         ->StartListL()
00235             ->BuildUUIDL(KL2CAP)
00236             ->BuildUintL(channel)
00237         ->EndListL()
00238     ->EndListL();
00239 
00240     iSdpDB.UpdateAttributeL(iRecord, 
00241                             KSdpAttrIdProtocolDescriptorList, 
00242                             *protocolDescriptorList);
00243 
00244     CleanupStack::PopAndDestroy(); // protocolDescriptorList
00245     
00246     // Defines the application ID
00247     iSdpDB.UpdateAttributeL(iRecord, 
00248                             KSdpAttrIdServiceID, 
00249                             aApplicationID);
00250 
00251     // Defines the service name
00252     CSdpAttrValueString *service_name =
00253         CSdpAttrValueString::NewStringL(aServiceName);
00254     CleanupStack::PushL(service_name);
00255     iSdpDB.UpdateAttributeL(iRecord, 
00256                 KSdpAttrIdBasePrimaryLanguage + 
00257                 KSdpAttrIdOffsetServiceName, 
00258                 *service_name);
00259     CleanupStack::PopAndDestroy(); // service_name
00260 
00261     // Add a description to the record
00262     CSdpAttrValueString *service_desc =
00263         CSdpAttrValueString::NewStringL(aServiceDesc);
00264     CleanupStack::PushL(service_desc);
00265     iSdpDB.UpdateAttributeL(iRecord, 
00266                 KSdpAttrIdBasePrimaryLanguage + 
00267                 KSdpAttrIdOffsetServiceDescription,
00268                 *service_desc);
00269     CleanupStack::PopAndDestroy(); // service_desc
00270 }
00271 
00272 //##TODO## find out what the hell is the meaning of the bits we are setting
00273 void CBTCommunicator::SetAvailabilityL(TBool aIsAvailable)
00274 {
00275     TUint state = aIsAvailable ? 0xff : 0x00;
00276 
00277     // set the service availability attribute field
00278     iSdpDB.UpdateAttributeL(iRecord, KSdpAttrIdServiceAvailability, state);
00279 
00280     // increase the record version
00281     iSdpDB.UpdateAttributeL(iRecord, KSdpAttrIdServiceRecordState, iRecordVersion++);
00282 }
00283 
00284 
00285 // called by StartListeningL(). returns port to listen to
00286 TInt CBTCommunicator::OpenListeningSocketL()
00287 {
00288     Log::Print(_L("OpenListeningSocketL()"));
00289 
00290     //Log::Print(_L("calling RSocket.Close()"));
00291 
00292     // close existing listening socket if open
00293     iListeningSocket.Close();
00294 
00295     //Log::Print(_L("deleting old connection"));
00296 
00297     // delete old connection entity if any
00298     delete iListeningConnection;
00299     iListeningConnection = NULL;
00300 
00301     // open socket 
00302     /*
00303     User::LeaveIfError(iListeningSocket.Open(iSocketServ,
00304                                              KBTAddrFamily,
00305                                              KSockStream,
00306                                              KRFCOMM));
00307 */
00308     //Log::Print(_L("calling RSocket.Open()"));
00309 
00310     User::LeaveIfError(iListeningSocket.Open(iSocketServ,
00311                                              KBTAddrFamily,
00312                                              KSockSeqPacket,//KSockStream,
00313                                              KL2CAP));
00314 
00315                                                 
00316     /*
00317     // acquire port (a.k.a. channel) to listen to
00318     TInt port;
00319     User::LeaveIfError(
00320         iListeningSocket.GetOpt(KRFCOMMGetAvailableServerChannel, 
00321                 KSolBtRFCOMM, port)
00322     );
00323 */
00324 //    //Log::Print(_L("calling RSocket.GetOpt()"));
00325 
00326     // select an arbitrary value for L2CAP PSM (must be odd) from range 0x1001..0xffff
00327     TInt port = 1;
00328 
00329     // create listening address
00330 //    TBTSockAddr listen_addr;
00331 //    TL2CAPSockAddr listen_addr;
00332 //    listen_addr.SetPort(port);
00333 
00334 
00335     // try port numbers until one is free
00336     TBool is_ok = EFalse;
00337 
00338     while(  !is_ok ) {
00339         //Log::Print(_L("trying port %d"), port);
00340         TInt ret = iListeningSocket.SetLocalPort(port);
00341         if( ret == KErrNone ) {
00342             // bound to the port - start to listen
00343             break;
00344         } else if( ret == KErrInUse ) {
00345             // try next port number
00346             port += 2;
00347         } else {
00348             // error - failed
00349             //Log::Print(_L("SetLocalPort() error: %d"), ret);
00350             User::Leave(ret);
00351         }
00352     }
00353 
00354     // bind socket and start to listen
00355 //    //Log::Print(_L("calling Bind()"));
00356 //    User::LeaveIfError(iListeningSocket.Bind(listen_addr));
00357     //Log::Print(_L("calling Listen()"));
00358     User::LeaveIfError(iListeningSocket.Listen(KListeningQueueSize));
00359 
00360     //Log::Print(_L("creating con entity"));
00361 
00362     // create new connection entity 
00363     iListeningConnection = CConcreteConnection::NewListeningL(&iListeningSocket,
00364                                                               &iSocketServ,
00365                                                               *iServerSession);
00366 
00367     return port;
00368 }
00369 
00370 void CBTCommunicator::SetChannelSecurityL(TInt aChannel)
00371 {
00372     RBTMan sec_manager;
00373     RBTSecuritySettings sec_session;
00374 
00375     //Log::Print(_L("SetChannelSecurityL(): channel: %d"), aChannel);
00376 
00377     // open security manager session
00378     User::LeaveIfError(sec_manager.Connect());
00379     CleanupClosePushL(sec_manager);
00380     User::LeaveIfError(sec_session.Open(sec_manager));
00381     CleanupClosePushL(sec_session);
00382 
00383     // define the security settings
00384     //TBTServiceSecurity sec_settings(KCobainServerUid3, KSolBtRFCOMM, 0);
00385     TBTServiceSecurity sec_settings(KCobainServerUid3, KSolBtL2CAP, 0);
00386     sec_settings.SetAuthentication(EFalse);
00387     sec_settings.SetEncryption(EFalse);
00388     sec_settings.SetAuthorisation(EFalse);
00389 
00390     // register the service
00391     sec_settings.SetChannelID(aChannel);
00392     TRequestStatus status;
00393     sec_session.RegisterService(sec_settings, status);
00394     User::WaitForRequest(status);
00395     User::LeaveIfError(status.Int());
00396 
00397     // cleanup
00398     CleanupStack::PopAndDestroy(); // sec_session
00399     CleanupStack::PopAndDestroy(); // sec_manager
00400 }
00401 
00402 // called by CServerSession::ListenL()
00403 CConcreteConnection* CBTCommunicator::StartListeningL(const TInt aServiceClassID,
00404                                                       const TInt aApplicationID,
00405                                                       const TDesC8 &aServiceName,
00406                                                       const TDesC8 &aServiceDesc) 
00407 {
00408     __ASSERT_ALWAYS(iListeningConnection == NULL, 
00409                     User::Panic(KBTCommPanic, KErrBTCommAlreadyListening));
00410 
00411     //Log::Print(_L("StartListeningL()"));    
00412 
00413     // open new listening socket 
00414     TInt port = -1;
00415     
00416     TRAPD(err, (port = OpenListeningSocketL()));
00417     if( err != KErrNone ) {
00418         //Log::Print(_L("OpenListeningSocketL() error: %d"), err);
00419         User::Panic(KBTCommPanic, KerrBTCommFailedToCreateListeningSocket);
00420     }
00421 
00422     // set channel security
00423     SetChannelSecurityL(port);
00424 
00425     // start advertising the service
00426     StartAdvertisingL(port, 
00427                       aServiceClassID, 
00428                       aApplicationID, 
00429                       aServiceName,
00430                       aServiceDesc);
00431 
00432     // make the service available
00433     SetAvailabilityL(ETrue);
00434 
00435     iIsListening = ETrue;
00436 
00437     return iListeningConnection;
00438 }
00439 
00440 
00441 
00442 

Generated on Mon Dec 8 10:26:06 2003 for CobainAPIImplementation by doxygen 1.3.5