|
1 /* |
|
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "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 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * Filename: UCCSServMgr.cpp |
|
16 * System Includes |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 |
|
22 #include <string.h> |
|
23 #include <stdio.h> |
|
24 #include <stdlib.h> |
|
25 #include <assert.h> |
|
26 |
|
27 |
|
28 /*********************************************************************************** |
|
29 * |
|
30 * Local Includes |
|
31 * |
|
32 **********************************************************************************/ |
|
33 #include "strncpynt.h" |
|
34 #include "UCCS_CServMgr.h" |
|
35 #include "UCCS_ErrorCodes.h" |
|
36 #include "UCCS_ServiceValues.h" |
|
37 #include "../ServiceStubs/Mobster.v2/CMobsterStub.h" |
|
38 #include "../ServiceStubs/Internal/CInternalStub.h" |
|
39 #include "../ServiceStubs/Ppp/CPppControllerStub.h" |
|
40 #include "../ServiceStubs/HostExecute/CHostExecuteStub.h" |
|
41 #include "../ServiceStubs/UuInterface/CUuinterfaceStub.h" |
|
42 #include "../ServiceStubs/MobileAgent/CMobileAgentServiceStub.h" |
|
43 #include "../ServiceStubs/ForeignAgent/CForeignAgentServiceStub.h" |
|
44 #include "../ServiceStubs/HomeAgent/CHomeAgentServiceStub.h" |
|
45 #include "../ServiceStubs/HostExecuteAsync/CHostExecuteAsyncStub.h" |
|
46 #include "../ServiceStubs/Test/CTestStub.h" |
|
47 //#include "..\ServiceStubs\TestService\CTestServiceStub.h" |
|
48 #include "../ServiceStubs/GPSSimulator/CAPICommandHandlerStub.h" |
|
49 #include "../ServiceStubs/GenericStub/CGenericStub.h" |
|
50 //#include "..\..\include\penstd.h" |
|
51 #include "CUCCIniFile.h" |
|
52 |
|
53 /*********************************************************************************** |
|
54 * |
|
55 * Definitions |
|
56 * |
|
57 **********************************************************************************/ |
|
58 #define UCC_INI_FILE ".\\UCC.ini" |
|
59 #define SERVICE_INI "ini" |
|
60 #define SERVICE_HOST "host" |
|
61 |
|
62 #define STARTUP_GENERIC_SERVICE_STUB(rpcid,ini,servicename) \ |
|
63 service = iServiceList[localserviceindex] = new CGenericStub(ini,servicename); \ |
|
64 assert( service != NULL ); \ |
|
65 localerror = remoteerror = 0; \ |
|
66 rv = service->StartUccsService( aServiceHost, &localerror, &remoteerror ); \ |
|
67 if( rv != 0 ) { \ |
|
68 delete iServiceList[localserviceindex]; \ |
|
69 iServiceList[localserviceindex] = NULL; \ |
|
70 } else { \ |
|
71 strcpy( iServiceDescTable[localserviceindex].iHostname, aServiceHost ); \ |
|
72 iServiceDescTable[localserviceindex].iServiceID = rpcid; \ |
|
73 } \ |
|
74 break; |
|
75 |
|
76 #define STARTUP_SERVICE_STUB(rpcid,classname) \ |
|
77 service = iServiceList[localserviceindex] = new classname(); \ |
|
78 assert( service != NULL ); \ |
|
79 localerror = remoteerror = 0; \ |
|
80 rv = service->StartUccsService( aServiceHost, &localerror, &remoteerror ); \ |
|
81 if( rv != 0 ) { \ |
|
82 delete iServiceList[localserviceindex]; \ |
|
83 iServiceList[localserviceindex] = NULL; \ |
|
84 } else { \ |
|
85 strcpy( iServiceDescTable[localserviceindex].iHostname, aServiceHost ); \ |
|
86 iServiceDescTable[localserviceindex].iServiceID = rpcid; \ |
|
87 } |
|
88 |
|
89 #define STARTUP_SERVICE_STUB_CASE(rpcid,classname) case rpcid: \ |
|
90 STARTUP_SERVICE_STUB(rpcid, classname); \ |
|
91 break; |
|
92 |
|
93 #define SHUTDOWN_SERVICE_STUB(rpcid,classname) \ |
|
94 delete ((classname*)(iServiceList[aLocalServiceID])); \ |
|
95 iServiceList[aLocalServiceID] = NULL; \ |
|
96 iServiceDescTable[aLocalServiceID].iHostname[0] = 0; \ |
|
97 iServiceDescTable[aLocalServiceID].iServiceID = RPCSVC_INVALID; |
|
98 |
|
99 #define SHUTDOWN_SERVICE_STUB_CASE(rpcid,classname) case rpcid: \ |
|
100 SHUTDOWN_SERVICE_STUB(rpcid, classname); \ |
|
101 break; |
|
102 |
|
103 /*********************************************************************************** |
|
104 * |
|
105 * Construction |
|
106 * |
|
107 **********************************************************************************/ |
|
108 CServiceManager::CServiceManager( IOutput *aOutput ) |
|
109 : iNumGenericServices(0) |
|
110 { |
|
111 // verify the params |
|
112 assert( aOutput != NULL ); |
|
113 iOutput = aOutput; |
|
114 |
|
115 // initialise the service list |
|
116 for( int i = 0; i <= MAXSERVICES; i++ ) { |
|
117 iServiceList[i] = NULL; |
|
118 } |
|
119 |
|
120 // *** This need refactoring into a private method *** |
|
121 // Open the ucc.ini file |
|
122 CUCCIniFile iniFile(UCC_INI_FILE); |
|
123 vector<string> sections = iniFile.SectionNames(); |
|
124 |
|
125 // Check to see if there are any sections defined |
|
126 iNumGenericServices = sections.size(); |
|
127 if( iNumGenericServices > 0 && iNumGenericServices<(MAXSERVICES-RPCSVC_LAST) ) |
|
128 { |
|
129 for( int i=0 ; i<iNumGenericServices ; i++ ) |
|
130 { |
|
131 // *** No error checking currently *** |
|
132 |
|
133 // Set the service IID to the next available one |
|
134 iGenericServices[i].iServiceID = RPCSVC_LAST+i; |
|
135 |
|
136 // Set the service name to the section name |
|
137 strcpy( iGenericServices[i].iServiceName, sections[i].c_str() ); |
|
138 |
|
139 // Retrieve the ini file location |
|
140 string service_ini; |
|
141 bool ret = iniFile.KeyValue(SERVICE_INI, sections[i].c_str(), service_ini); |
|
142 assert( ret == true ); |
|
143 assert( service_ini.size() > 0 ); |
|
144 strcpy( iGenericServices[i].iIniFile, service_ini.c_str() ); |
|
145 |
|
146 // Retrieve the host name/ip address |
|
147 string host; |
|
148 ret = iniFile.KeyValue(SERVICE_HOST, sections[i].c_str(), host); |
|
149 assert( ret == true ); |
|
150 assert( host.size() > 0 ); |
|
151 strcpy( iGenericServices[i].iHost, host.c_str() ); |
|
152 } |
|
153 } |
|
154 } |
|
155 |
|
156 |
|
157 /*********************************************************************************** |
|
158 * |
|
159 * Destruction |
|
160 * |
|
161 **********************************************************************************/ |
|
162 CServiceManager::~CServiceManager() |
|
163 { |
|
164 // shutdown all loaded services -- log any errors |
|
165 ShutdownAll(); |
|
166 |
|
167 // verify all services are stopped (or trying to connect) |
|
168 for( int i = 0; i < MAXSERVICES; i++ ) { |
|
169 assert( (iServiceList[i] == NULL) || (iServiceDescTable[i].iServiceID == RPCSVC_INVALID) ); |
|
170 } |
|
171 } |
|
172 |
|
173 |
|
174 /*********************************************************************************** |
|
175 * |
|
176 * ShutdownAll - Close the connections to all services |
|
177 * |
|
178 **********************************************************************************/ |
|
179 int CServiceManager::ShutdownAll() |
|
180 { |
|
181 int localserviceindex = 0; |
|
182 |
|
183 //check each service and if it is alive then stop it |
|
184 for( localserviceindex = 0; localserviceindex < MAXSERVICES; localserviceindex++ ) { |
|
185 if( iServiceList[localserviceindex] != NULL ) { |
|
186 LocalStopService( localserviceindex ); |
|
187 } |
|
188 } |
|
189 return UCCS_OK; |
|
190 } |
|
191 |
|
192 |
|
193 /*********************************************************************************** |
|
194 * |
|
195 * PUBLIC METHOD: ResetService -- resets a service by starting then stopping it |
|
196 * |
|
197 **********************************************************************************/ |
|
198 int CServiceManager::ResetService( int aServiceID, char *aHostname ) |
|
199 { |
|
200 assert( !"Method withdrawn" ); |
|
201 return 0; |
|
202 } |
|
203 |
|
204 |
|
205 /*********************************************************************************** |
|
206 * |
|
207 * PUBLIC METHOD: ResetAllServices -- resets all the services in the oldservices |
|
208 * list |
|
209 * |
|
210 **********************************************************************************/ |
|
211 int CServiceManager::ResetAllServices() |
|
212 { |
|
213 assert( !"Method withdrawn" ); |
|
214 return 0; |
|
215 } |
|
216 |
|
217 |
|
218 /*********************************************************************************** |
|
219 * |
|
220 * PUBLIC METHOD: IssueCommand -- sends the command to the appropriate service |
|
221 * |
|
222 **********************************************************************************/ |
|
223 int CServiceManager::IssueCommand( CDataRecord* aRequestRecord, CDataRecord** aReturnedDataRecord ) |
|
224 { |
|
225 int returncode = ERR_NONE; |
|
226 int service_id; |
|
227 int err; |
|
228 int service_index; |
|
229 char *service_name; |
|
230 char *service_host; |
|
231 IService *service = NULL; |
|
232 |
|
233 // ensure that the passed buffer is set to NULL |
|
234 assert( *aReturnedDataRecord == NULL ); |
|
235 |
|
236 |
|
237 // Look for the service name initially |
|
238 // if the name doesn't exist then revert to the legacy method |
|
239 err = aRequestRecord->GetFieldAsString( "SVCNAME", &service_name ); |
|
240 if( err == UCCS_OK ) { |
|
241 // If a generic service is being used then retrieve the |
|
242 // service id and service name from the generic services list. |
|
243 bool found = false; |
|
244 for( int i=0; i<iNumGenericServices; i++ ) |
|
245 { |
|
246 if( strcmp(iGenericServices[i].iServiceName, service_name) == 0 ) |
|
247 { |
|
248 service_id = iGenericServices[i].iServiceID; |
|
249 service_host = iGenericServices[i].iHost; |
|
250 found = true; |
|
251 break; |
|
252 } |
|
253 } |
|
254 if (!found) |
|
255 return UCCS_NO_MATCHING_GENERIC_SERVICE_FOUND; |
|
256 } |
|
257 else |
|
258 { |
|
259 // retrieve the service id for the request |
|
260 err = aRequestRecord->GetFieldAsInt( "SVCID", &service_id ); |
|
261 if( err != UCCS_OK ) { |
|
262 return UCCS_NOSERVICEID; |
|
263 } |
|
264 |
|
265 // verify that this is a valid service id |
|
266 if( (service_id <= RPCSVC_INVALID) || (service_id >= RPCSVC_LAST+iNumGenericServices) ) { |
|
267 return UCCS_INVALIDSERVICEID; |
|
268 } |
|
269 |
|
270 // retrieve the hostname for the request |
|
271 err = aRequestRecord->GetFieldAsString( "SVCHOST", &service_host ); |
|
272 if( err != UCCS_OK ) { |
|
273 return UCCS_NOSERVICEHOST; |
|
274 } |
|
275 } |
|
276 |
|
277 // execute command |
|
278 // - performed within a loop to provide for a retry mechanism (eg. after new RPC connetion established) |
|
279 for (int i=0; i < 2; i++) |
|
280 { |
|
281 service_index = GetLocalServiceIndex( service_id, service_host ); |
|
282 if( service_index == -1 ) |
|
283 { |
|
284 // start service (RPC connect) |
|
285 err = LocalStartService(service_id, service_host); |
|
286 if (err != UCCS_OK) |
|
287 return err; |
|
288 service_index = GetLocalServiceIndex( service_id, service_host ); |
|
289 } |
|
290 |
|
291 // get a pointer to the service |
|
292 assert( service_index != -1 ); |
|
293 service = iServiceList[service_index]; |
|
294 assert( service != NULL ); |
|
295 |
|
296 // now issue the command to the service |
|
297 *aReturnedDataRecord = service->IssueCommand( aRequestRecord ); |
|
298 |
|
299 // Check the completion code and result |
|
300 int completion_code = ERR_NONE; |
|
301 err = (*aReturnedDataRecord)->GetFieldAsInt( STD_REPLY_FIELD_REQUESTCOMPLETIONCODE, &completion_code ); |
|
302 if( err == UCCS_OK ) |
|
303 { |
|
304 // If the completion code is ok, check the call result |
|
305 if( completion_code == ERR_NONE ) |
|
306 { |
|
307 int call_result = ERR_NONE; |
|
308 err = (*aReturnedDataRecord)->GetFieldAsInt( "RESULT", &call_result ); |
|
309 if( err == UCCS_OK ) |
|
310 { |
|
311 returncode = call_result; |
|
312 break; // no need to retry since it worked (either first or second time) |
|
313 } |
|
314 } |
|
315 else |
|
316 { |
|
317 returncode = completion_code; |
|
318 err = LocalStopService(service_index); |
|
319 } |
|
320 } |
|
321 } // for loop |
|
322 |
|
323 return returncode; |
|
324 } |
|
325 |
|
326 |
|
327 /*********************************************************************************** |
|
328 * |
|
329 * PRIVATE METHOD: StartService - creates and starts up a service. The passed id |
|
330 * must map to an entry in the service table which stores the RPC service and |
|
331 * the host that the service is targetted at. |
|
332 * |
|
333 **********************************************************************************/ |
|
334 int CServiceManager::LocalStartService( int aServiceID, char *aServiceHost ) |
|
335 { |
|
336 int rv; |
|
337 int i; |
|
338 int localerror = 0; |
|
339 int remoteerror = 0; |
|
340 int localserviceindex = -1; |
|
341 IService *service; |
|
342 |
|
343 // look for a free index in the service table |
|
344 for( i = 0; i < MAXSERVICES; i++ ) { |
|
345 if( iServiceList[i] == NULL ) { |
|
346 localserviceindex = i; |
|
347 break; |
|
348 } |
|
349 } |
|
350 |
|
351 // check that a slot was found |
|
352 if( localserviceindex == -1 ) { |
|
353 return UCCS_SERVICELISTFULL; |
|
354 } |
|
355 |
|
356 // startup each legacy service |
|
357 switch( aServiceID ) { |
|
358 |
|
359 STARTUP_SERVICE_STUB_CASE( RPCSVC_HOMEAGENT, CHomeAgentServiceStub ); |
|
360 STARTUP_SERVICE_STUB_CASE( RPCSVC_FOREIGNAGENT, CForeignAgentServiceStub ); |
|
361 STARTUP_SERVICE_STUB_CASE( RPCSVC_MOBILEAGENT, CMobileAgentServiceStub ); |
|
362 STARTUP_SERVICE_STUB_CASE( RPCSVC_MOBSTER, CMobsterServiceStub ); |
|
363 STARTUP_SERVICE_STUB_CASE( RPCSVC_UUINTERFACE, CUuinterfaceStub ); |
|
364 STARTUP_SERVICE_STUB_CASE( RPCSVC_HOSTEXECUTE, CHostExecuteStub ); |
|
365 STARTUP_SERVICE_STUB_CASE( RPCSVC_PPPCONTROLLER, CPppControllerServiceStub ); |
|
366 STARTUP_SERVICE_STUB_CASE( RPCSVC_INTERNAL, CInternalStub ); |
|
367 STARTUP_SERVICE_STUB_CASE( RPCSVC_HOSTEXECUTEASYNC, CHostExecuteAsyncStub ); |
|
368 STARTUP_SERVICE_STUB_CASE( RPCSVC_TEST, CTestStub ); |
|
369 STARTUP_SERVICE_STUB_CASE( RPCSVC_GPSSIMULATOR, CAPICommandHandlerStub ); |
|
370 |
|
371 default: |
|
372 { |
|
373 // Check to see if it is a generic service stub |
|
374 if( (aServiceID >= RPCSVC_LAST) && |
|
375 (aServiceID <= RPCSVC_LAST+iNumGenericServices) ) |
|
376 { |
|
377 STARTUP_GENERIC_SERVICE_STUB( (TRpcServiceID)aServiceID, |
|
378 iGenericServices[aServiceID-RPCSVC_LAST].iIniFile, |
|
379 iGenericServices[aServiceID-RPCSVC_LAST].iServiceName); |
|
380 } |
|
381 else |
|
382 { |
|
383 rv = ERR_INVALID_SERVICE; |
|
384 } |
|
385 } |
|
386 break; |
|
387 } |
|
388 |
|
389 // update the status |
|
390 iOutput->StartServiceResult( aServiceID, aServiceHost, rv, localerror, 0 ); |
|
391 return ((rv == ERR_NONE) ? UCCS_OK : UCCS_CANTSTARTSERVICE ); |
|
392 } |
|
393 |
|
394 |
|
395 /*********************************************************************************** |
|
396 * |
|
397 * PRIVATE METHOD: StopService - destroys the service object |
|
398 * |
|
399 **********************************************************************************/ |
|
400 int CServiceManager::LocalStopService( int aLocalServiceID ) |
|
401 { |
|
402 int err; |
|
403 int localerror; |
|
404 int remoteerror; |
|
405 TServiceTableEntry this_entry; |
|
406 |
|
407 // check parameters |
|
408 assert( (aLocalServiceID >= 0) && (aLocalServiceID < MAXSERVICES) ); |
|
409 localerror = remoteerror = 0; |
|
410 |
|
411 |
|
412 // get the service |
|
413 if( iServiceList[aLocalServiceID] == NULL ) { |
|
414 return UCCS_INVALIDSERVICEINDEX; |
|
415 } |
|
416 |
|
417 // save this entry in-case |
|
418 this_entry.iServiceID = iServiceDescTable[aLocalServiceID].iServiceID; |
|
419 STRNCPY_NULL_TERMINATE( this_entry.iHostname, iServiceDescTable[aLocalServiceID].iHostname, MAXHOSTNAME ); |
|
420 |
|
421 // stop the service and log the result |
|
422 err = (iServiceList[aLocalServiceID])->StopUccsService( &localerror, &remoteerror ); |
|
423 |
|
424 // regardless of success we still want to destroy the object |
|
425 switch( iServiceDescTable[aLocalServiceID].iServiceID ) { |
|
426 |
|
427 SHUTDOWN_SERVICE_STUB_CASE( RPCSVC_HOMEAGENT, CHomeAgentServiceStub ); |
|
428 SHUTDOWN_SERVICE_STUB_CASE( RPCSVC_FOREIGNAGENT, CForeignAgentServiceStub ); |
|
429 SHUTDOWN_SERVICE_STUB_CASE( RPCSVC_MOBILEAGENT, CMobileAgentServiceStub ); |
|
430 SHUTDOWN_SERVICE_STUB_CASE( RPCSVC_MOBSTER, CMobsterServiceStub ); |
|
431 SHUTDOWN_SERVICE_STUB_CASE( RPCSVC_UUINTERFACE, CUuinterfaceStub ); |
|
432 SHUTDOWN_SERVICE_STUB_CASE( RPCSVC_HOSTEXECUTE, CHostExecuteStub ); |
|
433 SHUTDOWN_SERVICE_STUB_CASE( RPCSVC_PPPCONTROLLER, CPppControllerServiceStub ); |
|
434 SHUTDOWN_SERVICE_STUB_CASE( RPCSVC_INTERNAL, CInternalStub ); |
|
435 SHUTDOWN_SERVICE_STUB_CASE( RPCSVC_HOSTEXECUTEASYNC, CHostExecuteAsyncStub ); |
|
436 SHUTDOWN_SERVICE_STUB_CASE( RPCSVC_TEST, CTestStub ); |
|
437 SHUTDOWN_SERVICE_STUB_CASE( RPCSVC_GPSSIMULATOR, CAPICommandHandlerStub ); |
|
438 |
|
439 // this means that the other thread is trying to connect to the service as |
|
440 // we speak - if we just ignore this then it should be ok? |
|
441 case RPCSVC_INVALID: |
|
442 break; |
|
443 |
|
444 default: |
|
445 { |
|
446 // Check to see if it is a generic service stub |
|
447 if( (iServiceDescTable[aLocalServiceID].iServiceID >= RPCSVC_LAST) && |
|
448 (iServiceDescTable[aLocalServiceID].iServiceID <= RPCSVC_LAST+iNumGenericServices) ) |
|
449 { |
|
450 SHUTDOWN_SERVICE_STUB( iServiceDescTable[aLocalServiceID].iServiceID, CGenericStub ); |
|
451 } |
|
452 else |
|
453 { |
|
454 assert( !"INVALID CODE PATH" ); |
|
455 } |
|
456 } |
|
457 break; |
|
458 } |
|
459 |
|
460 // update the status |
|
461 iOutput->StopServiceResult( this_entry.iServiceID, this_entry.iHostname, err, localerror, remoteerror ); |
|
462 return ((err == ERR_NONE) ? UCCS_OK : UCCS_CANTSTOPSERVICE ); |
|
463 } |
|
464 |
|
465 |
|
466 /*********************************************************************************** |
|
467 * |
|
468 * PRIVATE METHOD: GetLocalServiceIndex |
|
469 * |
|
470 **********************************************************************************/ |
|
471 int CServiceManager::GetLocalServiceIndex( int aServiceID, char *aServiceHost ) |
|
472 { |
|
473 int i; |
|
474 int match; |
|
475 |
|
476 // check params |
|
477 assert( aServiceHost != NULL ); |
|
478 assert( (aServiceID > RPCSVC_INVALID) && (aServiceID < RPCSVC_LAST+iNumGenericServices) ); |
|
479 |
|
480 // now look for a match |
|
481 for( i = 0; i < MAXSERVICES; i++ ) { |
|
482 |
|
483 // make sure this index is active |
|
484 if( iServiceList[i] == NULL ) { |
|
485 continue; |
|
486 } |
|
487 |
|
488 // try and match |
|
489 if( aServiceID != iServiceDescTable[i].iServiceID ) { |
|
490 continue; |
|
491 } |
|
492 match = strcmp( iServiceDescTable[i].iHostname, aServiceHost ); |
|
493 if( match != 0 ) { |
|
494 continue; |
|
495 } |
|
496 |
|
497 // we have a match |
|
498 return i; |
|
499 } |
|
500 |
|
501 // done -- failed |
|
502 return -1; |
|
503 } |
|
504 |
|
505 |
|
506 |
|
507 |