|
1 // Copyright (c) 2008-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 // cresponsehandler.cpp |
|
15 // |
|
16 // |
|
17 /** |
|
18 @file |
|
19 @internalTechnology |
|
20 */ |
|
21 |
|
22 //System include |
|
23 #include <mdns/ccacheentry.h> |
|
24 |
|
25 //User include |
|
26 #include "cresponsehandler.h" |
|
27 __FLOG_STMT(_LIT8(KComponent,"MDNSServer");) |
|
28 /** |
|
29 Two phase constructor |
|
30 @param aMessageHandler a reference to messagehandler |
|
31 */ |
|
32 CResponseHandler* CResponseHandler::NewL(CMessageHandler& aMessageHandler) |
|
33 { |
|
34 CResponseHandler* self = new(ELeave) CResponseHandler(aMessageHandler); |
|
35 CleanupStack::PushL(self); |
|
36 self->ConstructL(); |
|
37 CleanupStack::Pop(); |
|
38 return self; |
|
39 } |
|
40 |
|
41 /** |
|
42 Destructor |
|
43 */ |
|
44 CResponseHandler::~CResponseHandler() |
|
45 { |
|
46 __FLOG(_L8("CResponseHandler::~CResponseHandler - Entry")); |
|
47 iNotifyPtrName.Close(); |
|
48 __FLOG(_L8("CResponseHandler::~CResponseHandler - Exit")); |
|
49 __FLOG_CLOSE; |
|
50 } |
|
51 |
|
52 /** |
|
53 Handles any resopnse packet recieved from the mdns port |
|
54 @param response packet |
|
55 @return void |
|
56 */ |
|
57 void CResponseHandler::HandleIncomingPacketL(CDnsMessage& aMessage, const TSockAddr& /*aAddr*/) |
|
58 { |
|
59 __FLOG(_L8("CResponseHandler::HandleIncomingPacketL - Entry")); |
|
60 iNotifyPtrName.Close(); |
|
61 // process the answer section, and add to the host and service caches |
|
62 TInt aCount(aMessage.Header().AnswerCount()); |
|
63 const RPointerArray<CDnsResourceData>& answers = aMessage.Answers(); |
|
64 for (TInt i = 0; i < aCount; ++i) |
|
65 { |
|
66 HandlePacketAnswersL(answers[i]); |
|
67 } |
|
68 aCount = aMessage.Header().AdditionalRCount(); |
|
69 const RPointerArray<CDnsResourceData>& additional = aMessage.Additional(); |
|
70 for (TInt i = 0; i < aCount; ++i) |
|
71 { |
|
72 if(additional[i]!=NULL) |
|
73 HandlePacketAnswersL(additional[i]); |
|
74 } |
|
75 aCount = aMessage.Header().AuthorityNSCount(); |
|
76 const RPointerArray<CDnsResourceData>& authoritative = aMessage.Authorities(); |
|
77 for (TInt i = 0; i < aCount; ++i) |
|
78 { |
|
79 if(authoritative[i]!=NULL) |
|
80 HandlePacketAnswersL(authoritative[i]); |
|
81 } |
|
82 |
|
83 if(iNotifyPtrName.Count() > 0 ) |
|
84 { |
|
85 MessageHandler().NotifyNewServiceL(iNotifyPtrName); |
|
86 for(TInt i=0 ; i<iNotifyPtrName.Count() ; i++) |
|
87 { |
|
88 iNotifyPtrName[i].Close(); |
|
89 } |
|
90 iNotifyPtrName.Close(); |
|
91 } |
|
92 __FLOG(_L8("CResponseHandler::HandleIncomingPacketL - Exit")); |
|
93 } |
|
94 |
|
95 /* |
|
96 Constructor |
|
97 */ |
|
98 CResponseHandler::CResponseHandler(CMessageHandler& aMessageHandler):CBaseHandler(aMessageHandler) |
|
99 { |
|
100 |
|
101 } |
|
102 |
|
103 /** |
|
104 Two phasae constructor |
|
105 */ |
|
106 void CResponseHandler::ConstructL() |
|
107 { |
|
108 __FLOG_OPEN(KMDNSSubsystem, KComponent); |
|
109 __FLOG(_L8("CResponseHandler::ConstructL - Entry Exit")); |
|
110 } |
|
111 /* |
|
112 * Based on the type of query response recieved from the network. |
|
113 * it will route the record to particular interface. |
|
114 * @param aResourceData record recieved from the network. |
|
115 */ |
|
116 void CResponseHandler::HandlePacketAnswersL(CDnsResourceData* aResourceData) |
|
117 { |
|
118 __FLOG(_L8("CResponseHandler::HandlePacketAnswersL - Entry")); |
|
119 switch(aResourceData->Type()) |
|
120 { |
|
121 case EDnsType_A: |
|
122 { |
|
123 HandleAddrAnswersL(aResourceData); |
|
124 break; |
|
125 } |
|
126 |
|
127 case EDnsType_PTR: |
|
128 { |
|
129 HandlePTRAnswersL(aResourceData); |
|
130 break; |
|
131 } |
|
132 |
|
133 case EDnsType_TXT: |
|
134 { |
|
135 HandleTXTAnswersL(aResourceData); |
|
136 break; |
|
137 } |
|
138 |
|
139 case EDnsType_AAAA: |
|
140 { |
|
141 HandleAAAAAnswersL(aResourceData); |
|
142 //MessageHandler().DnsCache().Insert(); |
|
143 break; |
|
144 } |
|
145 |
|
146 case EDnsType_SRV: |
|
147 { |
|
148 HandleSRVAnswersL(aResourceData); |
|
149 break; |
|
150 } |
|
151 } |
|
152 __FLOG(_L8("CResponseHandler::HandlePacketAnswersL - Exit")); |
|
153 } |
|
154 |
|
155 /** |
|
156 This handles any address content in the answer section . |
|
157 If the cache already contains a address entry with the same name .This will notify the server to change the name. |
|
158 If the cache doesnt contain the entry it will just add this entry in to it. |
|
159 @param aResourceData Contains the answers and nspackets recieved from the mdns port |
|
160 @param aEntry Reference to entry to which record should be added so as to add the same to cache later. |
|
161 @return void |
|
162 */ |
|
163 void CResponseHandler::HandleAddrAnswersL(CDnsResourceData* aResourceData) |
|
164 { |
|
165 __FLOG(_L8("CResponseHandler::HandleAddrAnswersL - Entry")); |
|
166 CRdTypeA* addrRecord = static_cast<CRdTypeA*>(aResourceData); |
|
167 CleanupStack::PushL(addrRecord); |
|
168 TBufC8<100> domainName(addrRecord->Name()); |
|
169 RPointerArray<CCacheEntry> aCacheArray; |
|
170 TBool isUpdated = EFalse; |
|
171 TRAPD(error,MessageHandler().DnsCache().FindServiceL(aCacheArray,domainName,EDnsType_A)); |
|
172 if(error == KErrNone && 0 != aCacheArray.Count()) |
|
173 { |
|
174 const CRdTypeA* addrRecordCEntry = (aCacheArray[0])->AddressRecord(); |
|
175 if(addrRecordCEntry != NULL && addrRecordCEntry->Name().Compare(domainName) == 0) |
|
176 { |
|
177 if(aCacheArray[0]->IsAuthoritative()) |
|
178 { |
|
179 if(addrRecordCEntry->Address() != addrRecord->Address() && addrRecord->IsFlushBitSet()) |
|
180 { |
|
181 MessageHandler().DnsCache().UpdateCacheL(*addrRecord,EFalse,0); |
|
182 isUpdated = ETrue; |
|
183 } |
|
184 } |
|
185 else |
|
186 { |
|
187 isUpdated = ETrue; |
|
188 MessageHandler().DnsCache().UpdateCacheL(*addrRecord,EFalse,0); |
|
189 } |
|
190 |
|
191 } |
|
192 |
|
193 } |
|
194 |
|
195 if (! isUpdated&& 0 != aResourceData->Ttl()) |
|
196 { |
|
197 // we didn't find it, add a new entry. |
|
198 MessageHandler().DnsCache().UpdateCacheL(*addrRecord,EFalse,0); |
|
199 } |
|
200 aCacheArray.ResetAndDestroy(); |
|
201 aCacheArray.Close(); |
|
202 CleanupStack::Pop();//addrRecord |
|
203 __FLOG(_L8("CResponseHandler::HandleAddrAnswersL - Exit")); |
|
204 } |
|
205 |
|
206 /* |
|
207 * Handles any PTR records in the answer section. |
|
208 * 1.Updates the cache if not present . |
|
209 * 2.Notitfies the client about the new service availability if registered for it. |
|
210 * @param aResourceData ptr record recieved from the network. |
|
211 */ |
|
212 |
|
213 void CResponseHandler::HandlePTRAnswersL(CDnsResourceData* aResourceData) |
|
214 { |
|
215 __FLOG(_L8("CResponseHandler::HandlePTRAnswersL - Entry")); |
|
216 CRdTypePtr* ptrEntry = static_cast<CRdTypePtr*>(aResourceData); |
|
217 CleanupStack::PushL(ptrEntry); |
|
218 TBufC8<100> name(ptrEntry->Name()); |
|
219 RPointerArray<CCacheEntry> aCacheArray; |
|
220 MessageHandler().DnsCache().FindServiceL(aCacheArray,name,EDnsType_PTR); |
|
221 TBool isUpdated = EFalse; |
|
222 for (TInt i =0 ; i< aCacheArray.Count(); i++) |
|
223 { |
|
224 if(NULL != aCacheArray[i]) |
|
225 { |
|
226 const CRdTypePtr* ptrRecord = aCacheArray[i]->PtrRecord(); |
|
227 if(ptrRecord->DomainName().CompareF(ptrEntry->DomainName()) == 0) |
|
228 { |
|
229 MessageHandler().DnsCache().UpdateCacheL(*ptrEntry,EFalse,0); |
|
230 isUpdated = ETrue; |
|
231 if(aResourceData->Ttl() == 0) |
|
232 { |
|
233 if(ptrEntry->DomainName().Find(ptrEntry->Name()) != KErrNotFound) |
|
234 { |
|
235 RBuf8 temp; |
|
236 temp.CreateL(ptrEntry->DomainName()); |
|
237 if(iNotifyPtrName.Find(temp) == KErrNotFound) |
|
238 { |
|
239 iNotifyPtrName.AppendL(temp); |
|
240 } |
|
241 else |
|
242 { |
|
243 temp.Close(); |
|
244 } |
|
245 } |
|
246 CRdTypeSrv* srvRecord = static_cast <CRdTypeSrv*>( aCacheArray[i]->ServiceRecord()); |
|
247 if(srvRecord != NULL) |
|
248 { |
|
249 srvRecord->SetTtl(0); |
|
250 MessageHandler().DnsCache().UpdateCacheL(*srvRecord,EFalse,0); |
|
251 } |
|
252 CRdTypeTxt* txtRecord = static_cast <CRdTypeTxt*> (aCacheArray[i]->TxtRecord()); |
|
253 if(txtRecord != NULL) |
|
254 { |
|
255 txtRecord->SetTtl(0); |
|
256 MessageHandler().DnsCache().UpdateCacheL(*txtRecord,EFalse,0); |
|
257 } |
|
258 } |
|
259 |
|
260 break; |
|
261 } |
|
262 } |
|
263 } |
|
264 if(!isUpdated && 0 != aResourceData->Ttl()) |
|
265 { |
|
266 MessageHandler().DnsCache().UpdateCacheL(*ptrEntry,EFalse,0); |
|
267 //Notify the client about new service |
|
268 if(ptrEntry->DomainName().Find(ptrEntry->Name()) != KErrNotFound) |
|
269 { |
|
270 RBuf8 temp; |
|
271 temp.CreateL(ptrEntry->DomainName()); |
|
272 if(iNotifyPtrName.Find(temp) == KErrNotFound) |
|
273 { |
|
274 iNotifyPtrName.AppendL(temp); |
|
275 } |
|
276 else |
|
277 { |
|
278 temp.Close(); |
|
279 } |
|
280 } |
|
281 } |
|
282 aCacheArray.ResetAndDestroy(); |
|
283 aCacheArray.Close(); |
|
284 CleanupStack::Pop(ptrEntry); |
|
285 __FLOG(_L8("CResponseHandler::HandlePTRAnswersL - Exit")); |
|
286 } |
|
287 |
|
288 /* |
|
289 * Handles any TXT records in the answer section. |
|
290 * 1.Updates the cache if not present . |
|
291 * @param aResourceData ptr record recieved from the network. |
|
292 */ |
|
293 void CResponseHandler::HandleTXTAnswersL(CDnsResourceData* aResourceData) |
|
294 { |
|
295 __FLOG(_L8("CResponseHandler::HandleTXTAnswersL - Entry")); |
|
296 CRdTypeTxt* txtEntry = static_cast<CRdTypeTxt*>(aResourceData); |
|
297 CleanupStack::PushL(txtEntry); |
|
298 RPointerArray<CCacheEntry> aCacheArray; |
|
299 TBool isUpdated = EFalse; |
|
300 TRAPD(error,MessageHandler().DnsCache().FindServiceL(aCacheArray,txtEntry->Name(),EDnsType_TXT)); |
|
301 if(error == KErrNone && 0 != aCacheArray.Count() && NULL != aCacheArray[0]->TxtRecord()) |
|
302 { |
|
303 const CRdTypeTxt* txtRecord = aCacheArray[0]->TxtRecord(); |
|
304 if(NULL != txtRecord && txtRecord->Name().CompareF(txtEntry->Name()) == 0) |
|
305 { |
|
306 if(aCacheArray[0]->IsAuthoritative()) |
|
307 { |
|
308 isUpdated = ETrue; |
|
309 MessageHandler().DnsCache().UpdateCacheL(*txtEntry,ETrue,0); |
|
310 } |
|
311 else |
|
312 { |
|
313 isUpdated = ETrue; |
|
314 MessageHandler().DnsCache().UpdateCacheL(*txtEntry,EFalse,0); |
|
315 } |
|
316 |
|
317 } |
|
318 } |
|
319 if(!isUpdated && aResourceData->Ttl() != 0 ) |
|
320 { |
|
321 MessageHandler().DnsCache().UpdateCacheL(*txtEntry,EFalse,0); |
|
322 } |
|
323 RBuf8 temp; |
|
324 temp.CreateL(txtEntry->Name()); |
|
325 if(iNotifyPtrName.Find(temp) == KErrNotFound) |
|
326 { |
|
327 iNotifyPtrName.AppendL(temp); |
|
328 } |
|
329 else |
|
330 { |
|
331 temp.Close(); |
|
332 } |
|
333 aCacheArray.ResetAndDestroy(); |
|
334 aCacheArray.Close(); |
|
335 CleanupStack::Pop();//txtEntry*/ |
|
336 __FLOG(_L8("CResponseHandler::HandleTXTAnswersL - Exit")); |
|
337 } |
|
338 |
|
339 void CResponseHandler::HandleAAAAAnswersL(CDnsResourceData* /*aResourceData*/) |
|
340 { |
|
341 |
|
342 } |
|
343 |
|
344 /* |
|
345 * Handles any SRV records in the answer section. |
|
346 * 1.Updates the cache if not present . |
|
347 * @param aResourceData ptr record recieved from the network. |
|
348 */ |
|
349 void CResponseHandler::HandleSRVAnswersL(CDnsResourceData* aResourceData) |
|
350 { |
|
351 __FLOG(_L8("CResponseHandler::HandleSRVAnswersL - Entry")); |
|
352 CRdTypeSrv* srvEntry = static_cast<CRdTypeSrv*>(aResourceData); |
|
353 CleanupStack::PushL(srvEntry); |
|
354 RPointerArray<CCacheEntry> cacheArray; |
|
355 TBool isUpdated = EFalse; |
|
356 TRAPD(error,MessageHandler().DnsCache().FindServiceL(cacheArray,srvEntry->Name(),EDnsType_SRV)); |
|
357 if(KErrNone == error && cacheArray.Count() != 0 && NULL != cacheArray[0]->ServiceRecord()) |
|
358 { |
|
359 const CRdTypeSrv* srvRecord = cacheArray[0]->ServiceRecord(); |
|
360 /*if(aResourceData->Ttl() == 0) |
|
361 { |
|
362 if(srvEntry->Name().Find(srvEntry->Target()) != KErrNotFound) |
|
363 { |
|
364 RBuf8 temp; |
|
365 temp.CreateL(srvEntry->Name()); |
|
366 if(iNotifyPtrName.Find(temp) == KErrNotFound) |
|
367 { |
|
368 iNotifyPtrName.AppendL(temp); |
|
369 } |
|
370 else |
|
371 { |
|
372 temp.Close(); |
|
373 } |
|
374 } |
|
375 CRdTypeSrv* srvRecord = static_cast <CRdTypeSrv*>( cacheArray[i]->ServiceRecord()); |
|
376 if(srvRecord != NULL) |
|
377 { |
|
378 srvRecord->SetTtl(0); |
|
379 MessageHandler().DnsCache().UpdateCacheL(*srvRecord,EFalse,0); |
|
380 } |
|
381 CRdTypeTxt* txtRecord = static_cast <CRdTypeTxt*> (aCacheArray[i]->TxtRecord()); |
|
382 if(txtRecord != NULL) |
|
383 { |
|
384 txtRecord->SetTtl(0); |
|
385 MessageHandler().DnsCache().UpdateCacheL(*txtRecord,EFalse,0); |
|
386 } |
|
387 }*/ |
|
388 |
|
389 if(srvRecord->Name().CompareF(srvEntry->Name()) == 0 && srvEntry->IsFlushBitSet()) |
|
390 { |
|
391 if(cacheArray[0]->IsAuthoritative()) |
|
392 { |
|
393 isUpdated = ETrue; |
|
394 MessageHandler().DnsCache().UpdateCacheL(*srvEntry,ETrue,0); |
|
395 } |
|
396 else |
|
397 { |
|
398 isUpdated = ETrue; |
|
399 MessageHandler().DnsCache().UpdateCacheL(*srvEntry,EFalse,0); |
|
400 } |
|
401 } |
|
402 |
|
403 } |
|
404 RBuf8 temp; |
|
405 temp.CreateL(srvEntry->Name()); |
|
406 if(iNotifyPtrName.Find(temp) == KErrNotFound) |
|
407 { |
|
408 iNotifyPtrName.AppendL(temp); |
|
409 } |
|
410 else |
|
411 { |
|
412 temp.Close(); |
|
413 } |
|
414 if(!isUpdated && srvEntry->Ttl() != 0) |
|
415 { |
|
416 MessageHandler().DnsCache().UpdateCacheL(*srvEntry,EFalse,0); |
|
417 } |
|
418 cacheArray.ResetAndDestroy(); |
|
419 cacheArray.Close(); |
|
420 CleanupStack::Pop();//srvEntry |
|
421 __FLOG(_L8("CResponseHandler::HandleSRVAnswersL - Exit")); |
|
422 } |
|
423 |