|
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 // mdnsserver.cpp |
|
15 // |
|
16 // |
|
17 /** |
|
18 @file |
|
19 @internalTechnology |
|
20 */ |
|
21 |
|
22 #include "mdnsserver.h" |
|
23 #include <commdbConnpref.h> |
|
24 #include "mdnsserversession.h" |
|
25 #include "shutdowntimer.h" |
|
26 #include "cmessagehandler.h" |
|
27 #include "cmdnscacheconsistencymgr.h" |
|
28 #include <mdns/cmdnsserverconstants.h> |
|
29 #include "cmdnsprobemanager.h" |
|
30 #include <nifman.h> |
|
31 #include <comms-infras/es_config.h> |
|
32 #include <EscapeUtils.h> |
|
33 #include <ecom/ECom.h> |
|
34 #include <btengsettings.h>// Console |
|
35 #include "cengsettingsobserver.h" |
|
36 __FLOG_STMT(_LIT8(KComponent,"MDNSServer");) |
|
37 CMdnsServer* CMdnsServer::NewL() |
|
38 { |
|
39 |
|
40 CMdnsServer* self = CMdnsServer::NewLC(); |
|
41 CleanupStack::Pop(self); |
|
42 |
|
43 return self; |
|
44 } |
|
45 |
|
46 /* |
|
47 * Two phase constructor |
|
48 */ |
|
49 CMdnsServer* CMdnsServer::NewLC() |
|
50 { |
|
51 CMdnsServer* self = new (ELeave) CMdnsServer; |
|
52 CleanupStack::PushL(self); |
|
53 self->ConstructL(); |
|
54 return self; |
|
55 } |
|
56 |
|
57 /* |
|
58 * Derived from CPolicy server |
|
59 * Creates a new session object. |
|
60 */ |
|
61 CSession2* CMdnsServer::NewSessionL(const TVersion& /*aVersion*/, const RMessage2& /*aMessage*/) const |
|
62 { |
|
63 __FLOG(_L8("CMdnsServer::NewSessionL - Entry")); |
|
64 // if we're in the process of shutting the server down cleanly, |
|
65 // don't accept any more connections. |
|
66 if (iShutdownInProgress) |
|
67 { |
|
68 User::Leave(KErrCouldNotConnect); |
|
69 } |
|
70 |
|
71 CMdnsServerSession* session = CMdnsServerSession::NewL(*this); |
|
72 __FLOG(_L8("CMdnsServer::NewSessionL - Exit")); |
|
73 return session; |
|
74 } |
|
75 |
|
76 TInt CMdnsServer::NewSession() |
|
77 { |
|
78 __FLOG(_L8("CMdnsServer::NewSession - Entry")); |
|
79 iShutdownTimer->Cancel(); |
|
80 ++iConnectionCount; |
|
81 ++iSessionIdCounter; |
|
82 __FLOG(_L8("CMdnsServer::NewSession - Exit")); |
|
83 return iSessionIdCounter; |
|
84 } |
|
85 |
|
86 void CMdnsServer::DropSession() |
|
87 { |
|
88 __FLOG(_L8("CMdnsServer::DropSession - Entry")); |
|
89 if (0 == --iConnectionCount) |
|
90 { |
|
91 //CActiveScheduler::Stop(); |
|
92 iShutdownTimer->Start(); |
|
93 } |
|
94 __FLOG(_L8("CMdnsServer::DropSession - Exit")); |
|
95 } |
|
96 |
|
97 void CMdnsServer::BeginShutdownL() |
|
98 { |
|
99 __FLOG(_L8("CMdnsServer::BeginShutdownL - Entry")); |
|
100 iShutdownInProgress = ETrue; |
|
101 CActiveScheduler::Stop(); |
|
102 __FLOG(_L8("CMdnsServer::BeginShutdownL - Exit")); |
|
103 } |
|
104 |
|
105 /* |
|
106 * Destructor |
|
107 */ |
|
108 CMdnsServer::~CMdnsServer() |
|
109 { |
|
110 __FLOG(_L8("CMdnsServer::~CMdnsServer - Entry")); |
|
111 iCacheConsistencyMgr->Stop(); |
|
112 delete iShutdownTimer; |
|
113 delete iMessageHandler; |
|
114 delete iProbeManager; |
|
115 delete iInternalMessageQueue; |
|
116 delete iCacheConsistencyMgr; |
|
117 iConnection.Close(); |
|
118 iSockServ.Close(); |
|
119 iHostName.Close(); |
|
120 REComSession::FinalClose(); |
|
121 __FLOG(_L8("CMdnsServer::~CMdnsServer - Exit")); |
|
122 __FLOG_CLOSE; |
|
123 } |
|
124 |
|
125 CMdnsServer::CMdnsServer() |
|
126 : CPolicyServer(EPriorityStandard, zeroconfPolicy),iConnectionCount(0),iSessionIdCounter(0) |
|
127 { |
|
128 } |
|
129 |
|
130 /* |
|
131 * Get the system ipaddress by amaking a query to the dns. |
|
132 * @param aAddr on return contains the address. |
|
133 */ |
|
134 TInt CMdnsServer::GetLocalHost ( TSockAddr& aAddr ) |
|
135 { |
|
136 __FLOG(_L8("CMdnsServer::GetLocalHost - Entry")); |
|
137 RSocket socket; |
|
138 TInt err = socket.Open ( iSockServ, KAfInet, KSockStream, KProtocolInetTcp ); |
|
139 |
|
140 if ( err == KErrNone ) |
|
141 { |
|
142 TInetAddr localHost; |
|
143 localHost.SetAddress ( KInetAddrAny ); |
|
144 TPckgBuf<TSoInetIfQuery> query; |
|
145 query ().iDstAddr = localHost; |
|
146 |
|
147 err = socket.GetOpt ( KSoInetIfQueryByDstAddr, KSolInetIfQuery, query ); |
|
148 |
|
149 if ( err == KErrNone ) |
|
150 { |
|
151 // its local IP address |
|
152 localHost = query ().iSrcAddr; |
|
153 aAddr = localHost; |
|
154 TBuf<255>name ; |
|
155 name.Append(query ().iName); |
|
156 } |
|
157 } |
|
158 |
|
159 socket.Close (); |
|
160 __FLOG(_L8("CMdnsServer::GetLocalHost - Exit")); |
|
161 return err; |
|
162 } |
|
163 |
|
164 /* |
|
165 * Two phase constructor |
|
166 */ |
|
167 void CMdnsServer::ConstructL() |
|
168 { |
|
169 __FLOG_OPEN(KMDNSSubsystem, KComponent); |
|
170 __FLOG(_L8("CMdnsServer::ConstructL - Entry")); |
|
171 User::LeaveIfError(iSockServ.Connect()); |
|
172 User::LeaveIfError(iConnection.Open(iSockServ)); |
|
173 |
|
174 // fetch the IAP from the command line |
|
175 HBufC* iapBuf = HBufC::NewLC(User::CommandLineLength()); |
|
176 TPtr iapPtr = iapBuf->Des(); |
|
177 User::CommandLine(iapPtr); |
|
178 |
|
179 TUint32 iap(0); |
|
180 TLex lex(*iapBuf); |
|
181 User::LeaveIfError(lex.Val(iap, EDecimal)); |
|
182 |
|
183 CleanupStack::PopAndDestroy(iapBuf); |
|
184 |
|
185 // start a connection with the appropriate IAP |
|
186 TCommDbConnPref prefs; |
|
187 prefs.SetIapId(iap); |
|
188 prefs.SetDialogPreference(ECommDbDialogPrefDoNotPrompt); |
|
189 User::LeaveIfError(iConnection.Start(prefs)); |
|
190 |
|
191 User::LeaveIfError(iSocket.Open(iSockServ, KAfInet, KSockDatagram, KProtocolInetUdp)); |
|
192 User::LeaveIfError(iSocket.SetLocalPort(KMdnsPort)); |
|
193 TInetAddr broadcast; |
|
194 //To be added in constant header |
|
195 const TUint32 KMDnsAddr = INET_ADDR(224, 0, 0, 251); |
|
196 broadcast.SetAddress(KMDnsAddr); |
|
197 JoinMulticastGroupL(broadcast); |
|
198 iMessageHandler = CMessageHandler::NewL(*this); |
|
199 iShutdownTimer = CShutdownTimer::NewL(*this); |
|
200 /***************************************PROBE**************************************************/ |
|
201 //From here : Probe only for Host Name |
|
202 iProbeManager = CMDNSProbeManager::NewL(iMessageHandler->DnsCache(),*iMessageHandler,ETrue); |
|
203 TInetAddr addr; |
|
204 GetLocalHost(addr); |
|
205 //iHostName.Create(_L8("vadan.Local")); |
|
206 CEngSettingsObserver* observer = CEngSettingsObserver::NewLC(); |
|
207 |
|
208 CBTEngSettings* btsettings= CBTEngSettings::NewL(observer); |
|
209 |
|
210 RBuf name; |
|
211 name.CreateL(64); |
|
212 btsettings->GetLocalName(name); |
|
213 if(name.Length()==0) |
|
214 { |
|
215 iHostName.CreateL(_L8("MyNokiaPhone.Local")); |
|
216 } |
|
217 else |
|
218 { |
|
219 name.Append(_L(".local")); |
|
220 iHostName.CreateL(name.Collapse()); |
|
221 } |
|
222 |
|
223 iProbeManager->StartNameProbeL(iHostName,addr); |
|
224 /*****************************************END**************************************************/ |
|
225 iInternalMessageQueue = CInternalMessageQueue::NewL(*this); |
|
226 /*****************************************ConsistencyMgr***************************************/ |
|
227 iCacheConsistencyMgr = CMDNSCacheConsistencyMgr::NewL(ETrue,*iMessageHandler); |
|
228 iCacheConsistencyMgr->Start(); |
|
229 // start up the server |
|
230 StartL(KMdnsServerName); |
|
231 __FLOG(_L8("CMdnsServer::ConstructL - Exit")); |
|
232 } |
|
233 /* |
|
234 * Interface to join the multicast group. |
|
235 * @param aMulticastAddr specifies the multicast address to which it will join |
|
236 * this is generally the mdns multicast address. |
|
237 */ |
|
238 void CMdnsServer::JoinMulticastGroupL(TInetAddr& aMulticastAddr) |
|
239 { |
|
240 __FLOG(_L8("CMdnsServer::JoinMulticastGroupL - Entry")); |
|
241 TPckgBuf<TIp6Mreq> mReq; |
|
242 |
|
243 if (aMulticastAddr.Family() != KAfInet6) |
|
244 { |
|
245 aMulticastAddr.ConvertToV4Mapped(); |
|
246 } |
|
247 |
|
248 mReq().iAddr = aMulticastAddr.Ip6Address(); |
|
249 mReq().iInterface = 0; |
|
250 User::LeaveIfError(iSocket.SetOpt(KSoIp6MulticastHops, KSolInetIp, 255)); |
|
251 User::LeaveIfError(iSocket.SetOpt(KSoIp6JoinGroup, KSolInetIp, mReq)); |
|
252 User::LeaveIfError(iSocket.SetOpt(KSoIp6MulticastLoop, KSolInetIp, 0)); |
|
253 __FLOG(_L8("CMdnsServer::JoinMulticastGroupL - Exit")); |
|
254 } |
|
255 |
|
256 /* |
|
257 * @return returns the reference to the socket. |
|
258 */ |
|
259 RSocket& CMdnsServer::Socket() |
|
260 { |
|
261 __FLOG(_L8("CMdnsServer::Socket -Entry Exit")); |
|
262 return iSocket; |
|
263 } |
|
264 /* |
|
265 * returns the reference to messagehandler. |
|
266 */ |
|
267 CMessageHandler& CMdnsServer::MessageHandler()const |
|
268 { |
|
269 __FLOG(_L8("CMdnsServer::MessageHandler -Entry Exit")); |
|
270 return *iMessageHandler; |
|
271 } |
|
272 |
|
273 /* |
|
274 * Query from the client should be served after a delay .If sent to the |
|
275 * network. usually 120ms. |
|
276 * Server will be notified with the same after the time elapses. |
|
277 * @param aClientHandle session id which actually requested for the query . |
|
278 * |
|
279 * */ |
|
280 void CMdnsServer::NotifyClientQuery(TInt aClientHandle) |
|
281 { |
|
282 __FLOG(_L8("CMdnsServer::NotifyClientQuery - Entry")); |
|
283 iSessionIter.SetToFirst(); |
|
284 CSession2* session = NULL; |
|
285 while (NULL != (session = iSessionIter++)) |
|
286 { |
|
287 CMdnsServerSession* serverSession = static_cast<CMdnsServerSession*>(session); |
|
288 if(serverSession->OutStandQueryClientHandle() == aClientHandle) |
|
289 { |
|
290 serverSession->SendResponseL(); |
|
291 } |
|
292 } |
|
293 __FLOG(_L8("CMdnsServer::NotifyClientQuery - Exit")); |
|
294 } |
|
295 |
|
296 /* |
|
297 * Returns the hostname with which it has been probed. |
|
298 */ |
|
299 TDesC8& CMdnsServer::HostName()const |
|
300 { |
|
301 __FLOG(_L8("CMdnsServer::HostName -Entry Exit")); |
|
302 return (TDesC8&)iHostName; |
|
303 } |
|
304 |
|
305 |
|
306 void CMdnsServer::SetHostNameL(const TDesC8& aName) |
|
307 { |
|
308 iHostName.Close(); |
|
309 iHostName.CreateL(aName); |
|
310 } |
|
311 |
|
312 /* |
|
313 * When a new service appears in the network. |
|
314 * will be notified to the server using this. |
|
315 * Server in turn looks for the session interested in the service and completes the asynchronous reuest. |
|
316 */ |
|
317 void CMdnsServer::NotifyNewServiceL(const RArray<RBuf8>& aName) |
|
318 { |
|
319 __FLOG(_L8("CMdnsServer::NotifyNewServiceL - Entry")); |
|
320 iSessionIter.SetToFirst(); |
|
321 CSession2* session = NULL; |
|
322 while (NULL != (session = iSessionIter++)) |
|
323 { |
|
324 CMdnsServerSession* serverSession = static_cast<CMdnsServerSession*>(session); |
|
325 serverSession->NewServiceL(aName); |
|
326 } |
|
327 __FLOG(_L8("CMdnsServer::NotifyNewServiceL - Exit")); |
|
328 } |
|
329 |
|
330 /* |
|
331 * After the service has been published succesfully. |
|
332 * Server will be notified with this interface. |
|
333 * @param aName name with which the service is published. |
|
334 * @param aError result of submission. |
|
335 * @param aSessionId session id of the client. |
|
336 */ |
|
337 void CMdnsServer::NotifyServicePublishL(const RBuf8& aName,TInt aError, TInt aSessionId) |
|
338 { |
|
339 __FLOG(_L8("CMdnsServer::NotifyServicePublishL - Entry")); |
|
340 iSessionIter.SetToFirst(); |
|
341 CSession2* session = NULL; |
|
342 while ((NULL != (session = iSessionIter++)) ) |
|
343 { |
|
344 CMdnsServerSession* serverSession = static_cast<CMdnsServerSession*>(session); |
|
345 if(serverSession->SessionId() == aSessionId) |
|
346 { |
|
347 serverSession->HandleServiceNameConflictL(aName,aError); |
|
348 } |
|
349 } |
|
350 SetPublishingService(EFalse); |
|
351 if(MessageQueue()->Count()>0) |
|
352 { |
|
353 MessageQueue()->StartProcessing(); |
|
354 } |
|
355 __FLOG(_L8("CMdnsServer::NotifyServicePublishL - Exit")); |
|
356 } |
|
357 |
|
358 /* |
|
359 * This performs two tast. |
|
360 * 1. Set the iIsHostprobing to ETrue if host probing is going on. |
|
361 * 2. If Hostprobing is over it sees whether there are any pending queries or |
|
362 * publish request . IF there are any it will start processing the same . |
|
363 * @param aProbing true if host probing. |
|
364 */ |
|
365 void CMdnsServer::SetStateHostProbing(TBool aProbing) |
|
366 { |
|
367 __FLOG(_L8("CMdnsServer::SetStateHostProbing - Entry")); |
|
368 iIsHostProbing = aProbing; |
|
369 if(!aProbing && MessageQueue()->Count()>0) |
|
370 { |
|
371 MessageQueue()->StartProcessing(); |
|
372 } |
|
373 __FLOG(_L8("CMdnsServer::SetStateHostProbing - Exit")); |
|
374 } |
|
375 |
|
376 /* |
|
377 * @return returns wheteher host probing is going on or not. |
|
378 */ |
|
379 TBool CMdnsServer::IsHostProbing()const |
|
380 { |
|
381 __FLOG(_L8("CMdnsServer::IsHostProbing - Exit")); |
|
382 return iIsHostProbing; |
|
383 } |
|
384 |
|
385 /* |
|
386 * Starts any pending publish or query request in the queue. |
|
387 * @param aMessage query or publish request. |
|
388 * @param aType can be either publish or query. |
|
389 * @param aSessionId session which requested . |
|
390 */ |
|
391 void CMdnsServer::ProcessQueuedMessage(const RMessage2& aMessage, const TMessageType aType,TInt aSessionId) |
|
392 { |
|
393 __FLOG(_L8("CMdnsServer::ProcessQueuedMessage - Entry")); |
|
394 iSessionIter.SetToFirst(); |
|
395 CSession2* session = NULL; |
|
396 while (NULL != (session = iSessionIter++)) |
|
397 { |
|
398 CMdnsServerSession* serverSession = static_cast<CMdnsServerSession*>(session); |
|
399 if(aSessionId == serverSession->SessionId()) |
|
400 { |
|
401 switch(aType) |
|
402 { |
|
403 case EQueryMessage: |
|
404 { |
|
405 serverSession->ServiceQueryL(aMessage); |
|
406 break; |
|
407 } |
|
408 case EPublishMessage: |
|
409 { |
|
410 serverSession->PublishL(aMessage); |
|
411 break; |
|
412 } |
|
413 } |
|
414 } |
|
415 } |
|
416 __FLOG(_L8("CMdnsServer::ProcessQueuedMessage - Exit")); |
|
417 } |
|
418 |
|
419 /* |
|
420 * Pointer to the internall message queue. |
|
421 */ |
|
422 CInternalMessageQueue* CMdnsServer::MessageQueue() |
|
423 { |
|
424 __FLOG(_L8("CMdnsServer::MessageQueue -Entry Exit")); |
|
425 return iInternalMessageQueue; |
|
426 } |
|
427 |
|
428 |
|
429 void CMdnsServer::OnPacketSendL(TInt /*aError*/) |
|
430 { |
|
431 // this is the call back after the bye-bye packet is sent. |
|
432 // do nothing |
|
433 __FLOG(_L8("CMdnsServer::OnPacketSendL -Entry Exit")); |
|
434 } |
|
435 /* |
|
436 * if publishing will be set to true. |
|
437 * this is to halt any further publish , till the one undergoing gets over. |
|
438 */ |
|
439 void CMdnsServer::SetPublishingService(TBool aFlag) |
|
440 { |
|
441 __FLOG(_L8("CMdnsServer::SetPublishingService - Entry")); |
|
442 iIsPublishing = aFlag; |
|
443 __FLOG(_L8("CMdnsServer::SetPublishingService - Exit")); |
|
444 |
|
445 } |
|
446 TBool CMdnsServer::IsPublishingService() const |
|
447 { |
|
448 __FLOG(_L8("CMdnsServer::IsPublishingService -Entry Exit")); |
|
449 return iIsPublishing ; |
|
450 } |