File: ArServerClient.h

package info (click to toggle)
libaria 2.8.0%2Brepack-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 13,628 kB
  • ctags: 16,574
  • sloc: cpp: 135,490; makefile: 925; python: 597; java: 570; ansic: 182
file content (284 lines) | stat: -rw-r--r-- 9,870 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
#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<bool, ArNetPacket *, 
	  struct sockaddr_in *> *sendUdpCallback,
	  std::map<unsigned int, ArServerData *> *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<unsigned int> myCommandStack;
  std::list<bool> myForceTcpStack;  
  std::list<unsigned int> mySlowIdleCommandStack;
  std::list<bool> 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<std::string, ArStrCaseCmpOp> myGroups;  
  ArNetPacketSenderTcp myTcpSender;
  std::map<unsigned int, ArServerData *> *myDataMap;
  std::list<ArServerClientData *> myRequested;
  void internalSwitchState(ServerState state);
  ServerState myState;
  ArTime myStateStart;
  bool myUdpConfirmedFrom;
  bool myUdpConfirmedTo;
  ArSocket myTcpSocket;
  ArNetPacketReceiverTcp myTcpReceiver;
  ArFunctor2C<ArServerClient, ArNetPacket *, bool> myProcessPacketCB;
  ArRetFunctor2<bool, ArNetPacket *, struct sockaddr_in *> *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<ArTypes::UByte2, Tracker *> myTrackingSentMap;
  std::map<ArTypes::UByte2, Tracker *> myTrackingReceivedMap;
  bool myLogPasswordFailureVerbosely;  

  bool myAllowSlowPackets;
  bool myAllowIdlePackets;

  ArThread *mySlowIdleThread;
  
  bool myHaveSlowPackets;
  bool myHaveIdlePackets;

  ArMutex mySlowPacketsMutex;
  std::list<ArNetPacket *> mySlowPackets;
  ArMutex myIdlePacketsMutex;
  std::list<ArNetPacket *> 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