|
1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Name : CBtService.cpp |
|
15 // Part of : ex_btsocket |
|
16 // Created : 17/11/2004 by Shane Kearns |
|
17 // Server "smart connector" class |
|
18 // Version : |
|
19 // |
|
20 // |
|
21 |
|
22 #include "cbtservice.h" |
|
23 |
|
24 /** |
|
25 Standard Symbian style 2 phase construction |
|
26 @param aServiceUUID a universally unique identifier for this application. |
|
27 @param aSdpSession a constructed sdp session owned by the application |
|
28 @param aSocketServer a constructed socket server session owned by the application |
|
29 @param aOwner the owning class which should receive notification of new connections |
|
30 @param aProtocol the protocol (RFCOMM or L2CAP) to register |
|
31 @param aSecurity optional security settings to use on the socket instead of system defaults |
|
32 */ |
|
33 EXPORT_C CBtService* CBtService::NewL(const TUUID& aServiceUUID, |
|
34 RSdp& aSdpSession, |
|
35 RSocketServ& aSocketServer, |
|
36 MConnectionObserver& aOwner, |
|
37 TUint aProtocol, |
|
38 const TBTServiceSecurity* aSecurity=NULL) |
|
39 { |
|
40 LOG_FN_TRACE((_L("+CBtService::NewL"))); |
|
41 __ASSERT_ALWAYS(aProtocol == KL2CAP || aProtocol == KRFCOMM, ExBtSocket::Panic(ExBtSocket::EUnsupportedProtocol)); |
|
42 CBtService* self = new(ELeave) CBtService(aSocketServer, aOwner, aProtocol); |
|
43 CleanupStack::PushL(self); |
|
44 self->ConstructL(aServiceUUID, aSdpSession, aSecurity); |
|
45 CleanupStack::Pop(self); |
|
46 LOG_FN_TRACE((_L("-CBtService::NewL"))); |
|
47 return self; |
|
48 } |
|
49 |
|
50 /** |
|
51 Standard 1st phase constructor, inialise member variables |
|
52 */ |
|
53 CBtService::CBtService(RSocketServ& aSocketServer, MConnectionObserver& aOwner, TUint aProtocol) : |
|
54 iSocketServer(aSocketServer), |
|
55 iOwner(aOwner), |
|
56 iProtocol(aProtocol) |
|
57 { |
|
58 } |
|
59 |
|
60 /** |
|
61 Standard 2nd phase constructor, perform initialisation which could leave |
|
62 */ |
|
63 void CBtService::ConstructL(const TUUID& aServiceUUID, RSdp& aSdpSession, const TBTServiceSecurity* aSecurity) |
|
64 { |
|
65 LOG_FN_TRACE((_L("+CBtService::ConstructL"))); |
|
66 |
|
67 //open handle so it is certain to be valid in the destructor |
|
68 iServiceRecord.Open(aSdpSession); |
|
69 |
|
70 //First, create a listening socket |
|
71 if(iProtocol == KL2CAP) |
|
72 { |
|
73 iAcceptorSocket = CBluetoothSocket::NewL(*this, iSocketServer, KSockSeqPacket, KL2CAP); |
|
74 //bind the socket to a port |
|
75 TL2CAPSockAddr addr; |
|
76 addr.SetPort(KL2CAPPassiveAutoBind); //allow the stack to choose a free port automatically |
|
77 if(aSecurity) |
|
78 { |
|
79 addr.SetSecurity(*aSecurity); //set security requirements, if present |
|
80 } |
|
81 User::LeaveIfError(iAcceptorSocket->Bind(addr)); |
|
82 } |
|
83 else if(iProtocol == KRFCOMM) |
|
84 { |
|
85 iAcceptorSocket = CBluetoothSocket::NewL(*this, iSocketServer, KSockStream, KRFCOMM); |
|
86 //bind the socket to a port |
|
87 TRfcommSockAddr addr; |
|
88 addr.SetPort(KRfcommPassiveAutoBind); //allow the stack to choose a free port automatically |
|
89 if(aSecurity) |
|
90 { |
|
91 addr.SetSecurity(*aSecurity); //set security requirements, if present |
|
92 } |
|
93 User::LeaveIfError(iAcceptorSocket->Bind(addr)); |
|
94 } |
|
95 User::LeaveIfError(iAcceptorSocket->Listen(1)); |
|
96 |
|
97 //Now, register in the SDP database |
|
98 TUint port = iAcceptorSocket->LocalPort(); //get the port chosen by the stack |
|
99 LOG_INFO((_L("Listening for connections on port %d"), port)); |
|
100 iServiceRecord.CreateServiceRecordL(aServiceUUID, iServiceRecordHandle); |
|
101 |
|
102 // Set attr 4 (protocol list) to L2CAP, and RFCOMM |
|
103 CSdpAttrValueDES *attrValDES; |
|
104 |
|
105 //This following code is doing these steps |
|
106 //1. create a DES (data element set) attribute |
|
107 //2. within that list, create a DES for each protocol, L2CAP and optionally RFCOMM |
|
108 //3. each protocol is a list of elements, the UUID of the protocol, and the port to connect to. |
|
109 //4. the service record is updated to include the new attribute |
|
110 //5. discard the attribute we built, as it has been copied to the SDP server |
|
111 attrValDES = CSdpAttrValueDES::NewDESL(NULL); |
|
112 CleanupStack::PushL(attrValDES); |
|
113 if(iProtocol == KL2CAP) |
|
114 { |
|
115 LOG_INFO((_L("Registering SDP PDL for L2CAP"))); |
|
116 //This code will register an L2CAP (datagram) service |
|
117 attrValDES |
|
118 ->StartListL() |
|
119 ->BuildDESL() |
|
120 ->StartListL() |
|
121 ->BuildUUIDL(TUUID(TUint16(KL2CAP))) // L2CAP |
|
122 ->BuildUintL(TSdpIntBuf<TUint16>(TUint16(port))) // The Protocol Service Multiplexor (port) for our service |
|
123 ->EndListL() |
|
124 ->EndListL(); |
|
125 } |
|
126 else if(iProtocol == KRFCOMM) |
|
127 { |
|
128 LOG_INFO((_L("Registering SDP PDL for RFCOMM"))); |
|
129 //This code will register an RFCOMM (stream) service |
|
130 attrValDES |
|
131 ->StartListL() |
|
132 ->BuildDESL() |
|
133 ->StartListL() |
|
134 ->BuildUUIDL(TUUID(TUint16(KL2CAP))) // L2CAP |
|
135 ->EndListL() |
|
136 ->BuildDESL() |
|
137 ->StartListL() |
|
138 ->BuildUUIDL(TUUID(TUint16(KRFCOMM))) // RFCOMM |
|
139 ->BuildUintL(TSdpIntBuf<TUint8>(TUint8(port))) |
|
140 ->EndListL() |
|
141 ->EndListL(); |
|
142 } |
|
143 iServiceRecord.UpdateAttributeL(iServiceRecordHandle, KSdpAttrIdProtocolDescriptorList, *attrValDES); |
|
144 CleanupStack::PopAndDestroy(attrValDES); |
|
145 attrValDES = NULL; |
|
146 LOG_FN_TRACE((_L("-CBtService::ConstructL"))); |
|
147 } |
|
148 |
|
149 EXPORT_C CBtService::~CBtService() |
|
150 { |
|
151 LOG_FN_TRACE((_L("+CBtService::~CBtService"))); |
|
152 //attempt to remove the SDP record |
|
153 TRAP_IGNORE(iServiceRecord.DeleteRecordL(iServiceRecordHandle)); |
|
154 iServiceRecord.Close(); |
|
155 delete iAcceptorSocket; |
|
156 LOG_FN_TRACE((_L("-CBtService::~CBtService"))); |
|
157 } |
|
158 |
|
159 /** |
|
160 Accept a new connection. |
|
161 When the incoming connection has been made, HandleAcceptCompleteL() will be called |
|
162 in this class. |
|
163 That function informs the owner by calling HandleNewConnection() or HandleConnectFailed() |
|
164 @param aBlankSocket an empty socket to receive the incoming connection. |
|
165 */ |
|
166 EXPORT_C void CBtService::AcceptConnection(CBluetoothSocket& aBlankSocket) |
|
167 { |
|
168 LOG_FN_TRACE((_L("+CBtService::AcceptConnection"))); |
|
169 __ASSERT_ALWAYS(iConnectionSocket == NULL, ExBtSocket::Panic(ExBtSocket::EReEntrant)); |
|
170 iConnectionSocket = &aBlankSocket; |
|
171 iAcceptorSocket->Accept(*iConnectionSocket); |
|
172 LOG_FN_TRACE((_L("-CBtService::AcceptConnection"))); |
|
173 } |
|
174 |
|
175 /** |
|
176 Callback from CBluetoothSocket when a new incoming connection is complete. |
|
177 Inform the owner |
|
178 */ |
|
179 void CBtService::HandleAcceptCompleteL(TInt aErr) |
|
180 { |
|
181 LOG_FN_TRACE((_L("+CBtService::HandleAcceptCompleteL"))); |
|
182 if(aErr == KErrNone) |
|
183 { |
|
184 iOwner.HandleNewConnection(iConnectionSocket); |
|
185 } |
|
186 else |
|
187 { |
|
188 iOwner.HandleConnectFailed(aErr); |
|
189 } |
|
190 iConnectionSocket = NULL; |
|
191 LOG_FN_TRACE((_L("-CBtService::HandleAcceptCompleteL"))); |
|
192 } |
|
193 |
|
194 /** |
|
195 This function is not used but must be implemented as it is pure virtual |
|
196 */ |
|
197 void CBtService::HandleConnectCompleteL(TInt /*aErr*/) |
|
198 { |
|
199 LOG_FN_TRACE((_L("+CBtService::HandleConnectCompleteL"))); |
|
200 ExBtSocket::Panic(ExBtSocket::EBadCallback); |
|
201 } |
|
202 |
|
203 /** |
|
204 This function is not used but must be implemented as it is pure virtual |
|
205 */ |
|
206 void CBtService::HandleShutdownCompleteL(TInt /*aErr*/) |
|
207 { |
|
208 LOG_FN_TRACE((_L("+CBtService::HandleShutdownCompleteL"))); |
|
209 ExBtSocket::Panic(ExBtSocket::EBadCallback); |
|
210 } |
|
211 |
|
212 /** |
|
213 This function is not used but must be implemented as it is pure virtual |
|
214 */ |
|
215 void CBtService::HandleSendCompleteL(TInt /*aErr*/) |
|
216 { |
|
217 LOG_FN_TRACE((_L("+CBtService::HandleSendCompleteL"))); |
|
218 ExBtSocket::Panic(ExBtSocket::EBadCallback); |
|
219 } |
|
220 |
|
221 /** |
|
222 This function is not used but must be implemented as it is pure virtual |
|
223 */ |
|
224 void CBtService::HandleReceiveCompleteL(TInt /*aErr*/) |
|
225 { |
|
226 LOG_FN_TRACE((_L("+CBtService::HandleReceiveCompleteL"))); |
|
227 ExBtSocket::Panic(ExBtSocket::EBadCallback); |
|
228 } |
|
229 |
|
230 /** |
|
231 This function is not used but must be implemented as it is pure virtual |
|
232 */ |
|
233 void CBtService::HandleIoctlCompleteL(TInt /*aErr*/) |
|
234 { |
|
235 LOG_FN_TRACE((_L("+CBtService::HandleIoctlCompleteL"))); |
|
236 ExBtSocket::Panic(ExBtSocket::EBadCallback); |
|
237 } |
|
238 |
|
239 /** |
|
240 This function is not used but must be implemented as it is pure virtual |
|
241 */ |
|
242 void CBtService::HandleActivateBasebandEventNotifierCompleteL(TInt /*aErr*/, TBTBasebandEventNotification& /*aEventNotification*/) |
|
243 { |
|
244 LOG_FN_TRACE((_L("+CBtService::HandleActivateBasebandEventNotifierCompleteL"))); |
|
245 ExBtSocket::Panic(ExBtSocket::EBadCallback); |
|
246 } |
|
247 |