MCS  0.3.3-alpha7
Server.cc
1 // ----------------------------------------------------------------------^
2 // Copyright (C) 2004, 2005, 2006, 2007, 2008 Giorgio Calderone
3 // (mailto: <gcalderone@ifc.inaf.it>)
4 //
5 // This file is part of MCS.
6 //
7 // MCS is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
11 //
12 // MCS is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with MCS; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21 // ----------------------------------------------------------------------$
22 
23 
24 #include "mcs.hh"
25 using namespace mcs;
26 
27 
28 #define PIDFILE "mcs.pid"
29 
30 
31 //--------------------------------------------------------
32 mcs::Server::Server(Env* lenv) : BaseThread(NULL, "MMM"),
33  dispatch(true)
34 {
35  //Initialize to NULL all callback function pointers.
36  cb_log = NULL;
37  cb_connect = NULL;
38  cb_auth = NULL;
39  cb_exec = NULL;
40  cb_postexec = NULL;
41  cb_disconnect = NULL;
42  cb_newClient = NULL;
43  cbwa_log = NULL;
44  cbwa_connect = NULL;
45  cbwa_auth = NULL;
46  cbwa_exec = NULL;
47  cbwa_postexec = NULL;
48 
49  pClient = NULL;
50  env=lenv; //env is a static member of Thread
51 
52  env->local = NULL;
53  if (env->cl_logstdout) {
54  //Print a banner
55  cout << MCS_BANNER;
56  cout << "\nYYYYMMDD HHMMSS thr MESSAGE" << endl;
57  cout <<
58  "-------- ------ --- " <<
59  "------------------------------------------------------------" <<
60  endl;
61  }
62 }
63 
64 
65 
66 
68 {
69  // env->server_running=false;
70 
71  if (env->local) {
72  Log(MCS_OK( MSG_KILLING_LOCAL ));
73  env->cl_restartlocal = 0;
74  env->local->stop(); //TESTING //env->local->exit(false);
75  }
76 
77  if (pClient) {
79  free(pClient);
80  }
81 
82  Log(MCS_OK( MSG_THREAD_DESTROY, "Server" ));
83 }
84 
85 
87 {
88  int i;
89  int newsock;
90 
91  set_cancel_state(false);
92 
93  try {
94  Log(MCS_OK( MSG_THREAD_CREATE, "Server" ));
95 
96  Log(MCS_OK( MSG_SERVER_DIR, env->path.csz ));
97 
98  if (env->max_users <= 0)
99  throw MCS_FATAL(MSG_ERROR, "max_users <= 0");
100 
101  pClient = (UserThread**) malloc(env->max_users * sizeof(UserThread*));
102  if (! pClient)
103  throw MCS_FATAL(MSG_OUT_OF_MEMORY);
104 
105  env->local=NULL;
106 
107  for (i=0; i<env->max_users; i++)
108  pClient[i]=NULL;
109 
110  if (env->cl_createlocal) {
111  Log(MCS_OK( MSG_CREATING_LOCAL ));
112  env->local=newLocalThread();
113  env->local->start();
114  }
115 
116  ServerSocket server(env->interface, env->port,
118  env->ssl_ctx = server.getSSLContext(); //To be passed to UserThread objects
119 
120  Log(MCS_OK( MSG_SERVER_RUNNING, server.ipaddress().c_str(), env->port ));
121 
122 
123  //Write the PIDFILE
124  {
125  ofstream of(PIDFILE, ios::out);
126  pid_t pid = getpid();
127  of << pid << endl;
128  of.close();
129  }
130 
131 
132  for(;;) {
133  set_cancel_state(true);
134  if (server.acceptConnection(newsock, 1000)) {
135  set_cancel_state(false);
136  newClient(newsock);
137  }
138  set_cancel_state(false);
139 
140  if (! env->local) {
141  if (env->cl_local_kills_mcs) {
142  Log(MCS_OK( MSG_LOCAL_THREAD_DIED ));
143  return;
144  }
145 
146  else if(env->cl_restartlocal) {
147  Log(MCS_OK( MSG_CREATING_LOCAL ));
148  env->local=newLocalThread();
149  env->local->start();
150  }
151  }
152  }
153  }
154  catch(Event e) {
155  Log(e);
156  if (e.type() == FATAL)
157  return;
158  }
159 }
160 
161 
162 
163 
164 void mcs::Server::notify(int id, Thread* ref)
165 {
166 #if ENABLE_DEBUG
167  Thread::notify(id, ref);
168 #endif
169 
170  //ref->allowTermination();
171 
172  if (ref == env->local) {
173  delete env->local; //TESTING
174  env->local = NULL;
175  }
176  else {
177  delete pClient[id]; //TESTING
178  pClient[id]=NULL;
179  }
180 }
181 
182 
183 
184 
186 {
187  int i, res=-1;
188  for (i=0; i<env->max_users; i++)
189  if (pClient[i] == NULL) {
190  res=i;
191  break;
192  }
193 
194  return res;
195 }
196 
197 
198 
199 
200 void mcs::Server::newClient(int newsock)
201 {
202  int i=find_free_id();
203  if (i >= 0) {
204  Log(MCS_OK( MSG_CREATING_CLIENT, i ));
205  pClient[i] = newUserThread(i, newsock);
206  pClient[i]->start();
207  hk_newClient(i);
208  }
209  else {
210  close(newsock);
211  Log(MCS_ERROR( MSG_NO_MORE_CLIENT_ALLOWED ));
212  }
213 }
214 
215 
216 
218 {
219  if (i>=0 && i<env->max_users)
220  if (pClient[i]) {
221  Log(MCS_OK( MSG_KILLING_CLIENT, i ));
222  pClient[i]->stop(); //TESTING //pClient[i]->exit(false);
223  }
224 }
225 
226 
228 {
229  if (pClient) {
230  Log(MCS_OK( MSG_KILLING_ALL_CLIENTS ));
231  for (int i=0; i<env->max_users; i++)
232  killClient(i);
233  }
234 }
235 
236 
238 {
239  RecordSet* ret = new RecordSet();
240 
241  for (int i=0; i<env->max_users; i++)
242  if (pClient[i])
243  ret->insert(pClient[i]->info());
244 
245  return ret;
246 }
247 
248 //vector<string> mcs::Server::clientsInfo()
249 //{
250 // vector<string> ret;
251 // string s;
252 // static string tab = "\t";
253 // struct ClientInfo* info;
254 //
255 //
256 // for (int i=0; i<env->max_users; i++) {
257 // info = NULL;
258 // if (pClient[i])
259 // info = pClient[i]->clientInfo();
260 //
261 // if (info) {
262 // s = itos(info->id) + tab;
263 // s += info->ipaddress + tab;
264 // s += info->hostname + tab;
265 // s += info->timeConnetcted + tab;
266 // s += info->username + tab;
267 // s += info->lastCommand + tab;
268 // s += info->timeLastCommand + tab;
269 // s += itos(info->commandExecuted) + tab;
270 // s += itos(info->logged);
271 // ret.push_back(s);
272 // }
273 // }
274 // return ret;
275 //}
276 
277 
278 
280 {
281  return new UserThread(this, lID, newsock);
282 }
283 
285 {
286  return new LocalThread(this);
287 }
288 
289 
291 {
292  if (cb_newClient)
293  (*(cb_newClient))(i);
294 }
295 
296 
297 
298 
299 
300 
301 
302 
304 {
305  addField(new Data (NULL, INT, "id" ));
306  addField(new Data (NULL, STRING, "ipaddress" , 15));
307  addField(new Data (NULL, STRING, "hostname" , 30));
308  addField(new Data (NULL, TIME, "timeConnected" ));
309  addField(new Data (NULL, STRING, "username" , 15));
310  addField(new Data (NULL, STRING, "lastCommand" , 30));
311  addField(new Data (NULL, TIME, "timeLastCommand" ));
312  addField(new Data (NULL, INT, "commandExecuted" ));
313  addField(new Data (NULL, TINY, "logged" ));
314 }
315 
316 
326 
327 
328 
329 //mcs::ClientsInfo_set::ClientsInfo_set(UserThread** pClient, int max_users) :
330 // RecordSet()
331 //{
332 // this->pClient = pClient;
333 // this->max_users = max_users;
334 // lastpos = 0;
335 //
336 // ClientsInfo tmp;
337 // metarec() = tmp;
338 // init(0, true, true);
339 //}
340 //
341 //
342 //bool mcs::ClientsInfo_set::fetch(unsigned int newpos, bool random)
343 //{
344 // ClientsInfo tmp;
345 //
346 // for (int i=lastpos; i<max_users; i++)
347 // if (pClient[i]) {
348 // rec() = pClient[i]->clientsInfo();
349 // rec().emptyName();
350 // lastpos = i;
351 // return true;
352 // }
353 //
354 // return false;
355 //}
356 
void(* cb_newClient)(int i)
Pointer to a void callback function, called by hk_newClient().
Definition: mcs.hh:7319
void(* cbwa_log)()
Pointer to a void callback function without arguments, called by hk_log().
Definition: mcs.hh:7304
Definition: mcs.hh:63
void newClient(int newsock)
Search for a free identifier and creates a new UserThread object.
Definition: Server.cc:200
void killClient(int i)
Kill client with specified identifier.
Definition: Server.cc:217
RetValue Log(Event e)
Logging facility.
Definition: BaseThread.cc:29
void(* cb_log)(UserThread *p, Event e)
Pointer to a callback function, called by hk_log().
Definition: mcs.hh:7286
int id()
Returns the Thread object identificator.
Definition: Thread.cc:310
void killAllClients()
Kills all UserThread and the LocalThread objects.
Definition: Server.cc:227
Base class for MCS threaded objects.
Definition: mcs.hh:6098
Data & lastCommand()
Last command executed.
Definition: Server.cc:322
virtual void notify(int id, Thread *ref)
A method called from child threads to notify their termination.
Definition: Thread.cc:326
void(* cbwa_postexec)()
Pointer to a void callback function without arguments, called by hk_postexec().
Definition: mcs.hh:7316
int port
Server port number.
Definition: mcs.hh:6941
void start()
Start a new thread in the joinable state.
Definition: Thread.cc:378
void stop()
Stop thread execution.
Definition: Thread.cc:507
The server side client thread.
Definition: mcs.hh:6365
UserThread ** pClient
Array of pointers to UserThread objects.
Definition: mcs.hh:7172
void(* cbwa_exec)()
Pointer to a void callback function without arguments, called by hk_exec().
Definition: mcs.hh:7313
Hold informations about an event.
Definition: mcs.hh:814
virtual void hk_newClient(int i)
Virtual method called when a new user connects to the server.
Definition: Server.cc:290
static Env * env
Pointer to the actual Env object, this can be seen in all threaded object.
Definition: mcs.hh:6116
A dynamic array of Data objects.
Definition: mcs.hh:4170
int find_free_id()
Search for a free client identifier when a new client tries to connect. See Env.max_users.
Definition: Server.cc:185
Data & timeLastCommand()
Time at which the last command was executed.
Definition: Server.cc:323
string path
Main server path (APPD).
Definition: mcs.hh:6929
bool acceptConnection(int &newsock, unsigned int millisec)
Wait for an incoming connection.
Definition: Socket.cc:878
The base class that implement the data abstraction layer.
Definition: mcs.hh:4510
#define MCS_ERROR(A, rest...)
Facility to easily pass all necessary parameter to an Event constructor.
Definition: mcs.hh:964
int max_users
How many clients can be connected at the same time.
Definition: mcs.hh:6949
Data & operator[](string name)
Definition: Record.cc:439
Data & timeConnetcted()
Time at which the client connected.
Definition: Server.cc:320
Data & commandExecuted()
Number of commands executed.
Definition: Server.cc:324
void * ssl_ctx
Pointer to the global SSL context object, used if cl_use_ssl is true.
Definition: mcs.hh:7018
Data & hostname()
Hostname of client.
Definition: Server.cc:319
bool cl_restartlocal
Resart local thread when it dies.
Definition: mcs.hh:6976
RetValue type()
Return the event type.
Definition: Event.cc:99
bool cl_createlocal
Create local thread.
Definition: mcs.hh:6973
Server(const Server &)
Declared to avoid using of default copy constructor.
RecordSet * getAll_ClientInfo()
Return a RecordSet object containing informations about all clients connections.
Definition: Server.cc:237
void run()
Server thread body.
Definition: Server.cc:86
virtual LocalThread * newLocalThread()
Wrapper around LocalThread constructors.
Definition: Server.cc:284
string ipaddress(int index=-1)
Return the IP address of an interface.
Definition: Socket.cc:144
Data & logged()
True if the client has logged in.
Definition: Server.cc:325
RetValue(* cb_auth)(int &, bool &)
Pointer to a callback function, called by hk_auth().
Definition: mcs.hh:7292
bool cl_local_kills_mcs
When the local thread dies the server will be stopped.
Definition: mcs.hh:6952
void notify(int id, Thread *ref)
Called when a child thread terminate, used to free resources.
Definition: Server.cc:164
void insert(Record *rec)
Insert a new record in the set.
Definition: Record.cc:673
Definition: mcs.hh:55
Server side administrative thread.
Definition: mcs.hh:6741
string interface
Server interface name.
Definition: mcs.hh:6938
Main include file for all MCS based applications.
bool cl_logstdout
Copy log on stdout.
Definition: mcs.hh:6970
~Server()
Destructor.
Definition: Server.cc:67
void addField(Data *d)
Wrapper around Dynamic_Array.push.
Definition: Record.cc:364
Data & username()
User name.
Definition: Server.cc:321
A general purpose data type.
Definition: mcs.hh:3092
void set_cancel_state(bool cancel)
Set cancellation state for current thread.
Definition: Thread.cc:338
RetValue(* cb_connect)()
Pointer to a callback function, called by hk_connect().
Definition: mcs.hh:7289
#define MCS_OK(A, rest...)
Facility to easily pass all necessary parameter to an Event constructor.
Definition: mcs.hh:958
Hold all environment variables.
Definition: mcs.hh:6867
Data & id()
Client ID, the same as the one returned with the MCS_CMD_CID command.
Definition: Server.cc:317
A class to create separate threads.
Definition: mcs.hh:2487
bool cl_use_ssl
Use secure connections.
Definition: mcs.hh:6988
string sslpriv
Path to the SSL private key file, used if cl_use_ssl = 1.
Definition: mcs.hh:6994
#define MCS_BANNER
MCS banner.
Definition: mcs.hh:232
virtual UserThread * newUserThread(int lID, int newsock)
Wrapper around UserThread constructors.
Definition: Server.cc:279
#define MCS_FATAL(A, rest...)
Facility to easily pass all necessary parameter to an Event constructor.
Definition: mcs.hh:967
RetValue(* cb_exec)(CommandParser *, bool &_executed)
Pointer to a callback function, called by hk_exec().
Definition: mcs.hh:7295
void(* cbwa_auth)()
Pointer to a void callback function without arguments, called by hk_auth().
Definition: mcs.hh:7310
string sslcert
Path to the SSL certificate file, used if cl_use_ssl = 1.
Definition: mcs.hh:6991
void(* cb_disconnect)()
Pointer to a callback function, called by hk_disconnect().
Definition: mcs.hh:7301
void(* cb_postexec)(CommandParser *, RetValue)
Pointer to a callback function, called by hk_postexec().
Definition: mcs.hh:7298
Manage TCP server sockets.
Definition: mcs.hh:2015
Data & ipaddress()
IP address of client.
Definition: Server.cc:318
ClientInfo()
Constructor.
Definition: Server.cc:303
Namespace for MCS library.
Definition: mcs.hh:58
void(* cbwa_connect)()
Pointer to a void callback function without arguments, called by hk_connect().
Definition: mcs.hh:7307

mcslogo

MCS (My Customizable Server) ver. 0.3.3-alpha7
Documentation generated on Mon May 28 07:39:41 UTC 2018