|
1 // Copyright (c) 2000-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 // Implements the SDP Protocol object |
|
15 // |
|
16 // |
|
17 |
|
18 #include <bluetooth/logger.h> |
|
19 #include <bt_sock.h> |
|
20 #include <btsdp.h> |
|
21 #include "sdp.h" |
|
22 #include "sdpclient.h" |
|
23 #include "sdpnetdb.h" |
|
24 #include "sdpstackutil.h" |
|
25 #include "sdpconsts.h" |
|
26 #include "bt.h" |
|
27 |
|
28 #ifdef __FLOG_ACTIVE |
|
29 _LIT8(KLogComponent, LOG_COMPONENT_SDP); |
|
30 #endif |
|
31 |
|
32 CSdpProtocol::CSdpProtocol(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan) |
|
33 :CBluetoothProtocolBase(aSecMan, aControlPlane, aCodMan), |
|
34 iClients(_FOFF(CSdpClient, iLink)) |
|
35 /** |
|
36 Protocol Constructor. |
|
37 **/ |
|
38 { |
|
39 LOG_FUNC |
|
40 } |
|
41 |
|
42 CSdpProtocol::~CSdpProtocol() |
|
43 /** |
|
44 Protocol Destructor. |
|
45 We only clean up the signallers as the NetDbProviders are owned by ESOCK and |
|
46 it is up to it to destroy them. |
|
47 **/ |
|
48 { |
|
49 LOG_FUNC |
|
50 while(!iClients.IsEmpty()) |
|
51 { |
|
52 CSdpClient* c = iClients.First(); |
|
53 c->iLink.Deque(); |
|
54 delete c; |
|
55 } |
|
56 if(iLowerProtocol) |
|
57 iLowerProtocol->Close(); // Matches the bind |
|
58 #ifdef __FLOG_ACTIVE |
|
59 CLOSE_LOGGER |
|
60 #endif |
|
61 } |
|
62 |
|
63 CSdpProtocol* CSdpProtocol::NewL(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan) |
|
64 { |
|
65 #ifdef __FLOG_ACTIVE |
|
66 CONNECT_LOGGER |
|
67 #endif |
|
68 LOG_STATIC_FUNC |
|
69 CSdpProtocol* i=new (ELeave) CSdpProtocol(aSecMan, aControlPlane, aCodMan); |
|
70 return i; |
|
71 } |
|
72 |
|
73 void CSdpProtocol::InitL(TDesC& /*aTag*/) |
|
74 /** |
|
75 Pre-binding initialise. |
|
76 Alloc any stuff we need. |
|
77 |
|
78 This will only ever be called once during the lifetime of this |
|
79 protocol. |
|
80 **/ |
|
81 { |
|
82 LOG_FUNC |
|
83 // ...nothing required! |
|
84 } |
|
85 |
|
86 void CSdpProtocol::StartL() |
|
87 /** |
|
88 Binding complete. |
|
89 **/ |
|
90 { |
|
91 LOG_FUNC |
|
92 // Should check that we're bound now. |
|
93 __ASSERT_ALWAYS(iLowerProtocol,Panic(ESdpNotBound)); |
|
94 } |
|
95 |
|
96 |
|
97 void CSdpProtocol::BindToL(CProtocolBase* aProtocol) |
|
98 /*** |
|
99 Request by Protocol Mgr to bind to the specified protocol. |
|
100 We can only be bound to one lower layer protocol, so the function panics |
|
101 if we are already bound. |
|
102 @param aProtocol The protocol we need to bind to. |
|
103 **/ |
|
104 { |
|
105 LOG_FUNC |
|
106 FTRACE(TBuf<255> tmp(aProtocol->Tag()); |
|
107 LOG1(_L("CSdpProtocol::BindToL binding to %S"), |
|
108 &tmp)); |
|
109 |
|
110 if(!iLowerProtocol) |
|
111 { |
|
112 #ifdef _DEBUG |
|
113 TServerProtocolDesc prtDesc; |
|
114 aProtocol->Identify(&prtDesc); |
|
115 |
|
116 if(prtDesc.iAddrFamily!=KBTAddrFamily || |
|
117 prtDesc.iProtocol!=KL2CAP) |
|
118 { |
|
119 User::Leave(KErrBtEskError); |
|
120 } |
|
121 #endif |
|
122 |
|
123 iLowerProtocol=static_cast<CBluetoothProtocolBase*>(aProtocol); |
|
124 iLowerProtocol->BindL(this, KSDPPSM); |
|
125 iLowerProtocol->Open(); |
|
126 } |
|
127 else |
|
128 { |
|
129 User::Leave(KErrSdpAlreadyBound); |
|
130 } |
|
131 } |
|
132 |
|
133 // Factory functions |
|
134 |
|
135 CNetDBProvdBase* CSdpProtocol::NewNetDatabaseL() |
|
136 /** |
|
137 Create a new NetDbProvider. |
|
138 The NetDbProvider returned is owned by the caller -- this protocol will |
|
139 not clean it up. esock uses this function to create a new NetDbProvider, |
|
140 and esock will delete when it is finished with it. |
|
141 **/ |
|
142 { |
|
143 LOG_FUNC |
|
144 return CSdpNetDbProvider::NewL(*this); |
|
145 } |
|
146 |
|
147 // Query functions |
|
148 |
|
149 void CSdpProtocol::Identify(TServerProtocolDesc *aDesc)const |
|
150 /** |
|
151 Identify request from SOCKET server |
|
152 **/ |
|
153 { |
|
154 LOG_FUNC |
|
155 ProtocolIdentity(aDesc); |
|
156 } |
|
157 |
|
158 void CSdpProtocol::ProtocolIdentity(TServerProtocolDesc* aDesc) |
|
159 { |
|
160 LOG_STATIC_FUNC |
|
161 _LIT(name,"SDP"); |
|
162 aDesc->iProtocol=KSDP; |
|
163 |
|
164 aDesc->iName=name; |
|
165 aDesc->iAddrFamily=KBTAddrFamily; |
|
166 aDesc->iSockType=1; // Bogus... but (debug) esock demands non-zero here. |
|
167 |
|
168 aDesc->iVersion=TVersion(KBTMajor,KBTMinor,KBTBuild); |
|
169 aDesc->iByteOrder=EBigEndian; |
|
170 aDesc->iServiceInfo=0; |
|
171 aDesc->iNamingServices=KNSInfoDatabase; |
|
172 aDesc->iSecurity=0; |
|
173 aDesc->iMessageSize=KSocketMessageSizeUndefined; |
|
174 aDesc->iServiceTypeInfo=ECantProcessMBufChains; |
|
175 aDesc->iNumSockets=1;// Bogus... but (debug) esock demands non-zero here. |
|
176 } |
|
177 |
|
178 void CSdpProtocol::CloseNow() |
|
179 /** |
|
180 Our reference is now zero, so start to close. |
|
181 When SDP server is in place, this'll be far more involved, as we'll |
|
182 want to hang around to service SDP queries, for some (???) length |
|
183 of time. |
|
184 In the mean time, we can just close, as there are now no netdbs left, so |
|
185 even if any SDP clients are still hanging around, they may as well die. |
|
186 **/ |
|
187 { |
|
188 LOG_FUNC |
|
189 iClosePending = ETrue; |
|
190 TryToClose(); |
|
191 } |
|
192 |
|
193 void CSdpProtocol::Open() |
|
194 /** |
|
195 Request to open the protocol. |
|
196 The protocol may be repeatedly opened and closed. The order of calls is |
|
197 InitL, [Open *n , Close * n, CloseNow] * m, CanClose(upcall) etc. |
|
198 **/ |
|
199 { |
|
200 LOG_FUNC |
|
201 iClosePending = EFalse; |
|
202 CProtocolBase::Open(); |
|
203 } |
|
204 |
|
205 void CSdpProtocol::Close() |
|
206 /** |
|
207 This is one session closing. |
|
208 Just call default, which decs the ref count. |
|
209 CloseNow will be called when this hits 0. |
|
210 **/ |
|
211 { |
|
212 LOG_FUNC |
|
213 CProtocolBase::Close(); |
|
214 } |
|
215 |
|
216 void CSdpProtocol::TryToClose() |
|
217 { |
|
218 LOG_FUNC |
|
219 if (iClosePending && iClients.IsEmpty()) |
|
220 CanClose(); // delete's us! |
|
221 } |
|
222 |
|
223 void CSdpProtocol::GetClient(CSdpNetDbProvider& aNetDbProvider) |
|
224 /** |
|
225 Find a Client for this NetDbProvider. |
|
226 |
|
227 When a Client is found, the NetDbProvider is notified via the ClientUp() call. |
|
228 Note that if there is no existing Client then it will be created |
|
229 here and the link brought up before the ClientUp() call is made. This implies |
|
230 that the ClientUp() call on the NetDbProvider can be synchronous or Asynchronous. |
|
231 |
|
232 @param aNetDbProvider The NetDbProvider that needs a Client. |
|
233 **/ |
|
234 { |
|
235 LOG_FUNC |
|
236 CSdpClient* client; |
|
237 TBool needsL2CAPChannel = EFalse; |
|
238 |
|
239 client=FindClient(aNetDbProvider.iRemoteDev); |
|
240 if(!client) |
|
241 {// Need to create one |
|
242 needsL2CAPChannel = ETrue; |
|
243 TRAPD(err, client=CSdpClient::NewL(*this, *iLowerProtocol)); |
|
244 if(err != KErrNone) |
|
245 { |
|
246 // Can't create a client, so error the NetDbProvider |
|
247 aNetDbProvider.Error(err); |
|
248 return; |
|
249 } |
|
250 // Add client to the Q |
|
251 iClients.AddFirst(*client); |
|
252 } |
|
253 // Take NetDb off the idle Q |
|
254 |
|
255 // and add it to the client |
|
256 aNetDbProvider.iClient=client; |
|
257 client->AddNetDbProvider(aNetDbProvider); |
|
258 |
|
259 // Bring up the client if needed |
|
260 if (needsL2CAPChannel) |
|
261 client->Open(aNetDbProvider.iRemoteDev); // Will call back through ClientUp() |
|
262 } |
|
263 |
|
264 CSdpClient* CSdpProtocol::FindClient(const TBTDevAddr& aAddr) |
|
265 /** |
|
266 Find the existing client for this address. |
|
267 @return Pointer to a client for this address, or NULL if it doesn't exist. |
|
268 **/ |
|
269 { |
|
270 LOG_FUNC |
|
271 TDblQueIter<CSdpClient> iter(iClients); |
|
272 CSdpClient* client; |
|
273 |
|
274 while(iter) |
|
275 { |
|
276 client=iter++; |
|
277 if(client->iRemoteAddr == aAddr) |
|
278 { |
|
279 // We have a client, so return it |
|
280 return client; |
|
281 } |
|
282 } |
|
283 // No client |
|
284 return 0; |
|
285 } |
|
286 |
|
287 void CSdpProtocol::ClientDown(CSdpClient& aClient) |
|
288 { |
|
289 LOG_FUNC |
|
290 aClient.iLink.Deque(); |
|
291 delete &aClient; |
|
292 TryToClose(); |
|
293 } |
|
294 |
|
295 TInt CSdpProtocol::BearerConnectComplete(const TBTDevAddr& /*aAddr*/, CServProviderBase* /*aSSP*/) |
|
296 { |
|
297 LOG_FUNC |
|
298 // SDP Protocol doesn't do incoming stuff! |
|
299 Panic(ESdpClientPassiveConnect); |
|
300 return KErrNotSupported; |
|
301 } |
|
302 |