/*
* KryptoSerwer.h
* Autor: Pawe Gala
*/

#ifndef __KRYPTOSERWER_H__
#define __KRYPTOSERWER_H__

#include <e32base.h>
#include "KryptoSerwer.pan"


class CKryptoSerwer : public CServer2
    {
    public:        // Konstruktory dwufazowe i destruktor
        static CKryptoSerwer* NewL();
        static CKryptoSerwer* NewLC();
        
        virtual ~CKryptoSerwer();

    public:
        static TInt FunkcjaWatku( TAny* aPtr );
        // Funkcje do zliczania sesji - po zamkniciu ostatniej sesji serwer jest
        // zatrzymywany, a jego proces koczony.
        // Metody wywoywane w konstruktorze i destruktorze klasy CKryptoSesja
        void InkrementujLicznikSesji();
        void DekrementujLicznikSesji();

    protected:        // Odziedziczone z CServer2 (CActive::RunError())
        TInt RunError( TInt aError );

    private:        // Konstruktory pierwszej i drugiej fazy
        CKryptoSerwer();
        void ConstructL();

    private:
        static void SpanikujSerwer( TPanikaKryptoSerwera aNrPaniki );
        static void FunkcjaWatkuL();

    private:    // Odziedziczone z CServer2 
        CSession2* NewSessionL( const TVersion& aVersion, 
                                const RMessage2& aMessage ) const;

    private:    // Pola
        TInt iLicznikSesji;
    };

#endif // __KRYPTOSERWER_H__


/*
* KryptoSerwer.cpp
* Autor: Pawe Gala
*/

#include <e32svr.h>

#include "KryptoSerwer.h"
#include "KryptoWspolne.h"
#include "KryptoSesja.h"


CKryptoSerwer* CKryptoSerwer::NewL()
    {
    CKryptoSerwer* self = CKryptoSerwer::NewLC();
    CleanupStack::Pop( self );
    return self;
    }

CKryptoSerwer* CKryptoSerwer::NewLC()
    {
    CKryptoSerwer* self = new( ELeave ) CKryptoSerwer();
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }

void CKryptoSerwer::ConstructL()
    {
    StartL( KNazwaKryptoSerwera );
    }

CKryptoSerwer::CKryptoSerwer() : CServer2( EPriorityHigh )
    {
    }

CKryptoSerwer::~CKryptoSerwer()
    {
    }

CSession2* CKryptoSerwer::NewSessionL( const TVersion& aVersion,
                                     const RMessage2& /*aMessage*/ ) const
    {
    // Sprawdzamy wersj klienta.
    if ( !User::QueryVersionSupported( TVersion( KKryptoSerwerWersjaGlowna,
                                                 KKryptoSerwerWersjaPodrzedna,
                                                 KKryptoSerwerWersjaPlikuWyk ),
                                       aVersion ) )
        {
        // Klient wymaga nowszej wersji serwera.
        User::Leave( KErrNotSupported );
        }

    return CKryptoSesja::NewL( *const_cast< CKryptoSerwer* >( this ) );
    }

void CKryptoSerwer::InkrementujLicznikSesji()
    {
    iLicznikSesji++;
    }
    
void CKryptoSerwer::DekrementujLicznikSesji()
    {
    iLicznikSesji--;
    if ( iLicznikSesji == 0 )
        {
        CActiveScheduler::Stop();
        }
    }

TInt CKryptoSerwer::RunError( TInt aError )
    {
    // Nie udao si utworzy sesji - poinformuj o tym klienta.
    Message().Complete( aError );

    // Nie pozwalamy serwerowi zakoczy pracy.
    ReStart();

    // Obsuylimy bd - moemy zwrci warto KErrNone.
    return KErrNone;
    }
    
void CKryptoSerwer::SpanikujSerwer( TPanikaKryptoSerwera aNrPaniki )
    {
    User::Panic( KKryptoSerwerPanika, aNrPaniki );
    }

void CKryptoSerwer::FunkcjaWatkuL()
    {
    // Tworzymy i instalujemy instancj Zarzdcy Aktywnoci.
    CActiveScheduler* activeScheduler = new ( ELeave ) CActiveScheduler;
    CleanupStack::PushL( activeScheduler );
    CActiveScheduler::Install( activeScheduler );

    // Tworzymy i startujemy serwer.
    CKryptoSerwer::NewLC();

    // Serwer zosta uruchomiony - teraz klient moe utworzy sesj.
    RSemaphore semafor;
    User::LeaveIfError( semafor.OpenGlobal( KNazwaKryptoSemafora ) );
    semafor.Signal();
    semafor.Close();
    
    // Startujemy ptl gwn Zarzdcy Aktywnoci.
    CActiveScheduler::Start();

    // Zwalaniamy dwa ostatnie wskaniki znajdujce si na szczycie stosu
    // CleanupStack (wskanik na obiekt serwera oraz activeScheduler).
    CleanupStack::PopAndDestroy( 2, activeScheduler );
    }

TInt CKryptoSerwer::FunkcjaWatku( TAny* /*aPtr*/ )
    {
    // Tworzymy stos CleanupStack.
    CTrapCleanup* cleanupStack = CTrapCleanup::New();
    if ( !( cleanupStack ) )
        {
        SpanikujSerwer( EBrakStosuCleanupStack );
        }

    // Startujemy waciw funkcj wtku.
    TRAPD( err, FunkcjaWatkuL() );
    if ( err != KErrNone )
        {
        SpanikujSerwer( EWyjscieWFunkcjiWatkuSerwera );
        }

    delete cleanupStack;
    return KErrNone;
    }

/**
* Punkt wejcia do procesu.
* Funkcja wywoywana przez system operacyjny.
*/
TInt E32Main()
    {
    return CKryptoSerwer::FunkcjaWatku( NULL );
    }
