sdkcreationmw/sdkruntimes/MIDP/DebugAgent/src/JavaDebugAgentDriver.cpp
changeset 0 b26acd06ea60
equal deleted inserted replaced
-1:000000000000 0:b26acd06ea60
       
     1 /*
       
     2 * Copyright (c) 2006 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 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32math.h>
       
    20 
       
    21 #include "TcpServer.h"
       
    22 #ifdef DEBUG_AGENT_ENGINE_AMS
       
    23 #include "AmsEngine.h"
       
    24 #else
       
    25 #include "SwiEngine.h"
       
    26 #endif
       
    27 
       
    28 #include "JavaDebugAgentLog.h"
       
    29 #include "JavaDebugAgentDriver.h"
       
    30 #include "JavaDebugAgentConnector.h"
       
    31 
       
    32 #define SUPER CDriver
       
    33 
       
    34 const TInt KPinLength = 4;
       
    35 
       
    36 CJavaDebugAgentDriver* CJavaDebugAgentDriver::NewLC(MJavaDebugAgentLog* aLog)
       
    37 {
       
    38     CJavaDebugAgentDriver* self = new(ELeave)CJavaDebugAgentDriver(aLog);
       
    39     CleanupStack::PushL(self);
       
    40     self->ConstructL();
       
    41     return self;
       
    42 }
       
    43 
       
    44 CJavaDebugAgentDriver* CJavaDebugAgentDriver::NewL(MJavaDebugAgentLog* aLog)
       
    45 {
       
    46     CJavaDebugAgentDriver* self = NewLC(aLog);
       
    47     CleanupStack::Pop(self);
       
    48     return self;
       
    49 }
       
    50 
       
    51 CJavaDebugAgentDriver::CJavaDebugAgentDriver(MJavaDebugAgentLog* aLog) : 
       
    52 iLog(aLog)
       
    53 {
       
    54 }
       
    55 
       
    56 CJavaDebugAgentDriver::~CJavaDebugAgentDriver()
       
    57 {
       
    58     DeleteConnector();
       
    59     SetState(EDeleted);
       
    60 
       
    61     iDeadHandlers.ResetAndDestroy();
       
    62     iHandlers.ResetAndDestroy();
       
    63     iKeepAliveList.ResetAndDestroy();
       
    64     delete iAsyncCleanup;
       
    65     delete iServer;
       
    66     delete iEngine;
       
    67     iFs.Close();
       
    68     iSocketServ.Close();
       
    69 }
       
    70 
       
    71 void CJavaDebugAgentDriver::ConstructL()
       
    72 {
       
    73     TCallBack cb(AsyncCleanup,this);
       
    74     iAsyncCleanup = new(ELeave)CAsyncCallBack(cb,CActive::EPriorityStandard);
       
    75     User::LeaveIfError(iSocketServ.Connect());
       
    76     User::LeaveIfError(iFs.Connect());
       
    77     iFs.ShareProtected();
       
    78 }
       
    79 
       
    80 void CJavaDebugAgentDriver::InitL()
       
    81 {
       
    82 #ifdef DEBUG_AGENT_ENGINE_AMS
       
    83     iEngine = new (ELeave)CAmsEngine(this);
       
    84 #else
       
    85     iEngine = new (ELeave)CSwiEngine(this);
       
    86 #endif
       
    87 
       
    88     // setup pin code
       
    89     if (IsUsePin())
       
    90     {
       
    91         // generate random KPinLength digit pin
       
    92         TInt rand = (TInt)(0x7fffffff & (Math::Random()));
       
    93         TBuf<32> buf;
       
    94         buf.AppendNum(rand);
       
    95         SetPinCodeL(buf.Left(KPinLength));
       
    96         iLog->LogFormat(_S("Pin code for this session: %S"),GetPinCode());
       
    97     }
       
    98 }
       
    99 
       
   100 TInt CJavaDebugAgentDriver::AsyncCleanup(TAny* aThis)
       
   101 {
       
   102     ((CJavaDebugAgentDriver*)aThis)->iDeadHandlers.ResetAndDestroy();
       
   103     return KErrNone;
       
   104 }
       
   105 
       
   106 TBool CJavaDebugAgentDriver::CheckIfIdle() const
       
   107 {
       
   108     if (iServer)
       
   109     {
       
   110         iLog->Log(_S("Already listening!"));
       
   111         return EFalse;
       
   112     }
       
   113     if (iHandlers.Count() > 0)
       
   114     {
       
   115         iLog->Log(_S("Already connected!"));
       
   116         return EFalse;
       
   117     }
       
   118     return ETrue;
       
   119 }
       
   120 
       
   121 void CJavaDebugAgentDriver::StartListeningL()
       
   122 {
       
   123     if (!CheckIfIdle()) return;
       
   124     CTcpServer* server = CTcpServer::NewLC(this);
       
   125     TInetAddr address(GetAgentPort());
       
   126     TRAPD(err,server->StartListeningL(_L("tcp"), address, 10));
       
   127     if (err == KErrNone)
       
   128     {
       
   129         CleanupStack::Pop();
       
   130         iServer = server;
       
   131         SetState(EListening);
       
   132     }
       
   133     else
       
   134     {
       
   135         iLog->LogFormat(_S("Server failed, error %d"),err);
       
   136         User::Leave(err);
       
   137     }
       
   138 }
       
   139 
       
   140 void CJavaDebugAgentDriver::DeleteConnector()
       
   141 {
       
   142     // Note: CJavaDebugAgentConnector destructor may invoke ConnectionFailed
       
   143     // and we want iConnector pointer be NULL to avoid double delete.
       
   144     CJavaDebugAgentConnector* connector = iConnector;
       
   145     iConnector = NULL;
       
   146     delete connector;
       
   147 }
       
   148 
       
   149 void CJavaDebugAgentDriver::ConnectL()
       
   150 {
       
   151     if (!CheckIfIdle()) return;
       
   152     DeleteConnector();
       
   153     iConnector = new(ELeave)CJavaDebugAgentConnector(this, iApId);
       
   154     iConnector->ConnectL();
       
   155     SetState(EConnecting);
       
   156 }
       
   157 
       
   158 void CJavaDebugAgentDriver::SetState(TState aState)
       
   159 {
       
   160     if (iState != aState)
       
   161     {
       
   162         iState = aState;
       
   163         if (iObserver)
       
   164         {
       
   165             iObserver->StateChanged(aState);
       
   166         }
       
   167     }
       
   168 }
       
   169 
       
   170 void CJavaDebugAgentDriver::Log(const TDesC& aString)
       
   171 {
       
   172     iLog->LogFormat(_S("%S"),&aString);
       
   173 }
       
   174 
       
   175 RFs& CJavaDebugAgentDriver::Fs()
       
   176 {
       
   177     return iFs;
       
   178 }
       
   179 
       
   180 void CJavaDebugAgentDriver::Shutdown()
       
   181 {
       
   182     DeleteConnector();
       
   183     delete iServer;
       
   184     iServer = NULL;
       
   185 }
       
   186 
       
   187 CAgentEngine* CJavaDebugAgentDriver::Engine() 
       
   188 {
       
   189     return iEngine;
       
   190 }
       
   191 
       
   192 void CJavaDebugAgentDriver::Message(const TDesC& aString)
       
   193 {
       
   194     Log(aString);
       
   195 }
       
   196 
       
   197 void CJavaDebugAgentDriver::SettingsChange()
       
   198 {
       
   199     // ????
       
   200 }
       
   201 
       
   202 void CJavaDebugAgentDriver::InitKeepAliveL(const TSockAddr* aRemoteAddr)
       
   203 {
       
   204     CJavaDebugAgentKeepAlive* keepAlive = 
       
   205         CJavaDebugAgentKeepAlive::NewLC(&iSocketServ, aRemoteAddr, iLog,
       
   206                                         iKeepAlivePeriod);
       
   207     User::LeaveIfError(iKeepAliveList.Append(keepAlive));
       
   208     CleanupStack::Pop(keepAlive);
       
   209 }
       
   210 
       
   211 // Notifications from CTcpServerHandler
       
   212 void CJavaDebugAgentDriver::ClientConnected(CTcpServerHandler* aHandler)
       
   213 {
       
   214     if (iHandlers.Append(aHandler) == KErrNone)
       
   215     {
       
   216         if (iKeepAlivePeriod > 0)
       
   217         {
       
   218             TInetAddr local;
       
   219             TInetAddr remote;
       
   220             aHandler->Socket()->LocalName(local);
       
   221             aHandler->Socket()->RemoteName(remote);
       
   222 
       
   223             // No ping for local connections (as in case of debugging over
       
   224             // Bluetooth)
       
   225             if (!local.Match(remote))
       
   226             {
       
   227                 TRAPD(err, InitKeepAliveL(&remote));
       
   228                 if (err == KErrNone)
       
   229                 {
       
   230                     iLog->Log(_S("Starting keep-alive timer"));
       
   231                 }
       
   232                 else
       
   233                 {
       
   234                     // Ignore the error, it shoudn't be fatal
       
   235                     iLog->LogFormat(_S("Keep-alive error %d"),err);
       
   236                 }
       
   237             }
       
   238         }
       
   239 
       
   240         if (iHandlers.Count() == 1) 
       
   241         {
       
   242             // First client
       
   243             SetState(EConnected);
       
   244         }
       
   245     }
       
   246     else
       
   247     {
       
   248         // This connection will work but we will leak some memory.
       
   249         // Suggest the user to restart the application
       
   250         iLog->Log(_S("Internal error. Please restart debug agent."));
       
   251     }
       
   252 }
       
   253 
       
   254 void CJavaDebugAgentDriver::ClientDisconnected(CTcpServerHandler* aHandler)
       
   255 {
       
   256     TInt handlerPos = iHandlers.Find(aHandler);
       
   257     if (handlerPos >= 0) {
       
   258         TInetAddr remote;
       
   259         RSocket* socket = aHandler->Socket();
       
   260         socket->LocalName(remote);
       
   261 
       
   262         // Delete a matching KeepAlive object. It doesn't matter which one.
       
   263         // Ideally we shouldn't create more than one KeepAlive per address
       
   264         // but we normally have no more than one client, so it's doesn't
       
   265         // really matter.
       
   266         for (TInt i = 0; i<iKeepAliveList.Count(); i++)
       
   267         {
       
   268             if (remote.Match(iKeepAliveList[i]->Address()))
       
   269             {
       
   270                 delete iKeepAliveList[i];
       
   271                 iKeepAliveList.Remove(i);
       
   272                 break;
       
   273             }
       
   274         }
       
   275 
       
   276         // It's not obvious how we can recover from the situation when
       
   277         // we can't this handler to iDeadHandlers array. It's not safe
       
   278         // to delete the handler here because this callback is invoked 
       
   279         // by the handler, and it may access its this pointer after this
       
   280         // callback has returned. It that case, let's leave it in iHandlers
       
   281         // array. It screws things up but at least we don't leak memory.
       
   282         // Hopefully, this won't happen too often...
       
   283         if (iDeadHandlers.Append(aHandler) == KErrNone)
       
   284         {
       
   285             iHandlers.Remove(handlerPos);
       
   286             if (iHandlers.Count() == 0) {
       
   287                 // It was our last client
       
   288                 SetState(iServer ? EListening : EDisconnected);
       
   289             }
       
   290             // Schedule callback on a clean stack where we can safely
       
   291             // delete the handler
       
   292             iAsyncCleanup->CallBack();
       
   293         }
       
   294     }
       
   295     
       
   296     //Dima: Cleanup on start in InitL conflicts with installation
       
   297     //seemingly due to errors in Installer (ECOM framework panics
       
   298     //on loading midp2installerplugin.dll on installation after cleanup)
       
   299     //so we clean up on client disconnect.
       
   300     if (IsAutoCleanEnabled())
       
   301     {
       
   302         Log(_L("Cleaning up old data..."));
       
   303         iEngine->Cleanup();
       
   304         Log(_L("Done cleaning..."));
       
   305     }
       
   306 }
       
   307 
       
   308 // Notification from CJavaDebugAgentConnector
       
   309 void CJavaDebugAgentDriver::ConnectionFailed()
       
   310 {
       
   311     DeleteConnector();
       
   312     SetState(EDisconnected);
       
   313 }
       
   314 
       
   315 /**
       
   316  * Local Variables:
       
   317  * c-basic-offset: 4
       
   318  * indent-tabs-mode: nil
       
   319  * End:
       
   320  */