#ifndef NLSERVERCLIENT_H #define NLSERVERCLIENT_H #include "ArNetPacket.h" #include "ArServerCommands.h" #include "ArNetPacketReceiverTcp.h" #include "ArNetPacketSenderTcp.h" class ArServerData; class ArServerUserInfo; #include "ArServerClientData.h" #include "ArServerClientIdentifier.h" /** This class represents the server's connection to the client, and contains the socket that the server uses to talk to the client and the information for sending packets to the client. **/ class ArServerClient { public: /// The state of the connection enum ServerState { STATE_SENT_INTRO, ///< opened socket, sent our intro to the server STATE_REJECTED, ///< Client was rejected by server STATE_CONNECTED, ///< Client is connected to server STATE_DISCONNECTED ///< Client has disconnected from server }; /// Constructor AREXPORT ArServerClient( ArSocket *tcpSocket, unsigned int udpPort, long authKey, long introKey, ArRetFunctor2 *sendUdpCallback, std::map *dataMap, const char *passwordKey, const char *serverKey, const ArServerUserInfo *userInfo = NULL, int rejecting = 0, const char *rejectingString = "", bool debugLogging = false, const char *serverClientName = "ArServerBase_unknown", bool logPasswordFailureVerbosely = false, bool allowSlowPackets = true, bool allowIdlePackets = true, const char *enforceProtocolVersion = "", ArServerCommands::Type enforceType = ArServerCommands::TYPE_UNSPECIFIED); /// Destructor AREXPORT virtual ~ArServerClient(); /// The callback for taking care of the TCP connection AREXPORT bool tcpCallback(void); /// The callback for taking care of slow packets AREXPORT bool slowPacketCallback(void); /// The callback for taking care of idle packets (logic on idle elsewhere) AREXPORT bool idlePacketCallback(void); /// Sets the backup timeout AREXPORT void setBackupTimeout(double timeoutInMins); /// Process the packet whever it came from AREXPORT void processPacket(ArNetPacket *packet, bool tcp = true); /// Send a packet over TCP. /// The command ID of the outgoing packet will be set to the current command ID /// (from the incoming packet). AREXPORT virtual bool sendPacketTcp(ArNetPacket *packet); /// Send a packet over UDP (unless client only wants TCP; then sends over TCP). /// The command ID of the outgoing packet will be set to the current command ID /// (from the incoming packet). AREXPORT virtual bool sendPacketUdp(ArNetPacket *packet); /// Sees if this client has access to a given group AREXPORT bool hasGroupAccess(const char *group); /** Broadcasts a packet over TCP if this client wants this data -- For internal * use only! * @internal */ AREXPORT void broadcastPacketTcp(ArNetPacket *packet); /** Broadcasts a packet over UDP if this client wants this data (unless client only wants tcp then sends over tcp) -- For internal ArNetworking use only! * @internal */ AREXPORT void broadcastPacketUdp(ArNetPacket *packet); /// Logs the tracking information (packet and byte counts) AREXPORT void logTracking(bool terse); /// Clears the tracking information (resets counters) AREXPORT void resetTracking(void); /// Gets the IP string of the client AREXPORT const char *getIPString(void) const; /// Gets the identifier of this server client AREXPORT ArServerClientIdentifier getIdentifier(void) const; /// Sets the identifier of this server client AREXPORT void setIdentifier(ArServerClientIdentifier identifier); /// Sends a shutdown command to the socket AREXPORT void shutdown(void); /// Sets the sin (network address) for the UDP socket AREXPORT void setUdpAddress(struct sockaddr_in *sin); /// Gets the sin (network address) for the UDP socket AREXPORT struct sockaddr_in *getUdpAddress(void); /// Gets the authKey used for setting up UDP from this client to the server AREXPORT long getAuthKey(void); /// Processes the auth packets that came from udp AREXPORT void processAuthPacket(ArNetPacket *packet, struct sockaddr_in *sin); /// Handles the requests for packets AREXPORT void handleRequests(void); /// Internal function to get the tcp socket AREXPORT ArSocket *getTcpSocket(void) { return &myTcpSocket; } /// Forcibly disconnect a client (for client/server switching) AREXPORT void forceDisconnect(bool quiet); /// Gets how often a command is asked for AREXPORT long getFrequency(ArTypes::UByte2 command); /// Sets the TCP only flag AREXPORT void useTcpOnly(void) { myTcpOnly = true; } /// Gets the tcp only flag AREXPORT bool isTcpOnly(void) { return myTcpOnly; } /// Gets the state AREXPORT ServerState getState(void) { return myState; } /// Gets if we have any slow packets to process AREXPORT bool hasSlowPackets(void) { return myHaveSlowPackets; } /// Gets if we have any idle packets to process AREXPORT bool hasIdlePackets(void) { return myHaveIdlePackets; } /// Starts a new request transaction, incrementing the count. /** * This method is intended to be called solely by the ArServerBase. * It MUST be followed by a call to endRequestTransaction(). * * Request transactions are used under certain circumstances to * indicate that a number of related request/reply packets must * be completely processed before background idle processing can * proceed. See ArServerBase for more information. **/ AREXPORT void startRequestTransaction(); /// Ends the most recent request transaction, decrementing the count. /** * This method is intended to be called solely by the ArServerBase. * @see startRequestTransaction(). **/ AREXPORT bool endRequestTransaction(); /// Returns the number of request transactions that are currently in progress. /** * This method is intended to be called solely by the ArServerBase. * @see startRequestTransaction(). **/ AREXPORT int getRequestTransactionCount(); /// Returns the command ID for the specified name, or 0 if it is not found AREXPORT unsigned int findCommandFromName(const char *commandName) const; /// Get creation time AREXPORT ArTime getCreationTime(void) { return myCreationTime; } protected: const char *findCommandName(unsigned int command) const; // Some members so that we don't have to pass the number around std::list myCommandStack; std::list myForceTcpStack; std::list mySlowIdleCommandStack; std::list mySlowIdleForceTcpStack; AREXPORT bool setupPacket(ArNetPacket *packet); // Pushes a new number onto our little stack of numbers void pushCommand(unsigned int num); // Pops the command off the stack void popCommand(void); // Pushes a new number onto our little stack of numbers void pushSlowIdleCommand(unsigned int num); // Pops the command off the stack void popSlowIdleCommand(void); // Gets the command we're on unsigned int getCommand(); // Gets the command we're on bool getForceTcpFlag(); // Pushes a new forceTcp flag onto our little stack of flags void pushForceTcpFlag(bool forceTcp); // Pops the command off the stack void popForceTcpFlag(void); // Pushes a new forceTcp flag onto our little stack of flags void pushSlowIdleForceTcpFlag(bool forceTcp); // Pops the command off the stack void popSlowIdleForceTcpFlag(void); // this sends a list packet to our client void sendListPacket(void); // this could just be dealth with by seeing if myUserInfo is NULL, // but that may be confusing const ArServerUserInfo *myUserInfo; std::set myGroups; ArNetPacketSenderTcp myTcpSender; std::map *myDataMap; std::list myRequested; void internalSwitchState(ServerState state); ServerState myState; ArTime myStateStart; bool myUdpConfirmedFrom; bool myUdpConfirmedTo; ArSocket myTcpSocket; ArNetPacketReceiverTcp myTcpReceiver; ArFunctor2C myProcessPacketCB; ArRetFunctor2 *mySendUdpCB; struct sockaddr_in mySin; long myAuthKey; long myIntroKey; bool myTcpOnly; bool mySentTcpOnly; std::string myPasswordKey; std::string myServerKey; bool myDebugLogging; ArLog::LogLevel myVerboseLogLevel; std::string myLogPrefix; ArServerClientIdentifier myIdentifier; std::string myIPString; double myBackupTimeout; int myRejecting; std::string myRejectingString; std::string myEnforceProtocolVersion; ArServerCommands::Type myEnforceType; ArTime myTrackingStarted; class Tracker { public: Tracker() { reset(); } virtual ~Tracker() {} void reset(void) { myPacketsTcp = 0; myBytesTcp = 0; myPacketsUdp = 0; myBytesUdp = 0; } long myPacketsTcp; long myBytesTcp; long myPacketsUdp; long myBytesUdp; }; AREXPORT void trackPacketSent(ArNetPacket *packet, bool tcp); AREXPORT void trackPacketReceived(ArNetPacket *packet, ArTypes::UByte2); std::map myTrackingSentMap; std::map myTrackingReceivedMap; bool myLogPasswordFailureVerbosely; bool myAllowSlowPackets; bool myAllowIdlePackets; ArThread *mySlowIdleThread; bool myHaveSlowPackets; bool myHaveIdlePackets; ArMutex mySlowPacketsMutex; std::list mySlowPackets; ArMutex myIdlePacketsMutex; std::list myIdlePackets; /// Number of "request transactions" that are currently in progress for this client. int myRequestTransactionCount; /// Mutex for multi-threaded access to the request transaction count. ArMutex myRequestTransactionMutex; ArTime myCreationTime; }; #endif