#ifndef ARCLIENTSWITCH_H
#define ARCLIENTSWITCH_H
#include "Aria.h"
#include "ArServerBase.h"
#include "ArClientBase.h"
/**
The serverInfoFile takes the form of a config file roughly, there
are 3 things you can put in it now. 'user user', 'password
password' and 'serverKey serverKey'. Note that it loads these
files sequentially so if you pass it 5 files it'll read them in the
order they were passed in. If you give it just the keyword but not
the value (ie 'user') then it'll clear out that value.
Some program command line options can be used to configure this class:
@verbinclude ArClientSwitchManager_options
**/
class ArClientSwitchManager : public ArASyncTask
{
public:
AREXPORT ArClientSwitchManager(
ArServerBase *serverBase,
ArArgumentParser *parser,
const char *serverDescription = "Central Server",
const char *clientSoftwareDescription = "Software");
AREXPORT virtual ~ArClientSwitchManager();
/// Returns if we're connected or not
AREXPORT bool isConnected(void);
/// Function to parse the arguments given in the constructor
AREXPORT bool parseArgs(void);
/// Log the options the simple connector has
AREXPORT void logOptions(void) const;
/// Gets the hostname we're using for the central server (NULL means we're not trying to sue the central server)
AREXPORT const char *getCentralServerHostName(void);
/// Gets the identifier we're using
AREXPORT const char *getIdentifier(void);
/// Sets the identifier we're using
AREXPORT void setIdentifier(const char *identifier)
{ myIdentifier = identifier; }
/// Enforces the that the server is using this protocol version
AREXPORT void enforceProtocolVersion(const char *protocolVersion);
/// Enforces that the robots that connect are this type
AREXPORT void enforceType(ArServerCommands::Type type);
/// Gets the config display hint items dependent on the central
/// server should use (still check getCentralServerHostName to see
/// if it's being used)
const char *getConfigDisplayHint(void)
{ return myConfigDisplayHint.c_str(); }
/// The handler for the response to the switch command
AREXPORT void clientSwitch(ArNetPacket *packet);
/// The handler for the packet to let the server know we're still talking to it
AREXPORT void netCentralHeartbeat(ArServerClient *client,
ArNetPacket *packet);
/// The handler for the packet that comes from the server so we know
/// we're getting these
AREXPORT void netCentralServerHeartbeat(ArServerClient *client,
ArNetPacket *packet);
/// Parses the file for holding the user, password, and server key
AREXPORT bool parseFile(const char *fileName);
AREXPORT virtual void *runThread(void *arg);
/// Sets debug logging
AREXPORT void setDebugLogging(bool debugLogging = false)
{ myDebugLogging = debugLogging; }
/// Gets if this is using debug logging
AREXPORT bool getDebugLogging(void) { return myDebugLogging; }
/// Gets the server client the forwarder is using (internal)
/**
@internal
**/
AREXPORT ArServerClient* getServerClient(void)
{ return myServerClient; }
/// Adds central server or identifier not passed into the config
AREXPORT void addToConfig(const char *configSection,
const char *connectName, const char *connectDesc,
const char *addressName, const char *addressDesc);
/// Adds a callback when we switch states while starting
AREXPORT void addFailedConnectCB(
ArFunctor1 *functor, int position = 50)
{ myFailedConnectCBList.addCallback(functor, position); }
/// Removes a callback when we switch to running
AREXPORT void remFailedConnectCB(ArFunctor1 *functor)
{ myFailedConnectCBList.remCallback(functor); }
/// Adds a callback when we switch states while starting
AREXPORT void addConnectedCB(
ArFunctor1 *functor, int position = 50)
{ myConnectedCBList.addCallback(functor, position); }
/// Removes a callback when we switch to running
AREXPORT void remConnectedCB(ArFunctor1 *functor)
{ myConnectedCBList.remCallback(functor); }
protected:
AREXPORT void socketClosed(void);
ArServerBase *myServer;
ArArgumentParser *myParser;
std::string myServerDesc;
std::string myClientSoftwareDesc;
ArServerClient *myServerClient;
ArTime myLastTcpHeartbeat;
ArTime myLastUdpHeartbeat;
ArFileParser myFileParser;
bool myServerHasHeartbeat;
double myServerHeartbeatTimeout;
double myServerUdpHeartbeatTimeout;
double myServerBackupTimeout;
bool fileUserCallback(ArArgumentBuilder *arg);
bool filePasswordCallback(ArArgumentBuilder *arg);
bool fileServerKeyCallback(ArArgumentBuilder *arg);
enum State
{
IDLE, ///< Don't want to connect
TRYING_CONNECTION, ///< If we're trying to connect
CONNECTING, ///< If we're waiting for the response from the server
CONNECTED, ///< If we're connected
LOST_CONNECTION ///< If we lost a connection... wait a bit and try again
};
State myState;
ArTime myStartedState;
ArTime myLastConnectionAttempt;
//bool myGaveTimeWarning;
bool processFile(void);
AREXPORT void switchState(State state);
ArMutex myDataMutex;
bool myTryConnection;
ArClientBase *myClient;
std::string myUser;
std::string myPassword;
std::string myServerKey;
std::string myCentralServer;
int myCentralServerPort;
std::string myIdentifier;
std::string myEnforceProtocolVersion;
ArServerCommands::Type myEnforceType;
bool myConfigFirstProcess;
bool myConfigConnectToCentralServer;
char myConfigCentralServer[1024];
char myConfigIdentifier[1024];
std::string myConfigDisplayHint;
ArCallbackList1 myFailedConnectCBList;
ArCallbackList1 myConnectedCBList;
bool myDebugLogging;
ArRetFunctorC myParseArgsCB;
ArConstFunctorC myLogOptionsCB;
ArFunctorC mySocketClosedCB;
ArFunctor1C mySwitchCB;
ArFunctor2C myNetCentralHeartbeatCB;
ArFunctor2C myNetCentralServerHeartbeatCB;
ArRetFunctor1C myFileUserCB;
ArRetFunctor1C myFilePasswordCB;
ArRetFunctor1C myFileServerKeyCB;
ArRetFunctorC myProcessFileCB;
};
#endif // ARCLIENTSWITCH_H