|
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 // |
|
15 |
|
16 #include <es_sock.h> |
|
17 #include <btsdp.h> |
|
18 #include <e32des8.h> |
|
19 #include <bluetooth/logger.h> |
|
20 |
|
21 #include "SDPDatabase.h" |
|
22 #include "DataEncoder.h" |
|
23 #include "EncoderVisitor.h" |
|
24 |
|
25 #ifdef __FLOG_ACTIVE |
|
26 _LIT8(KLogComponent, LOG_COMPONENT_SDPDATABASE); |
|
27 #endif |
|
28 |
|
29 void Panic(TSdpDatabasePanics aCode) |
|
30 { |
|
31 User::Panic(KSdpDatabasePanicName, aCode); |
|
32 } |
|
33 |
|
34 // Class CSdpDatabase |
|
35 |
|
36 EXPORT_C CSdpDatabase* CSdpDatabase::NewLC() |
|
37 /** |
|
38 Creates a CSdpDatabase object, but leaves on the cleanup stack. |
|
39 |
|
40 @return Pointer to the created CSdpDatabase object |
|
41 */ |
|
42 { |
|
43 LOG_STATIC_FUNC |
|
44 CSdpDatabase* self = new(ELeave) CSdpDatabase; |
|
45 CleanupStack::PushL(self); |
|
46 self->ConstructL(); |
|
47 return self; |
|
48 } |
|
49 |
|
50 EXPORT_C CSdpDatabase* CSdpDatabase::NewL() |
|
51 /** |
|
52 Creates a CSdpDatabase object.(Does NOT leave it on the cleanup stack.) |
|
53 |
|
54 @return Pointer to the created CSdpDatabase object |
|
55 */ |
|
56 { |
|
57 LOG_STATIC_FUNC |
|
58 CSdpDatabase* self = CSdpDatabase::NewLC(); |
|
59 CleanupStack::Pop(); |
|
60 return self; |
|
61 } |
|
62 |
|
63 CSdpDatabase::CSdpDatabase() |
|
64 : iCanAddRecord(ETrue), |
|
65 iRecords(CSdpServRecord::LinkOffset()), |
|
66 iNextFreeHandle(KSdpMinServRecordHandle) |
|
67 { |
|
68 CONNECT_LOGGER |
|
69 } |
|
70 |
|
71 void CSdpDatabase::ConstructL() |
|
72 { |
|
73 LOG_FUNC |
|
74 } |
|
75 |
|
76 EXPORT_C CSdpDatabase::~CSdpDatabase() |
|
77 /** Destructor |
|
78 */ |
|
79 { |
|
80 LOG_FUNC |
|
81 // Delete all records on the record list |
|
82 iRecords.ResetAndDestroy(); |
|
83 CLOSE_LOGGER |
|
84 } |
|
85 |
|
86 /** Adds a service record to this database. |
|
87 @param aRecord The record being added |
|
88 */ |
|
89 EXPORT_C void CSdpDatabase::AddRecord(CSdpServRecord* aRecord) |
|
90 { |
|
91 LOG_FUNC |
|
92 iRecords.AddInOrder(*aRecord); //Panics if aRecord's handle is already bagged. |
|
93 //Must do this AFTER adding latest record...hence need for 'iCanAddRecord' |
|
94 iCanAddRecord = ReviseNextFreeHandle(); |
|
95 } |
|
96 |
|
97 /** Creates a new record on this database |
|
98 @leave KErrSdpDatabaseFull implies no more spare handles |
|
99 */ |
|
100 EXPORT_C CSdpServRecord* CSdpDatabase::NewRecordL() |
|
101 { |
|
102 LOG_FUNC |
|
103 // Add a new record only if we have spare handles... |
|
104 // ...there are 2^32 - 0x10000 to choose from! |
|
105 if(!iCanAddRecord) |
|
106 { |
|
107 User::Leave(KErrSdpDatabaseFull); |
|
108 } |
|
109 |
|
110 CSdpServRecord* record = CSdpServRecord::NewL(); |
|
111 CleanupStack::PushL(record); |
|
112 |
|
113 record |
|
114 ->BuildUintL(TSdpIntBuf<TUint16>(0)) |
|
115 ->BuildUintL(TSdpIntBuf<TSdpServRecordHandle>(NextFreeHandle())); |
|
116 |
|
117 AddRecord(record); |
|
118 CleanupStack::Pop(); //record |
|
119 return record; |
|
120 } |
|
121 |
|
122 /** Encodes complete database. */ |
|
123 EXPORT_C void CSdpDatabase::EncodeDbL() |
|
124 { |
|
125 LOG_FUNC |
|
126 for(TServRecordIter recIter(RecordIter()); recIter; recIter++) |
|
127 {// Iterate through records in Db |
|
128 for (TServAttrIter attrIter((*recIter).AttributeIter()); attrIter; attrIter++) |
|
129 {// iterate through attributes in record |
|
130 CSdpAttr* theAttr = &(*attrIter); |
|
131 CSdpAttrValue* theAttrValue = &(theAttr->Value()); |
|
132 TUint size = TElementEncoder::EncodedSize(theAttrValue->Type(), |
|
133 theAttrValue->DataSize()); |
|
134 |
|
135 HBufC8* outbuf = HBufC8::NewLC(size); |
|
136 TPtr8 writePtr = outbuf->Des(); |
|
137 TElementEncoder theEncoder(writePtr); |
|
138 CAttrEncoderVisitor::EncodeAttributeL(theEncoder, (*attrIter).Value()); |
|
139 theAttr->BuildEncodedL(writePtr); |
|
140 CleanupStack::PopAndDestroy(); //outbuf |
|
141 } |
|
142 } |
|
143 } |
|
144 |
|
145 /** Dead function. Space filler for .def file (left in for BC) |
|
146 */ |
|
147 EXPORT_C void CSdpDatabase::ParseDbL_Obscelete_DoesNothing() |
|
148 { |
|
149 LOG_FUNC |
|
150 return; |
|
151 } |
|
152 |
|
153 /** Returns the 'TSdpServRecordHandle' iNextFreeHandle. |
|
154 @return the next free handle |
|
155 */ |
|
156 EXPORT_C TSdpServRecordHandle CSdpDatabase::NextFreeHandle() |
|
157 { |
|
158 LOG_FUNC |
|
159 return iNextFreeHandle; |
|
160 } |
|
161 |
|
162 /** Finds a handle not used by any record in database. |
|
163 Starts at current next free handle value, and discovers if |
|
164 it is used by a record in the database. If so cycles it on one in |
|
165 in the allowed range, and checks again. This algorithm continues |
|
166 until an unused handle is found (=>return ETrue) or all handles |
|
167 have been checked and are found to be in use. (=>return EFalse) |
|
168 NB. We start by looking for the next available handle going upwards |
|
169 in value. Only if none are found do we return to the lower limit and |
|
170 search for "holes" below the last claimed handle. This should |
|
171 reduce processing time. We could have gone further and incremented |
|
172 iNextFreeHandle value before doing anything else, because it is likely |
|
173 that the current iNextFreeHandle will have just been used when this |
|
174 function is called |
|
175 */ |
|
176 TBool CSdpDatabase::ReviseNextFreeHandle() |
|
177 { |
|
178 LOG_FUNC |
|
179 if(iNextFreeHandle>KSdpMaxServRecordHandle|| |
|
180 iNextFreeHandle<KSdpMinServRecordHandle) |
|
181 { |
|
182 iNextFreeHandle = KSdpMinServRecordHandle; |
|
183 } |
|
184 |
|
185 TSdpServRecordHandle origNextFreeHandle(iNextFreeHandle); |
|
186 for(TServRecordIter recIter(RecordIter()); recIter; recIter++) |
|
187 {// Iterate thru records in iDatabase |
|
188 if((*recIter).Handle()==iNextFreeHandle) |
|
189 { |
|
190 if(++iNextFreeHandle>KSdpMaxServRecordHandle) |
|
191 iNextFreeHandle = KSdpMinServRecordHandle; |
|
192 //We've run out of handles |
|
193 if(iNextFreeHandle==origNextFreeHandle) |
|
194 return EFalse; |
|
195 //Run through all records again to check for new incremented handle. |
|
196 recIter.SetToFirst(); |
|
197 } |
|
198 } |
|
199 return ETrue; |
|
200 } |
|
201 |
|
202 |
|
203 EXPORT_C CAttrUuidVisitor* CAttrUuidVisitor::NewL() |
|
204 { |
|
205 LOG_STATIC_FUNC |
|
206 CAttrUuidVisitor* self = new(ELeave)CAttrUuidVisitor(); |
|
207 CleanupStack::PushL(self); |
|
208 self->ConstructL(); |
|
209 CleanupStack::Pop(); |
|
210 return self; |
|
211 } |
|
212 |
|
213 EXPORT_C CAttrUuidVisitor::~CAttrUuidVisitor() |
|
214 { |
|
215 LOG_FUNC |
|
216 iUuidContainer.Close(); |
|
217 } |
|
218 |
|
219 EXPORT_C RUUIDContainer& CAttrUuidVisitor::GetUuids() |
|
220 { |
|
221 LOG_FUNC |
|
222 return iUuidContainer; |
|
223 } |
|
224 |
|
225 void CAttrUuidVisitor::EncodeAttributeL(CSdpAttrValue& /*aSrcAttr*/) |
|
226 { |
|
227 LOG_FUNC |
|
228 __ASSERT_DEBUG(ETrue, User::Panic(_L("EncodeAttributeL() erroneously called"), KErrArgument)); |
|
229 } |
|
230 |
|
231 CAttrUuidVisitor::CAttrUuidVisitor() |
|
232 { |
|
233 LOG_FUNC |
|
234 iUuidContainer.Reset(); |
|
235 } |
|
236 |
|
237 void CAttrUuidVisitor::ConstructL() |
|
238 { |
|
239 LOG_FUNC |
|
240 } |
|
241 |
|
242 // Implementation of MAttributeVisitor interface |
|
243 void CAttrUuidVisitor::VisitAttributeL(CSdpAttr& /*aAttribute*/) |
|
244 { |
|
245 LOG_FUNC |
|
246 __ASSERT_DEBUG(ETrue, Panic(ESdpDatabaseVisitAttributeLErroneouslyCalled)); |
|
247 } |
|
248 |
|
249 void CAttrUuidVisitor::VisitAttributeValueL(CSdpAttrValue &aValue, TSdpElementType aType) |
|
250 { |
|
251 LOG_FUNC |
|
252 switch (aType) |
|
253 { |
|
254 case ETypeUUID: |
|
255 iUuidContainer.Add(aValue.UUID()); |
|
256 break; |
|
257 case ETypeEncoded: |
|
258 { |
|
259 TPtrC8 ptr = aValue.Des(); |
|
260 if(ptr.Length() == KSdpElemHdrTypeShift + KSizeOf16BitUUID) |
|
261 { |
|
262 // 16-bit UUID |
|
263 TUUID uuid = TUUID(BigEndian::Get16(&ptr[KSdpElemHdrTypeShift])); |
|
264 iUuidContainer.Add(uuid); |
|
265 } |
|
266 else if(ptr.Length() == KSdpElemHdrTypeShift + KSizeOf32BitUUID) |
|
267 { |
|
268 // 32-bit UUID |
|
269 TUUID uuid = TUUID(BigEndian::Get32(&ptr[KSdpElemHdrTypeShift])); |
|
270 iUuidContainer.Add(uuid); |
|
271 } |
|
272 else if(ptr.Length() == KSdpElemHdrTypeShift + KSizeOf128BitUUID) |
|
273 { |
|
274 // 128-bit UUID |
|
275 TUUID uuid = TUUID(BigEndian::Get32(&ptr[KSdpElemHdrTypeShift]), |
|
276 BigEndian::Get32(&ptr[KSdpElemHdrTypeShift+sizeof(TUint32)]), |
|
277 BigEndian::Get32(&ptr[KSdpElemHdrTypeShift+2*sizeof(TUint32)]), |
|
278 BigEndian::Get32(&ptr[KSdpElemHdrTypeShift+3*sizeof(TUint32)])); |
|
279 iUuidContainer.Add(uuid); |
|
280 } |
|
281 else |
|
282 { |
|
283 // We don't support other UUIDs |
|
284 } |
|
285 } |
|
286 break; |
|
287 default: |
|
288 __ASSERT_DEBUG(ETrue, Panic(ESdpDatabaseUnexpectedAttributeType)); |
|
289 break; |
|
290 } |
|
291 } |
|
292 |
|
293 void CAttrUuidVisitor::StartListL(CSdpAttrValueList& /*aList*/) |
|
294 { |
|
295 LOG_FUNC |
|
296 } |
|
297 |
|
298 void CAttrUuidVisitor::EndListL() |
|
299 { |
|
300 LOG_FUNC |
|
301 } |
|
302 |