|
1 // wsp_resolver.cpp |
|
2 // |
|
3 // Copyright (c) 2002 - 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Accenture - Initial contribution |
|
11 // |
|
12 |
|
13 #include <winsock2.h> |
|
14 // Prevent e32std.inl from failing to compile with "ambiguous access to overloaded function". |
|
15 #define memmove _memmove |
|
16 #define memset _memset |
|
17 // |
|
18 #include <e32math.h> |
|
19 #include <in_sock.h> |
|
20 #include <utf.h> |
|
21 #include "wsp_resolver.h" |
|
22 #include "wsp_session.h" |
|
23 #include "wsp_factory.h" |
|
24 #include "wsp_panic.h" |
|
25 #include "wsp_log.h" |
|
26 |
|
27 |
|
28 // |
|
29 // Constants. |
|
30 // |
|
31 |
|
32 _LIT(KWspResolverWorkerThreadNameFormat, "WinSockPrtResolverWorkerThread_%x_%d"); |
|
33 const TInt KWspResolverWorkerThreadNameLength = 64; |
|
34 const TInt KWspResolverWorkerThreadStackSize = KDefaultStackSize; |
|
35 |
|
36 |
|
37 // |
|
38 // RWin32Socket. |
|
39 // |
|
40 |
|
41 RWin32Resolver::RWin32Resolver() |
|
42 : iNameRecordPckg(NULL, 0, 0) |
|
43 { |
|
44 } |
|
45 |
|
46 TInt RWin32Resolver::Open(RWin32Factory& aFactory) |
|
47 { |
|
48 WSP_LOG(WspLog::Printf(_L("RWin32Resolver::Open: this: 0x%x"), this)); |
|
49 return CreateSubSession(aFactory, CWin32Factory::ENewResolver); |
|
50 } |
|
51 |
|
52 void RWin32Resolver::Close() |
|
53 { |
|
54 WSP_LOG(WspLog::Printf(_L("RWin32Resolver::Close: this: 0x%x"), this)); |
|
55 RWin32SubSession::Close(); |
|
56 } |
|
57 |
|
58 TInt RWin32Resolver::GetByName(TNameRecord& aName, TRequestStatus& aStatus) |
|
59 { |
|
60 WSP_LOG(WspLog::Printf(_L("RWin32Resolver::GetByName: this: 0x%x"), this)); |
|
61 iNameRecordPckg.Set(reinterpret_cast<TUint8*>(&aName), sizeof(TNameRecord),sizeof(TNameRecord)); |
|
62 iWin32Message.Set(CWin32Resolver::EGetByName, iNameRecordPckg, aStatus); |
|
63 return MakeRequest(iWin32Message); |
|
64 } |
|
65 |
|
66 TInt RWin32Resolver::GetByAddress(TNameRecord& aName, TRequestStatus& aStatus) |
|
67 { |
|
68 WSP_LOG(WspLog::Printf(_L("RWin32Resolver::GetByAddress: this: 0x%x"), this)); |
|
69 iNameRecordPckg.Set(reinterpret_cast<TUint8*>(&aName), sizeof(TNameRecord),sizeof(TNameRecord)); |
|
70 iWin32Message.Set(CWin32Resolver::EGetByAddress, iNameRecordPckg, aStatus); |
|
71 return MakeRequest(iWin32Message); |
|
72 } |
|
73 |
|
74 void RWin32Resolver::Cancel() |
|
75 { |
|
76 WSP_LOG(WspLog::Printf(_L("RWin32Resolver::Cancel: this: 0x%x"), this)); |
|
77 TWin32Message cancelWin32Message; |
|
78 cancelWin32Message.Set(CWin32Resolver::ECancel); |
|
79 MakeRequest(cancelWin32Message); // Throw away return code - can't do anything useful with it. |
|
80 } |
|
81 |
|
82 |
|
83 // |
|
84 // CWin32Resolver. |
|
85 // |
|
86 |
|
87 CWin32Resolver* CWin32Resolver::NewL(CWin32Scheduler& aScheduler) |
|
88 { |
|
89 CWin32Resolver* self = new(ELeave) CWin32Resolver(aScheduler); |
|
90 CleanupStack::PushL(self); |
|
91 self->ConstructL(); |
|
92 CleanupStack::Pop(self); |
|
93 return self; |
|
94 } |
|
95 |
|
96 CWin32Resolver::CWin32Resolver(CWin32Scheduler& aScheduler) |
|
97 : CWin32SubSession(aScheduler) |
|
98 { |
|
99 } |
|
100 |
|
101 void CWin32Resolver::ConstructL() |
|
102 { |
|
103 CWin32SubSession::ConstructL(); |
|
104 } |
|
105 |
|
106 CWin32Resolver::~CWin32Resolver() |
|
107 { |
|
108 } |
|
109 |
|
110 void CWin32Resolver::Run() |
|
111 { |
|
112 iMessage->Complete(iError); |
|
113 iMessage = NULL; |
|
114 iWorkerThread.Close(); |
|
115 } |
|
116 |
|
117 void CWin32Resolver::ServiceL(TWin32Message& aMessage) |
|
118 { |
|
119 switch (aMessage.OppCode()) |
|
120 { |
|
121 case EGetByName: |
|
122 case EGetByAddress: |
|
123 { |
|
124 __ASSERT_DEBUG(iMessage == NULL, Panic(EWinSockPrtCWin32ResolverMultipleRequests)); |
|
125 iMessage = &aMessage; |
|
126 CreateWorkerThread(); |
|
127 break; |
|
128 } |
|
129 case ECancel: |
|
130 { |
|
131 Cancel(); |
|
132 break; |
|
133 } |
|
134 default: |
|
135 { |
|
136 __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtInvalidResolverOppCode)); |
|
137 } |
|
138 } |
|
139 } |
|
140 |
|
141 void CWin32Resolver::Cancel() |
|
142 { |
|
143 if (iWorkerThread.Handle() && (iWorkerThread.ExitType() == EExitPending)) |
|
144 { |
|
145 iWorkerThread.Kill(KErrCancel); |
|
146 iMessage->Complete(KErrCancel); |
|
147 iMessage = NULL; |
|
148 iWorkerThread.Close(); |
|
149 } |
|
150 } |
|
151 |
|
152 void CWin32Resolver::CreateWorkerThread() |
|
153 { |
|
154 TBuf<KWspResolverWorkerThreadNameLength> threadName; |
|
155 threadName.Format(KWspResolverWorkerThreadNameFormat, this, Math::Rand(iRandSeed)); |
|
156 TInt err = iWorkerThread.Create(threadName, WorkerThreadStart, KWspResolverWorkerThreadStackSize, NULL, this, EOwnerThread); |
|
157 if (err == KErrNone) |
|
158 { |
|
159 iWorkerThread.Resume(); |
|
160 } |
|
161 else |
|
162 { |
|
163 iMessage->Complete(err); |
|
164 } |
|
165 } |
|
166 |
|
167 |
|
168 // |
|
169 // CWin32Resolver worker thread methods. |
|
170 // |
|
171 |
|
172 TInt CWin32Resolver::WorkerThreadStart(TAny* aPtr) |
|
173 { |
|
174 CWin32Resolver* self = reinterpret_cast<CWin32Resolver*>(aPtr); |
|
175 |
|
176 switch (self->iMessage->OppCode()) |
|
177 { |
|
178 case EGetByName: |
|
179 { |
|
180 self->GetByName(); |
|
181 break; |
|
182 } |
|
183 case EGetByAddress: |
|
184 { |
|
185 self->GetByAddress(); |
|
186 break; |
|
187 } |
|
188 case ECancel: |
|
189 default: |
|
190 { |
|
191 __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtResolverInvalidWorkerThreadRequest)); |
|
192 } |
|
193 } |
|
194 |
|
195 return KErrNone; |
|
196 } |
|
197 |
|
198 void CWin32Resolver::GetByName() |
|
199 { |
|
200 TNameRecord& nameRecord = (TNameRecord&)*iMessage->WriteBuffer().Ptr(); |
|
201 struct hostent* hp; |
|
202 HBufC8* narrowHostNameBuf = HBufC8::New(nameRecord.iName.MaxLength() + 1); // Note, this is one bigger than the size of THostName to allow for a null termination character. |
|
203 if (narrowHostNameBuf == NULL) |
|
204 { |
|
205 iError = KErrNoMemory; |
|
206 } |
|
207 else |
|
208 { |
|
209 TPtr8 narrowHostNamePtr(narrowHostNameBuf->Des()); |
|
210 CnvUtfConverter::ConvertFromUnicodeToUtf8(narrowHostNamePtr, nameRecord.iName); |
|
211 hp = gethostbyname(reinterpret_cast<const char*>(narrowHostNamePtr.PtrZ())); |
|
212 delete narrowHostNameBuf; |
|
213 if (hp) |
|
214 { |
|
215 TInetAddr& addr = reinterpret_cast<TInetAddr&>(nameRecord.iAddr); |
|
216 __ASSERT_DEBUG(hp->h_addrtype == AF_INET, Panic(EWinSockPrtResolverInvalidFamily)); |
|
217 addr.SetFamily(KAfInet); |
|
218 __ASSERT_DEBUG(hp->h_length == 4, Panic(EWinSockPrtResolverInvalidAddressLength)); |
|
219 TUint32* address = (TUint32*)hp->h_addr_list[0]; |
|
220 addr.SetAddress(htonl(*address)); |
|
221 iError = KErrNone; |
|
222 } |
|
223 else |
|
224 { |
|
225 iError = KErrNotFound; |
|
226 } |
|
227 } |
|
228 |
|
229 if (!SetEvent(iEvent)) |
|
230 { |
|
231 __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtResolverUnexpectedSetEventError)); |
|
232 } |
|
233 } |
|
234 |
|
235 void CWin32Resolver::GetByAddress() |
|
236 { |
|
237 TNameRecord& nameRecord = (TNameRecord&)*iMessage->WriteBuffer().Ptr(); |
|
238 TInetAddr& addr = reinterpret_cast<TInetAddr&>(nameRecord.iAddr); |
|
239 struct hostent* hp; |
|
240 char addressBuf[4]; |
|
241 *((TUint32*)addressBuf) = htonl(addr.Address()); |
|
242 hp = gethostbyaddr(addressBuf, 4, AF_INET); |
|
243 if (hp) |
|
244 { |
|
245 TPtrC8 narrowAddressPtr((TUint8*)hp->h_name, User::StringLength((TUint8*)hp->h_name)); |
|
246 CnvUtfConverter::ConvertToUnicodeFromUtf8(nameRecord.iName, narrowAddressPtr); |
|
247 iError = KErrNone; |
|
248 } |
|
249 else |
|
250 { |
|
251 iError = KErrNotFound; |
|
252 } |
|
253 |
|
254 if (!SetEvent(iEvent)) |
|
255 { |
|
256 __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtResolverUnexpectedSetEventError)); |
|
257 } |
|
258 } |
|
259 |
|
260 |
|
261 // |
|
262 // CWin32ResolverWrapper. |
|
263 // |
|
264 |
|
265 CWin32ResolverWrapper* CWin32ResolverWrapper::NewL(MWin32ResolverObserver& aObserver, RWin32Factory& aWin32Factory) |
|
266 { |
|
267 CWin32ResolverWrapper* self = new(ELeave) CWin32ResolverWrapper(aObserver); |
|
268 CleanupStack::PushL(self); |
|
269 self->ConstructL(aWin32Factory); |
|
270 CleanupStack::Pop(self); |
|
271 return self; |
|
272 } |
|
273 |
|
274 CWin32ResolverWrapper::~CWin32ResolverWrapper() |
|
275 { |
|
276 Cancel(); |
|
277 iWin32Resolver.Close(); |
|
278 } |
|
279 |
|
280 CWin32ResolverWrapper::CWin32ResolverWrapper(MWin32ResolverObserver& aObserver) |
|
281 : CActive(CActive::EPriorityStandard), iObserver(aObserver) |
|
282 { |
|
283 } |
|
284 |
|
285 void CWin32ResolverWrapper::ConstructL(RWin32Factory& aWin32Factory) |
|
286 { |
|
287 User::LeaveIfError(iWin32Resolver.Open(aWin32Factory)); |
|
288 CActiveScheduler::Add(this); |
|
289 } |
|
290 |
|
291 TInt CWin32ResolverWrapper::GetByName(TNameRecord& aName) |
|
292 { |
|
293 __ASSERT_DEBUG(!IsActive(), Panic(EWinSockPrtResolverWrapperGetByNameWhilstActive)); |
|
294 TInt err = iWin32Resolver.GetByName(aName, iStatus); |
|
295 if (err == KErrNone) |
|
296 { |
|
297 SetActive(); |
|
298 } |
|
299 return err; |
|
300 } |
|
301 |
|
302 TInt CWin32ResolverWrapper::GetByAddress(TNameRecord& aName) |
|
303 { |
|
304 __ASSERT_DEBUG(!IsActive(), Panic(EWinSockPrtResolverWrapperGetByAddressWhilstActive)); |
|
305 TInt err = iWin32Resolver.GetByAddress(aName, iStatus); |
|
306 if (err == KErrNone) |
|
307 { |
|
308 SetActive(); |
|
309 } |
|
310 return err; |
|
311 } |
|
312 |
|
313 void CWin32ResolverWrapper::DoCancel() |
|
314 { |
|
315 iWin32Resolver.Cancel(); |
|
316 } |
|
317 |
|
318 void CWin32ResolverWrapper::RunL() |
|
319 { |
|
320 iObserver.HandleWin32ResolverCompletion(iStatus.Int()); |
|
321 } |
|
322 |
|
323 TInt CWin32ResolverWrapper::RunError(TInt /*aError*/) |
|
324 { |
|
325 __ASSERT_DEBUG(EFalse, Panic(EWinSockPrtResolverWrapperUnexpectedRunError)); |
|
326 return 0; |
|
327 } |
|
328 |
|
329 |
|
330 // |
|
331 // CWinSockResolver. |
|
332 // |
|
333 |
|
334 CWinSockResolver* CWinSockResolver::NewL(RWin32Factory& aFactory) |
|
335 { |
|
336 CWinSockResolver* self = new(ELeave) CWinSockResolver(); |
|
337 CleanupStack::PushL(self); |
|
338 self->ConstructL(aFactory); |
|
339 CleanupStack::Pop(self); |
|
340 return self; |
|
341 } |
|
342 |
|
343 CWinSockResolver::~CWinSockResolver() |
|
344 { |
|
345 delete iResolverWrapper; |
|
346 } |
|
347 |
|
348 void CWinSockResolver::CancelCurrentOperation() |
|
349 { |
|
350 iResolverWrapper->Cancel(); |
|
351 } |
|
352 |
|
353 void CWinSockResolver::GetByName(TNameRecord& aName) |
|
354 { |
|
355 iResolverWrapper->GetByName(aName); |
|
356 } |
|
357 |
|
358 void CWinSockResolver::GetByAddress(TNameRecord& aName) |
|
359 { |
|
360 iResolverWrapper->GetByAddress(aName); |
|
361 } |
|
362 |
|
363 void CWinSockResolver::SetHostName(TDes& /*aNameBuf*/) |
|
364 { |
|
365 // TODO: |
|
366 ASSERT(EFalse); |
|
367 } |
|
368 |
|
369 void CWinSockResolver::GetHostName(TDes& /*aNameBuf*/) |
|
370 { |
|
371 // TODO: |
|
372 ASSERT(EFalse); |
|
373 } |
|
374 |
|
375 void CWinSockResolver::HandleWin32ResolverCompletion(TInt aError) |
|
376 { |
|
377 iNotify->QueryComplete(aError); |
|
378 } |
|
379 |
|
380 CWinSockResolver::CWinSockResolver() |
|
381 { |
|
382 } |
|
383 |
|
384 void CWinSockResolver::ConstructL(RWin32Factory& aFactory) |
|
385 { |
|
386 iResolverWrapper = CWin32ResolverWrapper::NewL(*this, aFactory); |
|
387 } |