|
1 // Copyright (c) 2002-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 // This defines the CTS_MultiHomingSuite class which is the |
|
15 // container class for the TS_MultiHomingStep-derived test steps |
|
16 // |
|
17 // |
|
18 |
|
19 /** |
|
20 @file |
|
21 */ |
|
22 |
|
23 #include "TS_MultiHomingSuite.h" |
|
24 #include "TS_RConnectionStart.h" |
|
25 #include "TS_RConnectionClose.h" |
|
26 #include "TS_RConnectionStop.h" |
|
27 #include "TS_TestConnection.h" |
|
28 #ifdef SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING |
|
29 #include "ts_testincomming.h" |
|
30 #endif //SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING |
|
31 #include "TS_CopyComDbFile.h" |
|
32 #include "TS_ShowConnections.h" |
|
33 #include "TS_ResolveName.h" |
|
34 #include "TS_ResolveAddress.h" |
|
35 #include "TS_GetConnectionInfo.h" |
|
36 #include "TS_CheckLinkLocalSame.h" |
|
37 #include "TS_Delay.h" |
|
38 #include <e32cons.h> |
|
39 #include <in_sock.h> |
|
40 #include <in_iface.h> |
|
41 #include <nifman.h> |
|
42 |
|
43 |
|
44 EXPORT_C CTS_MultiHomingSuite* NewTS_MultiHomingSuite( void ) |
|
45 /** Polymorphic interface, exported ordinal 1. Called by scheduletest |
|
46 * and used to instantiate the suite |
|
47 * @return A pointer to the created CTS_MultiHomingSuite object |
|
48 */ |
|
49 { |
|
50 CTS_MultiHomingSuite* ts = 0; |
|
51 TRAPD(err,ts = new (ELeave) CTS_MultiHomingSuite); |
|
52 if (err == KErrNone) |
|
53 return ts; |
|
54 return 0; |
|
55 } |
|
56 |
|
57 CTS_MultiHomingSuite::~CTS_MultiHomingSuite() |
|
58 /** |
|
59 * Destructor has to clean up any TConnDetails left hanging around |
|
60 * |
|
61 */ |
|
62 { |
|
63 delete iScheduler; |
|
64 } |
|
65 |
|
66 void CTS_MultiHomingSuite::AddTestStepL( CTS_MultiHomingStep* ptrTestStep ) |
|
67 /** |
|
68 * Adds a test step to the test suite object, using the base class method |
|
69 * @param ptrTestStep A pointer to the test step to be added |
|
70 * @exception Can leave |
|
71 */ |
|
72 { |
|
73 ptrTestStep->iOwnerSuite = this; |
|
74 CTestSuite::AddTestStepL(ptrTestStep); |
|
75 } |
|
76 |
|
77 void CTS_MultiHomingSuite::InitialiseL( void ) |
|
78 /** |
|
79 * Effective second-phase constructor. Creates all suite test steps |
|
80 * and associates them with the suite. |
|
81 */ |
|
82 { |
|
83 // Load the serial drivers |
|
84 TInt ret = User::LoadPhysicalDevice(PDD_NAME); |
|
85 if ( KErrNone != ret && KErrAlreadyExists != ret ) |
|
86 { |
|
87 User::Leave( ret ); |
|
88 } |
|
89 |
|
90 ret = User::LoadLogicalDevice(LDD_NAME); |
|
91 if ( KErrNone != ret && KErrAlreadyExists != ret ) |
|
92 { |
|
93 User::Leave( ret ); |
|
94 } |
|
95 |
|
96 // When bootstrapping C32 we have to avoid the PhBkSyncServer being started, since |
|
97 // it needs a different CommDB |
|
98 _LIT(KPhbkSyncCMI, "phbsync.cmi"); |
|
99 ret = StartC32WithCMISuppressions(KPhbkSyncCMI); |
|
100 if ( KErrNone != ret && KErrAlreadyExists != ret ) |
|
101 { |
|
102 User::Leave( ret ); |
|
103 } |
|
104 |
|
105 //Make the scheduler... |
|
106 |
|
107 iScheduler=new(ELeave) CEnhancedScheduler(); |
|
108 CEnhancedScheduler::Install(iScheduler); |
|
109 |
|
110 |
|
111 // Add Test steps |
|
112 AddTestStepL( new(ELeave) CTS_RConnectionStart ); |
|
113 AddTestStepL( new(ELeave) CTS_RConnectionClose ); |
|
114 AddTestStepL( new(ELeave) CTS_RConnectionStop ); |
|
115 AddTestStepL( new(ELeave) CTS_TestConnection ); |
|
116 |
|
117 #ifdef SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING |
|
118 AddTestStepL( new(ELeave) CTS_TestIncomming ); |
|
119 #endif //SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING |
|
120 AddTestStepL( new(ELeave) CTS_ShowConnections ); |
|
121 AddTestStepL( new(ELeave) CTS_ResolveName ); |
|
122 AddTestStepL( new(ELeave) CTS_ResolveAddress ); |
|
123 AddTestStepL( new(ELeave) CTS_GetConnectionInfo ); |
|
124 AddTestStepL( new(ELeave) CTS_CheckLinkLocalSame ); |
|
125 AddTestStepL( new(ELeave) CTS_CopyComDbFile ); |
|
126 AddTestStepL( new(ELeave) CTS_Delay ); |
|
127 } |
|
128 |
|
129 |
|
130 TPtrC CTS_MultiHomingSuite::GetVersion( void ) |
|
131 /** |
|
132 * Give version information back to Schedultest |
|
133 * @return The descriptor of the version |
|
134 */ |
|
135 { |
|
136 return KTxtVersion(); |
|
137 } |
|
138 |
|
139 |
|
140 TInt CTS_MultiHomingSuite::GetConnIndex(const TDesC& aName) |
|
141 /** |
|
142 * Gets the array index of the name passed in |
|
143 * @param aName Descriptor containing the connection name to match |
|
144 * @return The index, or KErrNotFound |
|
145 */ |
|
146 { |
|
147 for (TInt i=0; i < CTS_MultiHomingSuite::MAX_CONNECTIONS; i++) |
|
148 { |
|
149 if (iConnections[i].MatchName(aName)) |
|
150 return i; |
|
151 } |
|
152 return KErrNotFound; |
|
153 } |
|
154 |
|
155 |
|
156 TConnDetails *CTS_MultiHomingSuite::GetNewTConnection( ) |
|
157 /** |
|
158 * Retreive |
|
159 * |
|
160 */ |
|
161 { |
|
162 for (TInt i=0; i < CTS_MultiHomingSuite::MAX_CONNECTIONS; i++) |
|
163 { |
|
164 if (iConnections[i].iName.Length() == 0) |
|
165 return &iConnections[i]; |
|
166 } |
|
167 return 0; |
|
168 } |
|
169 |
|
170 TInt CTS_MultiHomingSuite::AddConnection(const TConnDetails& aConn) |
|
171 /** |
|
172 * Appends a connection to the array of connections in the suite |
|
173 * @param aName Reference to the object to pass in |
|
174 * @return System wide error code |
|
175 */ |
|
176 { |
|
177 TInt err= KErrNone; // Check the name doesn't already exist |
|
178 TInt connIndex = GetConnIndex(aConn.iName); |
|
179 if(KErrNotFound == connIndex) |
|
180 { |
|
181 //err = iConnections.Append(aConn); |
|
182 } |
|
183 else |
|
184 { |
|
185 err = KErrAlreadyExists; |
|
186 _LIT(KMultipleConns, "Connection has already been started. Check configuration files."); |
|
187 LogExtra((TText8*)__FILE__, __LINE__, ESevrInfo, KMultipleConns); |
|
188 } |
|
189 |
|
190 return err; |
|
191 } |
|
192 |
|
193 TConnDetails *CTS_MultiHomingSuite::GetTConnection(const TDesC& aName) |
|
194 /** |
|
195 * Returns the TConnection object for a specific connection |
|
196 * @param aName Name of connection to look up |
|
197 * @return The RConnection object |
|
198 */ |
|
199 |
|
200 { |
|
201 TInt err= KErrNone; |
|
202 err = GetConnIndex(aName); |
|
203 if (err == KErrNotFound) |
|
204 { |
|
205 //User::Panic(KTxtSuiteName, err); |
|
206 return 0; |
|
207 } |
|
208 return &iConnections[err]; |
|
209 } |
|
210 |
|
211 RConnection *CTS_MultiHomingSuite::GetRConnection(const TDesC& aName) |
|
212 /** |
|
213 * Returns the RConnection object for a specific connection |
|
214 * @param aName Name of connection to look up |
|
215 * @return The RConnection object |
|
216 */ |
|
217 { |
|
218 TInt err= KErrNone; |
|
219 err = GetConnIndex(aName); |
|
220 if (err == KErrNotFound) |
|
221 { |
|
222 //User::Panic(KTxtSuiteName, err); |
|
223 return 0; |
|
224 } |
|
225 return &iConnections[err].iConnection; |
|
226 } |
|
227 |
|
228 RSocketServ *CTS_MultiHomingSuite::GetRSocketServ(const TDesC& aName) |
|
229 /** |
|
230 * Returns the RSocketServ object for a specific connection |
|
231 * @param aName Name of connection to look up |
|
232 * @return The RSocketServ object |
|
233 */ |
|
234 { |
|
235 TInt connIndex = -1; |
|
236 |
|
237 connIndex = GetConnIndex(aName); |
|
238 if (connIndex < 0) |
|
239 { |
|
240 return 0; |
|
241 } |
|
242 return &iConnections[connIndex].iSocketServ; |
|
243 } |
|
244 |
|
245 |
|
246 TInt CTS_MultiHomingSuite::CloseConnection(const TDesC& aName) |
|
247 /** |
|
248 * Closes a connection and removes it from the array |
|
249 * @param aName The name of the connection to close |
|
250 * @return System wide error code |
|
251 */ |
|
252 { |
|
253 TInt index= KErrNone; |
|
254 index= GetConnIndex(aName); |
|
255 if (index != KErrNotFound) |
|
256 { |
|
257 if (iConnections[index].iClients == 0) // No open sockets, so can close |
|
258 { |
|
259 if(iConnections[index].iConnectionType |
|
260 != TConnDetails::implicitConn) |
|
261 { |
|
262 iConnections[index].iConnection.Close(); |
|
263 } |
|
264 else |
|
265 { |
|
266 iConnections[index].iSocket.Close(); |
|
267 } |
|
268 |
|
269 iConnections[index].iSocketServ.Close(); |
|
270 iConnections[index].iName.Zero(); |
|
271 return KErrNone; |
|
272 } |
|
273 return KErrInUse; |
|
274 } |
|
275 return index; |
|
276 } |
|
277 |
|
278 |
|
279 TInt CTS_MultiHomingSuite::StopConnection(const TDesC& aName) |
|
280 /** |
|
281 * Closes a connection and removes it from the array |
|
282 * @param aName The name of the connection to close |
|
283 * @return System wide error code |
|
284 */ |
|
285 { |
|
286 TInt index= KErrNone; |
|
287 index= GetConnIndex(aName); |
|
288 if (index != KErrNotFound) |
|
289 { |
|
290 if (iConnections[index].iClients == 0) // No open sockets, so can close |
|
291 { |
|
292 if(iConnections[index].iConnectionType |
|
293 != TConnDetails::implicitConn) |
|
294 { |
|
295 iConnections[index].iConnection.Stop(); //< Any connections present killed |
|
296 } |
|
297 else |
|
298 { |
|
299 iConnections[index].iSocket.Close(); |
|
300 } |
|
301 |
|
302 iConnections[index].iSocketServ.Close(); |
|
303 iConnections[index].iName.Zero(); |
|
304 return KErrNone; |
|
305 } |
|
306 return KErrInUse; |
|
307 } |
|
308 return index; |
|
309 } |
|
310 |
|
311 |
|
312 inline void RemoveScopeFromAddress(TName& address) |
|
313 { |
|
314 TChar percent('%'); |
|
315 TInt percentIndex = address.Locate(percent); |
|
316 |
|
317 if( percentIndex >= 0 ) |
|
318 { |
|
319 address.SetLength(percentIndex); |
|
320 } |
|
321 } |
|
322 |
|
323 TInt CTS_MultiHomingSuite::DisplayConnectionDetailsL() |
|
324 /** |
|
325 * Displays the IP interfaces that are currently in the system |
|
326 * @return number of non loopback interfaces |
|
327 */ |
|
328 { |
|
329 TInt err = KErrNone; |
|
330 for (TInt i=0; i < CTS_MultiHomingSuite::MAX_CONNECTIONS; i++) |
|
331 { |
|
332 if(iConnections[i].iName.Length() == 0) |
|
333 { |
|
334 continue; |
|
335 } |
|
336 _LIT (KConnLogString, "Name [%S], RConnection[%x], RSocketServ[%x]"); |
|
337 Log(KConnLogString, &iConnections[i].iName, |
|
338 &iConnections[i].iConnection, |
|
339 &iConnections[i].iSocketServ); |
|
340 |
|
341 } |
|
342 |
|
343 TAutoClose<RSocketServ> ss; |
|
344 err = ss.iObj.Connect(); |
|
345 ss.PushL(); |
|
346 |
|
347 TAutoClose<RSocket> sock; |
|
348 err = sock.iObj.Open(ss.iObj, _L("udp")); |
|
349 |
|
350 sock.PushL(); |
|
351 |
|
352 User::LeaveIfError(sock.iObj.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl)); |
|
353 |
|
354 TProtocolDesc in; |
|
355 User::LeaveIfError(sock.iObj.Info(in)); |
|
356 //LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("EPOC32 IP Stack Version %d.%d.%d ---- INTERFACE START"), in.iVersion.iMajor, in.iVersion.iMinor, in.iVersion.iBuild); |
|
357 |
|
358 |
|
359 TPckgBuf<TSoInetInterfaceInfo> info; |
|
360 |
|
361 err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info); |
|
362 // The first interface is always empty |
|
363 err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info); |
|
364 TInt numberOfInterfaces = 0; |
|
365 while(err == KErrNone) |
|
366 { |
|
367 // Skip loopback interfaces |
|
368 if(info().iFeatures & KIfIsLoopback || info().iState != EIfUp) |
|
369 { |
|
370 err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info); |
|
371 continue; |
|
372 } |
|
373 |
|
374 |
|
375 TBuf <MAX_LOG_LINE_LENGTH> LineBuf; |
|
376 |
|
377 |
|
378 LineBuf.AppendFormat(_L("%S: Tag: \"%S\" is ") |
|
379 ,&info().iName |
|
380 ,&info().iTag); |
|
381 |
|
382 LineBuf.Append(info().iState == EIfPending ? _L("PENDING") : |
|
383 info().iState == EIfUp ? _L("UP") : |
|
384 info().iState == EIfDown ? _L("DOWN") : |
|
385 info().iState == EIfBusy ? _L("BUSY") : |
|
386 _L("UNDEFINED_STATE")); |
|
387 LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, LineBuf); |
|
388 |
|
389 LineBuf.Zero(); |
|
390 LineBuf.AppendFormat(_L("%S: "), &info().iName); |
|
391 |
|
392 LineBuf.AppendFormat(_L("Mtu: %d Speed: %d "), info().iMtu, info().iSpeedMetric); |
|
393 LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, LineBuf); |
|
394 |
|
395 LineBuf.Zero(); |
|
396 LineBuf.AppendFormat(_L("%S: "), &info().iName); |
|
397 |
|
398 |
|
399 TName address; |
|
400 info().iAddress.Output(address); |
|
401 LineBuf.Append(_L("Address ")); |
|
402 //RemoveScopeFromAddress(address); |
|
403 LineBuf.Append(address); |
|
404 TName netmask; |
|
405 info().iNetMask.OutputWithScope(netmask); |
|
406 LineBuf.Append(_L("/")); |
|
407 LineBuf.Append(netmask); |
|
408 info().iAddress.IsLinkLocal() ? LineBuf.Append(_L(" is Link local")) : |
|
409 info().iAddress.IsSiteLocal() ? LineBuf.Append(_L(" is Site local")) : |
|
410 LineBuf.Append(_L(" is Global")); |
|
411 |
|
412 |
|
413 LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, LineBuf); |
|
414 LineBuf.Zero(); |
|
415 LineBuf.AppendFormat(_L("%S: "), &info().iName); |
|
416 |
|
417 |
|
418 info().iBrdAddr.Output(address); |
|
419 //RemoveScopeFromAddress(address); |
|
420 TChar colon(':'); |
|
421 // Assume single IPv4 addres per interface |
|
422 if(address.Locate(colon) < 0) |
|
423 { |
|
424 numberOfInterfaces++; |
|
425 } |
|
426 // 2 == :: ie zeros |
|
427 if(address.Length() > 3) |
|
428 LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("%S: Broadcast address %S"), &info().iName, &address); |
|
429 info().iDefGate.Output(address); |
|
430 //RemoveScopeFromAddress(address); |
|
431 if(address.Length() > 3) |
|
432 LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("%S: Default gateway %S"), &info().iName, &address); |
|
433 info().iNameSer1.Output(address); |
|
434 //RemoveScopeFromAddress(address); |
|
435 if(address.Length() > 3) |
|
436 LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("%S: Primary DNS %S"), &info().iName, &address); |
|
437 info().iNameSer2.Output(address); |
|
438 //RemoveScopeFromAddress(address); |
|
439 if(address.Length() > 3) |
|
440 LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("%S: Secondary DNS %S"), &info().iName, &address); |
|
441 |
|
442 |
|
443 |
|
444 if(info().iFeatures & KIfIsLoopback) |
|
445 { |
|
446 LineBuf.Append(_L(" LOOPBACK")); |
|
447 } |
|
448 if(info().iFeatures & KIfIsDialup) |
|
449 { |
|
450 LineBuf.Append(_L(" DIALUP")); |
|
451 } |
|
452 if(info().iFeatures & KIfIsPointToPoint) |
|
453 { |
|
454 LineBuf.Append(_L(" POINTTOPOINT")); |
|
455 } |
|
456 if(info().iFeatures & KIfCanBroadcast) |
|
457 { |
|
458 LineBuf.Append(_L(" BROADCAST")); |
|
459 } |
|
460 |
|
461 if(info().iFeatures & KIfCanMulticast) |
|
462 { |
|
463 LineBuf.Append(_L(" MULTICASTCAST")); |
|
464 } |
|
465 if(info().iFeatures & KIfCanSetMTU) |
|
466 { |
|
467 LineBuf.Append(_L(" SETMTU")); |
|
468 } |
|
469 if(info().iFeatures & KIfCanSetHardwareAddr) |
|
470 { |
|
471 LineBuf.Append(_L(" CANSETHWADDR")); |
|
472 } |
|
473 |
|
474 LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, LineBuf); |
|
475 LineBuf.Zero(); |
|
476 |
|
477 |
|
478 if(info().iFeatures & KIfHasHardwareAddr) |
|
479 { |
|
480 LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L(" Hardware address ")); |
|
481 TUint j; |
|
482 for(j=sizeof(SSockAddr) ; j<sizeof(SSockAddr)+6 ; ++j) |
|
483 { |
|
484 if(j<(TUint)info().iHwAddr.Length()) |
|
485 LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("%02X"), info().iHwAddr[j]); |
|
486 else |
|
487 LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("??")); |
|
488 if(j<sizeof(SSockAddr)+5) |
|
489 LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("-")); |
|
490 else |
|
491 LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("")); |
|
492 } |
|
493 } |
|
494 err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info); |
|
495 |
|
496 } |
|
497 |
|
498 sock.Pop(); |
|
499 ss.Pop(); |
|
500 |
|
501 // LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("EPOC32 IP Stack Version %d.%d.%d ---- INTERFACE LIST END"), in.iVersion.iMajor, in.iVersion.iMinor, in.iVersion.iBuild); |
|
502 |
|
503 return numberOfInterfaces; |
|
504 } |
|
505 |
|
506 |
|
507 /** |
|
508 * Compares first two non-loopback link-local addresses |
|
509 * @return TRUE if equal else FALSE |
|
510 */ |
|
511 TBool CTS_MultiHomingSuite::CompareLinkLocalAddressesL() |
|
512 { |
|
513 |
|
514 TName addresses[2]; |
|
515 TAutoClose<RSocketServ> ss; |
|
516 TInt err = ss.iObj.Connect(); |
|
517 ss.PushL(); |
|
518 TAutoClose<RSocket> sock; |
|
519 err = sock.iObj.Open(ss.iObj, _L("udp")); |
|
520 sock.PushL(); |
|
521 |
|
522 User::LeaveIfError(sock.iObj.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl)); |
|
523 |
|
524 TPckgBuf<TSoInetInterfaceInfo> info; |
|
525 err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info); |
|
526 // The first interface is always empty |
|
527 err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info); |
|
528 |
|
529 TInt i = 0; |
|
530 while((i < 2) && (err== KErrNone)) |
|
531 { |
|
532 // Skip loopback interfaces |
|
533 if(info().iFeatures & KIfIsLoopback) |
|
534 { |
|
535 err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info); |
|
536 continue; |
|
537 } |
|
538 |
|
539 if (info().iAddress.IsLinkLocal()) |
|
540 { |
|
541 //TName address; |
|
542 //addresses[i].FillZ(); |
|
543 info().iAddress.Output(addresses[i]); |
|
544 RemoveScopeFromAddress(addresses[i]); |
|
545 i++; |
|
546 } |
|
547 |
|
548 err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info); |
|
549 } |
|
550 |
|
551 sock.Pop(); |
|
552 ss.Pop(); |
|
553 |
|
554 if ((i == 2) && (addresses[0].Compare(addresses[1]) == 0)) |
|
555 return TRUE; |
|
556 return FALSE; |
|
557 } |
|
558 |