/*
* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
* This file was autogenerated by rpcgen, but should be modified by the developer.
* Make sure you don't use the -component_mod flag in future or this file will be overwritten.
* Fri Sep 19 13:14:28 2003
* System Includes
*
*/
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
/****************************************************************************************
*
* Local Includes
*
***************************************************************************************/
#include "CSvcMobster.h"
#include "mobster.h"
#include "../ThreadLibrary/CAThread.h"
#include "mobster_client_server_protocol.h"
/****************************************************************************************
*
* Definitions
*
***************************************************************************************/
#ifndef WIN32
#define ADDRESS_INTEGER s_addr
#define closesocket(x) (shutdown(x,SHUT_RDWR),close(x))
#endif
/****************************************************************************************
*
* File-scope variables
*
***************************************************************************************/
static CComponentManager<CSMobster> *iComponentManager;
static CAThread *iServerThread;
static int iServerListenSocket, iStopRequestedFlag;
/****************************************************************************************
*
* Implementation
*
***************************************************************************************/
/****************************************************************************************
*
* PUBLIC: GetInstanceKeyFromArgs
*
***************************************************************************************/
int CSvcMobster::GetInstanceKeyFromArgs( int aMethod, void *aArgs )
{
int rv;
int *ia;
TUUAddress *ua;
switch( aMethod ) {
case DSTR_REMOVEDEVICE:
case GETDEVICEINFO:
case GETDEVICELOG:
case STOPDEVICE:
ia = (int*)aArgs;
rv = *ia;
break;
case SETREMOTEUUADDRESS:
ua = (TUUAddress*)aArgs;
rv = ua->iDeviceID;
break;
default:
rv = ERR_INVALID_METHOD;
break;
}
return rv;
}
/****************************************************************************************
*
* PUBLIC: SetError
*
***************************************************************************************/
int CSvcMobster::SetError( int aMethod, void *aArgs, int aError )
{
int rv;
TComponentList *cl;
TDeviceDesc *dd;
TVarData *vd;
switch( aMethod ) {
case LIST_DEVICES:
cl = (TComponentList*)aArgs;
if( aError != ERR_NONE ) {
if( cl->TComponentList_val != NULL ) {
free(cl->TComponentList_val);
cl->TComponentList_val = NULL;
}
cl->TComponentList_len = 0;
}
rv = ERR_NONE;
break;
case GETDEVICEINFO:
dd = (TDeviceDesc*)aArgs;
dd->iMTID = aError;
rv = ERR_NONE;
break;
case GETDEVICELOG:
vd = (TVarData*)aArgs;
if( aError != ERR_NONE ) {
if( vd->TVarData_val != NULL ) {
free(vd->TVarData_val);
vd->TVarData_val = NULL;
}
vd->TVarData_len = 0;
}
rv = ERR_NONE;
break;
default:
rv = ERR_INVALID_METHOD;
break;
}
return rv;
}
/****************************************************************************************
*
* PUBLIC: StartRPCService
*
***************************************************************************************/
int CSvcMobster::StartRPCService( CComponentManager<CSMobster> *aComponentManager, TChannelAddress *aArg )
{
TThreadError terr;
int err;
struct sockaddr_in local_address;
// prologue
assert( iComponentManager == NULL );
assert( iServerThread == NULL );
// create a socket to listen for connections
iServerListenSocket = socket( AF_INET, SOCK_STREAM, 0 );
if( iServerListenSocket == -1 ) {
return ERR_CREATE_SOCKET_FAILED;
}
// bind the specified port (ignore address)
local_address.sin_family = AF_INET;
local_address.sin_addr.ADDRESS_INTEGER = INADDR_ANY;
local_address.sin_port = htons(aArg->iPort);
err = bind( iServerListenSocket, (struct sockaddr *)&local_address, sizeof(local_address) );
if( err == -1 ) {
closesocket( iServerListenSocket );
return ERR_BIND_FAILED;
}
// listen
err = listen( iServerListenSocket, 5 );
if( err == -1 ) {
closesocket( iServerListenSocket );
return ERR_LISTEN_FAILED;
}
// ok the socket is all setup to do an accept - so we pass over to the other thread
// and let the main call continue
iStopRequestedFlag = 0;
iServerThread = new CAThread( "CSvcMobster::iServerThread" );
assert( iServerThread != NULL );
terr = iServerThread->StartThread( (void*)CSvcMobster::WaitForConnectionsFromTerminalEmulations, NULL, &err );
if( terr != TE_NONE ) {
closesocket( iServerListenSocket );
delete iServerThread;
iServerThread = NULL;
return ERR_CREATE_SERVER_THREAD_FAILED;
}
// done
iComponentManager = aComponentManager;
return ERR_NONE;
}
/****************************************************************************************
*
* PUBLIC: StopRPCService
*
***************************************************************************************/
int CSvcMobster::StopRPCService()
{
TThreadError terr;
// close the socket to stop the thread
iStopRequestedFlag = 1;
closesocket( iServerListenSocket );
terr = iServerThread->WaitForThread( -1 );
if( terr != TE_NONE ) {
fprintf( stderr, "WARNING: CSvcMobster::StopRPCService - WaitForThread returned %d.\n", terr );
}
// clean up the thread
if( iServerThread != NULL ) {
delete iServerThread;
iServerThread = NULL;
}
// reset the component manager (though not responsible for delete)
iComponentManager = NULL;
return ERR_NONE;
}
/****************************************************************************************
*
* PRIVATE: WaitForConnectionsFromTerminalEmulations
*
***************************************************************************************/
void CSvcMobster::WaitForConnectionsFromTerminalEmulations( void )
{
int client_sockfd;
// repeat until StopRPCService is called (or an error occurs)
while( 1 ) {
// wait for a connection
client_sockfd = accept( iServerListenSocket, NULL, NULL );
if( client_sockfd == -1 ) {
if( ((errno != 0) && (errno != EINVAL)) || ((errno == EINVAL) && (iStopRequestedFlag == 0)) ) {
fprintf( stderr, "WARNING: Accept has failed with errno = %d.\n", errno );
}
break;
}
// we have a socket -- now it has to do the c/s protocol so that we know which
// MT to connect it to -- but if there is a problem then this could block
// forever -- so I'm going to create a thread per connection to deal with this.
// These threads are responsible for cleaning themselves up.
#ifdef WIN32
{
HANDLE client_thread;
client_thread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)CSvcMobster::ConnectClientToMobileTermination, (void*)client_sockfd, 0, NULL );
if( client_thread == NULL ) {
fprintf( stderr, "WARNING: Failed to create the client thread to connect to MobileTermination (%d).\n", GetLastError() );
}
client_thread = NULL;
#else
{
int err;
pthread_t client_thread;
err = pthread_create( &client_thread, NULL, (void*(*)(void*))(CSvcMobster::ConnectClientToMobileTermination), (void*)client_sockfd );
if( err != 0 ) {
fprintf( stderr, "WARNING: Failed to create the client thread to connect to MobileTermination (%d).\n", errno );
}
client_thread = 0;
}
#endif
// this is all we have to do
}
// done
return;
}
/****************************************************************************************
*
* PRIVATE: ConnectClientToMobileTermination
*
***************************************************************************************/
void CSvcMobster::ConnectClientToMobileTermination( int aSock )
{
int mtid, err;
CSMobster *mt;
// do the csprotocol across the socket to get the config info
mtid = client_server_protocol( aSock );
if( mtid < 0 ) {
fprintf( stderr, "WARNING: Invalid MTID received (%d).\n", mtid );
closesocket( aSock );
return;
}
// try and get the instance
mt = iComponentManager->GetInstance( mtid );
if( mt == NULL ) {
fprintf( stderr, "WARNING: Client requested non-existant device %d.\n", mtid );
closesocket( aSock );
return;
}
// pass the new socket to the mt
err = mt->settesocket( aSock );
if( err != ERR_NONE ) {
fprintf( stderr, "WARNING: Failed to set the socket on device %d (%d).\n", mtid, err );
closesocket( aSock );
return;
}
// all done -- thread exit
#ifdef WIN32
ExitThread( 0 );
#else
pthread_exit( 0 );
#endif
}