SYSCALL(MAHandle, maConnect(const char* url)) { TPtrC8 urlP(CBP url, SYSCALL_THIS->ValidatedStrLen(url)); LOGST("Connect %i %s", gConnNextHandle, url); if(gConnections.size() >= CONN_MAX) return CONNERR_MAX; _LIT8(KLocalhost, "localhost"); CConnection* conn = NULL; TPtrC8 match; SocketType socketType = TCP; // initialized to placate stupid compiler ConnectionType type; // determine type of connection if(SSTREQ(urlP, KSocket)) { match.Set(KSocket); type = eSocket; socketType = TCP; } else if(SSTREQ(urlP, KDatagram)) { match.Set(KDatagram); type = eSocket; socketType = UDP; } else if(SSTREQ(urlP, KSsl)) { match.Set(KSsl); type = eSocket; socketType = SSL; } else if(SSTREQ(urlP, KHttp)) { match.Set(KHttp); type = eHttp; socketType = TCP; } else if(SSTREQ(urlP, KHttps)) { match.Set(KHttps); type = eHttp; socketType = SSL; } else if(SSTREQ(urlP, KBtspp)) { match.Set(KBtspp); type = eBtspp; } else { //error return CONNERR_URL; } TPtrC8 parturl = urlP.Mid(match.Length()); if(type == eSocket) { TPtrC8 hostnamePtrC8; int port; if(!splitPurl(parturl, hostnamePtrC8, port, (1<<16))) { return CONNERR_URL; } Smartie<CSocket> sockp(createSocket(socketType)); _LIT8(K127, "127."); TInetAddr addr; bool localhost = false; if(hostnamePtrC8 == KLocalhost) { localhost = true; addr.SetAddress(INET_ADDR(127,0,0,1)); } else if(hostnamePtrC8.Length() > K127().Length()) { if(hostnamePtrC8.Left(K127().Length()) == K127) { localhost = true; Smartie<HBufC16> hostname(CreateHBufC16FromDesC8LC(hostnamePtrC8)); addr.Input(*hostname()); } } sockp->state |= CONNOP_CONNECT; if(localhost) { StartConnOpL(CO_AddrConnect::NewL(false, *this, gConnNextHandle, *sockp(), addr, port, *sockp())); } else { Smartie<HBufC16> hostname(CreateHBufC16FromDesC8LC(hostnamePtrC8)); CleanupStack::Pop(hostname()); StartConnOpL(CO_NameConnect::NewL(gNetworkingState != EStarted, *this, gConnNextHandle, *sockp(), hostname, port, *sockp())); } conn = sockp.extract(); } else if(type == eHttp) { CHttpConnection* http; TLTZ_PASS(httpCreateConnectionLC(parturl, http, HTTP_GET, socketType)); http->state |= CONNOP_CONNECT; StartConnOpL(CO_HttpFinish::NewL(gNetworkingState != EStarted, *this, gConnNextHandle, *http, *http, true)); http->mState = CHttpConnection::WRITING; conn = http; CleanupStack::Pop(conn); } else if(type == eBtspp) { if(gBtState != eAvailable) { return CONNERR_UNAVAILABLE; } TPtrC8 hostnamePtrC8; int port_m1_index = parturl.Locate(':'); if(port_m1_index == KErrNotFound) { return false; } hostnamePtrC8.Set(parturl.Left(port_m1_index)); if(hostnamePtrC8 == KLocalhost) { // server // extract and parse uuid static const int KUuidLength = 32; int uuidStartIndex = port_m1_index + 1; int paramStartIndex = uuidStartIndex + KUuidLength; if(parturl.Length() < paramStartIndex) { return CONNERR_URL; } TPtrC8 uuidPtrC8(parturl.Mid(uuidStartIndex, KUuidLength)); TUint32 us[4]; for(int i=0; i<4; i++) { TPtrC8 p(uuidPtrC8.Mid(i*8, 8)); for(int j=0; j<8; j++) { if(!TChar(p[j]).IsHexDigit()) return CONNERR_URL; } LHEL(TLex8(p).Val(us[i], EHex)); } TUUID uuid(us[0], us[1], us[2], us[3]); //TUUID uuid(KSerialPortUUID); //temp hack // create listener socket Smartie<CBtServerSocket> sockp(new (ELeave) CBtServerSocket(gBtSdpDB)); // extract name, if it's there. initialize the socket. TPtrC8 paramPtrC8(parturl.Mid(paramStartIndex)); _LIT8(KNameParam, ";name="); if(SSTREQ(paramPtrC8, KNameParam)) { TPtrC8 namePtrC8(paramPtrC8.Mid(KNameParam().Length())); sockp->init(gSocketServ, uuid, true, namePtrC8); } else if(paramPtrC8.Length() == 0) { sockp->init(gSocketServ, uuid, false); } else { return CONNERR_URL; } //skip the async/connect step gConnections.insert(gConnNextHandle, sockp.extract()); return gConnNextHandle++; } else { // client // extract port number int port; if(!splitPurl(parturl, hostnamePtrC8, port, 31)) { return CONNERR_URL; } TRfcommSockAddr rfcsa; // parse address TBTDevAddr btaddr; for(int i=0; i<BTADDR_LEN; i++) { TLex8 btaLex(parturl.Mid(i*2, 2)); int result = btaLex.Val(btaddr[i], EHex); if(result != KErrNone) return CONNERR_URL; } rfcsa.SetBTAddr(btaddr); // create socket Smartie<CSocket> sockp(new (ELeave) CSocket(gSocketServ, CSocket::ERfcomm)); sockp->state |= CONNOP_CONNECT; StartConnOpL(CO_AddrConnect::NewL(false, *this, gConnNextHandle, *sockp(), rfcsa, port, *sockp())); conn = sockp.extract(); } } CleanupStack::PushL(conn); gConnections.insert(gConnNextHandle, conn); CleanupStack::Pop(conn); return gConnNextHandle++; }
/** Standard 2nd phase constructor, perform initialisation which could leave */ void CBtService::ConstructL(const TUUID& aServiceUUID, RSdp& aSdpSession, const TBTServiceSecurity* aSecurity) { LOG_FN_TRACE((_L("+CBtService::ConstructL"))); //open handle so it is certain to be valid in the destructor iServiceRecord.Open(aSdpSession); //First, create a listening socket if(iProtocol == KL2CAP) { iAcceptorSocket = CBluetoothSocket::NewL(*this, iSocketServer, KSockSeqPacket, KL2CAP); //bind the socket to a port TL2CAPSockAddr addr; addr.SetPort(KL2CAPPassiveAutoBind); //allow the stack to choose a free port automatically if(aSecurity) { addr.SetSecurity(*aSecurity); //set security requirements, if present } User::LeaveIfError(iAcceptorSocket->Bind(addr)); } else if(iProtocol == KRFCOMM) { iAcceptorSocket = CBluetoothSocket::NewL(*this, iSocketServer, KSockStream, KRFCOMM); //bind the socket to a port TRfcommSockAddr addr; addr.SetPort(KRfcommPassiveAutoBind); //allow the stack to choose a free port automatically if(aSecurity) { addr.SetSecurity(*aSecurity); //set security requirements, if present } User::LeaveIfError(iAcceptorSocket->Bind(addr)); } User::LeaveIfError(iAcceptorSocket->Listen(1)); //Now, register in the SDP database TUint port = iAcceptorSocket->LocalPort(); //get the port chosen by the stack LOG_INFO((_L("Listening for connections on port %d"), port)); iServiceRecord.CreateServiceRecordL(aServiceUUID, iServiceRecordHandle); // Set attr 4 (protocol list) to L2CAP, and RFCOMM CSdpAttrValueDES *attrValDES; //This following code is doing these steps //1. create a DES (data element set) attribute //2. within that list, create a DES for each protocol, L2CAP and optionally RFCOMM //3. each protocol is a list of elements, the UUID of the protocol, and the port to connect to. //4. the service record is updated to include the new attribute //5. discard the attribute we built, as it has been copied to the SDP server attrValDES = CSdpAttrValueDES::NewDESL(NULL); CleanupStack::PushL(attrValDES); if(iProtocol == KL2CAP) { LOG_INFO((_L("Registering SDP PDL for L2CAP"))); //This code will register an L2CAP (datagram) service attrValDES ->StartListL() ->BuildDESL() ->StartListL() ->BuildUUIDL(TUUID(TUint16(KL2CAP))) // L2CAP ->BuildUintL(TSdpIntBuf<TUint16>(TUint16(port))) // The Protocol Service Multiplexor (port) for our service ->EndListL() ->EndListL(); } else if(iProtocol == KRFCOMM) { LOG_INFO((_L("Registering SDP PDL for RFCOMM"))); //This code will register an RFCOMM (stream) service attrValDES ->StartListL() ->BuildDESL() ->StartListL() ->BuildUUIDL(TUUID(TUint16(KL2CAP))) // L2CAP ->EndListL() ->BuildDESL() ->StartListL() ->BuildUUIDL(TUUID(TUint16(KRFCOMM))) // RFCOMM ->BuildUintL(TSdpIntBuf<TUint8>(TUint8(port))) ->EndListL() ->EndListL(); } iServiceRecord.UpdateAttributeL(iServiceRecordHandle, KSdpAttrIdProtocolDescriptorList, *attrValDES); CleanupStack::PopAndDestroy(attrValDES); attrValDES = NULL; LOG_FN_TRACE((_L("-CBtService::ConstructL"))); }
bool QRfcommServer::listen(const QBluetoothAddress &address, quint16 port) { Q_D(QRfcommServer); // listen has already been called before if(d->socket) return true; d->socket = new QBluetoothSocket(QBluetoothSocket::RfcommSocket,this); if(!d->socket) { return false; } d->ds = d->socket->d_ptr; if(!d->ds) { delete d->socket; d->socket = 0; return false; } d->ds->ensureNativeSocket(QBluetoothSocket::RfcommSocket); TRfcommSockAddr addr; if(!address.isNull()) { // TBTDevAddr constructor may panic TRAPD(err,addr.SetBTAddr(TBTDevAddr(address.toUInt64()))); if(err != KErrNone) { delete d->socket; d->socket = 0; return false; } } if (port == 0) addr.SetPort(KRfcommPassiveAutoBind); else addr.SetPort(port); TBTServiceSecurity security; switch (d->securityFlags) { case QBluetooth::Authentication: security.SetAuthentication(EMitmDesired); break; case QBluetooth::Authorization: security.SetAuthorisation(ETrue); break; case QBluetooth::Encryption: // "Secure" is BlueZ specific we just make sure the code remain compatible case QBluetooth::Secure: // authentication required security.SetAuthentication(EMitmDesired); security.SetEncryption(ETrue); break; case QBluetooth::NoSecurity: default: break; } if(d->ds->iSocket->Bind(addr) == KErrNone) { d->socket->setSocketState(QBluetoothSocket::BoundState); } else { delete d->socket; d->socket = 0; return false; } if(d->ds->iSocket->Listen(d->maxPendingConnections) != KErrNone) { delete d->socket; d->socket = 0; return false; } QBluetoothSocket *pendingSocket = new QBluetoothSocket(QBluetoothSocket::UnknownSocketType, this); if(!pendingSocket) { delete d->socket; d->socket = 0; return false; } QBluetoothSocketPrivate *pd = pendingSocket->d_ptr; pd->ensureBlankNativeSocket(QBluetoothSocket::RfcommSocket); connect(d->socket, SIGNAL(disconnected()), this, SLOT(_q_disconnected())); connect(d->socket, SIGNAL(connected()), this, SLOT(_q_connected())); connect(d->socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(_q_socketError(QBluetoothSocket::SocketError))); if (d->ds->iSocket->Accept(*pd->iSocket) == KErrNone) { d->socket->setSocketState(QBluetoothSocket::ListeningState); d->activeSockets.append(pendingSocket); return true; } else { delete d->socket, pendingSocket; d->socket = 0; return false; } }
TInt CStatTransportBT::StartSocketL() { TUint error; //make sure we are in the correct state asserte( iBTTransportStatus == EConnectingRegisterMgr ); // connect to the socket server (as we are the receiver and not the initiator), create a socket, bind, listen, accept User::LeaveIfError( iSocketServ.Connect() ); //now select the protocol to use (RFCOMM (serial emulation - boo. Problems with demultiplexing if 1 generic serial port is used for multiple BT connections) or L2CAP) TProtocolDesc pInfo; User::LeaveIfError( iSocketServ.FindProtocol(_L("RFCOMM"),pInfo ) ); //open the listener socket User::LeaveIfError( iListenSocket.Open(iSocketServ, pInfo.iAddrFamily, pInfo.iSockType, pInfo.iProtocol) ); // RFComm Socket TRfcommSockAddr addr; // Get First available server channel addr.SetPort(KRfcommPassiveAutoBind); // Set the service security //Set user defined EPOC TUid to internally represent the service iServiceSecurity.SetUid( TUid::Uid( 0x1234 ) ); //Define security requirements iServiceSecurity.SetAuthentication( EFalse ); iServiceSecurity.SetEncryption( EFalse ); iServiceSecurity.SetAuthorisation( EFalse ); addr.SetSecurity(iServiceSecurity); //bind User::LeaveIfError( iListenSocket.Bind( addr ) ); // Get the assigned port iPort=iListenSocket.LocalPort(); // register with the SDP database error = RegWithSDPDatabaseL(); if( error != KSTErrSuccess ) { iTransport->HandleError( error, (void*)iStatus.Int() ); return KSTErrGeneralFailure; } //listen User::LeaveIfError( iListenSocket.Listen( KLittleStatBTListenQueue ) ); // create a blank socket which is used as the data socket User::LeaveIfError( iDataSocket.Open(iSocketServ) ); // everything should now be set up, we just wait for a stat connection asserte( !IsActive() ); iListenSocket.Accept( iDataSocket, iStatus ); SetActive(); return KSTErrSuccess; }