///////////////////////////////////////////////////////////////////////////////
//File Name: LSSessionManager.hxx <Header File>
//Description: Managers the peer to peer connection between two LSs. This class
//can run either as a thread or a standalone application. OPEN messages are
//listened for on port 6069.
///////////////////////////////////////////////////////////////////////////////

#ifndef LSSessionManager_hxx
#define LSSessionManager_hxx

#include <vector>
#include <string>
#include "Sptr.hxx"
#include "TRIPItadKey.hxx"
#include "Connection.hxx"
#include "TRIPBadDataException.hxx"
#include "TRIPTransCapability.hxx"
#include "LSLocator.hxx"
#include "TRIPDef.hxx"
#include "DSA.hxx"
#include "RSA.hxx"
#include "LSTopology.hxx"
#include "VMutex.h"
#include "vtypes.h"
#include "global.h"

class LSPeerSession;
class NetworkAddress;
class TRIPUpdateMsg;
class TRIPRouteContainer;

class LSSessionManager{

public:
  
  //Authentication mechanism for this LS.
  char _authMech;

  //Authentication code for Authentication attribute.
  char _authCode;

  //The value of the TRIP ID.
  int _theTRIPID;
  
  /**
     Method to instantiate a singleton instance. 
  */
  static LSSessionManager& instance();

  /**
     Method to return the name of the class.
  */
  string className(){ 
    return "LSSessionManager"; 
  }

  /**
     Destructor.
  */
  virtual ~LSSessionManager();

  /**
     Frees the memory associated with singelton instance.
     Gets register to atexit() function at the time of creation.
  */
  static void destroy(void);

  /**
     Sets the authentication mechanism to be used by this LS.
     The default is DSA.
  */
  void setAuthMech(string am);

  /**
     Sets the authentication mechanism to be used by this LS.
     The default is DSA.
  */
  char getAuthMech(){
    return _authMech;
  };


  /**
     Method to initialise the LSSessionManager. Takes in as a parameter,
     the name of the Provision Server.
  */
  void init(string thePS);

  /**
     Method to display output of LSSessionManager.
  */
  friend ostream& operator<<(ostream& os, const LSSessionManager& lslocator);

  /**
     Returns true if session with given ITAD and tripId exists.
  */
  bool locateExistingPeerSession(u_int16_t itad, const TRIPId& tripId);

  /**
     Returns pointer to the PeerSession, if a PeerSession exists for a 
     given destination.
  */
  Sptr<LSPeerSession> locateExistingPeerSession(const string& destIp);

  /**
     Indicates if any session is established with an external Peer.
  */
  bool externalSessionExists() const;

  /**
     Retrieves the TRIPItadKey key for the LS.
  */
  const TRIPItadKey& getTripItadKey() const{ 
    return _tripItadKey; 
  };

  /**
     Retrieves the ITAD values for the LS.
  */
  u_int16_t getItad() const { return _tripItadKey.getItad(); };

  /**
     Retrieves the TRIP Iidentifier for the LS.
  */
  const TRIPId& getTripId() const{ 
    return _tripItadKey.getTripId(); 
  };

  /**
     Retrieves the mode of transport for the LS.
  */
  TRIPTransMode getTransMode() const { return _transMode; };

  /**
     Gets the local IP address.
  */
  const string& getLocalIp() const{ 
    return _localIp; 
  }

  /**
     Runs in while loop accepting OPEN connections in forground in the 
     main thread. Should be used ONLY when running LS
     as stand-alone application.
  */
  void run();

  /**
     Creates a separate thread to run the while loop accepting 
     connections. The method forces LS to run in its
     own thread.Should ONLY be used when running LS as part of any
     other application, for example within a Proxy.
  */
  void threadRun();
  
  /**
     Retrieves the list of peers for which sessions hold.
  */
  const LSPeerList& getSessionList() const { return _sessionList; };

  /**
     Locks the session list for reading or writing.
  */
  void lockSessionList() const{ 
    _sessionListMutex.lock(); 
  };

  /**
     Unlocks the session list.
  */
  void unlockSessionList()  const{
    _sessionListMutex.unlock(); 
  };

  //The minimum sequence number.
  static u_int32_t MinSeqNumber;

  //The maximum sequence number.
  static u_int32_t MaxSeqNumber;

  //Retrieves the sequence number.
  inline u_int32_t getSeqNumber(){ 
    return ++_seqNum; 
  };

  //Gets called when the Adj-TRIB-In for tribIn changed.
  void floodRoutes(Sptr <TRIPWorkSet> workSet, 
		   TRIPCallbackReason reason,
		   const TRIPItadKey& key);
  
  /**
     Floods routes with call back function.
  */
  static void floodRoutesCB(Sptr <TRIPWorkSet> workSet,
			    TRIPCallbackReason reason, 
			    const TRIPItadKey& changedSrc);

  /**
     Retrieves the next transaction ID.
  */
  inline u_int32_t getNextTransactionId() { 
    return ++_transactionId; 
  };

  Sptr <UpdateMsgList> getFloodMsgList(const TRIPRouteSet& floodSet,
				       bool initialFlood, 
				       bool isInternal);

  /**
     Gets the next sequence number.
  */
  u_int32_t getNextSeqNumber(bool startFlooding, Sptr<TRIPRouteElement> data);

  /**
     Gets the instance of the LSLocator.
  */
  const LSLocator& getLsLocator() const{ 
    return _lsLocator; 
  };

  /**
     Retrieves the protocol capability list.
  */
  const ProtoCapabilityList& getProtoCapabilityList() const { 
    return _protoCapabilityList; 
  };
  
  /**
     Retrieves the address family list.
  */
  const AddrFamilyList& getAddrFamilyList() const{ 
    return _addrFamilyList; 
  };

  /**
     Sends a topology update.
  */
  void sendTopologyUpdateOmit(const TRIPItadKey& srcItadKey, 
			      Sptr<TRIPUpdateMsg> uMsg );
  
  /**
     Handles topology changes.
  */
  void handleTopologyChanges(const TRIPItadKey& srcItadKey,
			     Sptr<TRIPItadTopology> itadTopology);

  /**
     Clears the Adj-TRIB-In table.
  */
  void clearAdjTribIn(const TRIPItadKey& itadKey);

  /**
     Creates a message to update the topology.
  */
  Sptr<TRIPUpdateMsg> createTopologyUpdateMsg(Sptr<TRIPItadTopology> topo=0);
  
  /**
     Adds an ITAD to the topology.
  */
  void addTopology(const TRIPItadKey& lKey, const TRIPItadKey& peerKey);
  
  /**
        Takes a prefix for which to find a gateway for in the LocTRIB and
        ExtTRIB tables of the TRIB database.
  */
  string LSSessionManager::findSIPGateway(string pre);

protected:

  /**
     Gets the next message t flood.
  */
  Sptr<TRIPUpdateMsg> getNextMsgToFlood(const TRIPTrieCache& cache, 
					bool startFlooding);
  
  /**
     Processes all of the routes.
  */
  void processRoutes(Sptr<TRIPRouteContainer> routeContainer,
		     Sptr<TRIPRouteSet> rSet,
		     const TRIPItadKey& itadKey,
		     u_int32_t seqNum, bool startFlooding);

  /**
     Creates a peer session between two LSs.
  */
  Sptr<LSPeerSession> createSession(const NetworkAddress& addr);
  
  /**
     Run method for the thread.
  */
  static void* threadRunImpl(void* args);

  /**
     Processes the UPDATE message
  */
  void processMsg();

  /**
     Processes a request to open a peering session.
  */
  void processOpenRequest(Connection& conn) throw (VNetworkException&, 
						   TRIPBadDataException&);

  
  /**
     Default constructor takes in no parameters.
  */
  LSSessionManager();
  
  //Singleton instance of the class.
  static LSSessionManager* _instance;

  //The name of the Provision Server for the LS.
  string _ps;
  

  //Server socket for listening.
  Sptr<TcpServerSocket>  _serverSocket;
  
  //Thread object.
  Sptr<VThread> _thread;
  
  //List of peers the LS has a connection with.
  LSPeerList _sessionList;
  
  //Mutex object.
  mutable VMutex _sessionListMutex;

  //ITAD and LS pair.
  TRIPItadKey  _tripItadKey;

  //The ITAD of the LS.
  int _itad;

  //Sequence number.
  u_int32_t _seqNum;

  //Transaction ID.
  u_int32_t  _transactionId;

  //Use to look up external LSs from a list.
  LSLocator  _lsLocator;
  
  //List of protocols supported by the LS.
  ProtoCapabilityList _protoCapabilityList;

  //List of address family supported by the LS.
  AddrFamilyList _addrFamilyList;

  //Mode of tranport for the LS.
  TRIPTransMode _transMode;

  //LS inter-ITAD topology.
  Sptr<LSTopology> _topology;

  //LS's IP address.
  string _localIp;

  //The port the LS listens on.
  int _localPort;

  //Tells you whether local routes have been injected.
  bool _injected;

};

#endif










