Server.cc

00001 // ----------------------------------------------------------------------^
00002 // Copyright (C) 2004, 2005, 2006, 2007, 2008 Giorgio Calderone
00003 // (mailto: <gcalderone@ifc.inaf.it>)
00004 // 
00005 // This file is part of MCS.
00006 // 
00007 // MCS is free software; you can redistribute it and/or modify
00008 // it under the terms of the GNU General Public License as published by
00009 // the Free Software Foundation; either version 2 of the License, or
00010 // (at your option) any later version.
00011 // 
00012 // MCS is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 // 
00017 // You should have received a copy of the GNU General Public License
00018 // along with MCS; if not, write to the Free Software
00019 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 // 
00021 // ----------------------------------------------------------------------$
00022 
00023 
00024 #include "mcs.hh"
00025 using namespace mcs;
00026 
00027 
00028 #define  PIDFILE "mcs.pid"
00029 
00030 
00031 //--------------------------------------------------------
00032 mcs::Server::Server(Env* lenv) : BaseThread(NULL, "MMM"),
00033                  dispatch(true)
00034 {
00035   //Initialize to NULL all callback function pointers.
00036   cb_log          = NULL;
00037   cb_connect      = NULL;
00038   cb_auth     = NULL;
00039   cb_exec     = NULL;
00040   cb_postexec     = NULL;
00041   cb_disconnect   = NULL;
00042   cb_newClient    = NULL;
00043   cbwa_log        = NULL;
00044   cbwa_connect    = NULL;
00045   cbwa_auth   = NULL;
00046   cbwa_exec   = NULL;
00047   cbwa_postexec   = NULL;
00048 
00049   pClient = NULL;
00050   env=lenv;  //env is a static member of Thread
00051 
00052   env->local = NULL;
00053   if (env->cl_logstdout) {
00054     //Print a banner
00055     cout << MCS_BANNER;
00056     cout << "\nYYYYMMDD HHMMSS thr MESSAGE" << endl;
00057     cout <<
00058       "-------- ------ --- " <<
00059       "------------------------------------------------------------" <<
00060       endl;
00061   }
00062 }
00063 
00064 
00065 
00066 
00067 mcs::Server::~Server()
00068 {
00069   //  env->server_running=false;
00070 
00071   if (env->local) {
00072     Log(MCS_OK( MSG_KILLING_LOCAL ));
00073     env->cl_restartlocal = 0;
00074     env->local->stop();  //TESTING  //env->local->exit(false);
00075   }
00076 
00077   if (pClient) {
00078       killAllClients();
00079       free(pClient);
00080   }
00081 
00082   Log(MCS_OK( MSG_THREAD_DESTROY, "Server" ));
00083 }
00084 
00085 
00086 void mcs::Server::run()
00087 {
00088   int i;
00089   int newsock;
00090 
00091   set_cancel_state(false);
00092 
00093   try {
00094     Log(MCS_OK( MSG_THREAD_CREATE, "Server" ));
00095 
00096     Log(MCS_OK( MSG_SERVER_DIR, env->path.csz ));
00097 
00098     if (env->max_users <= 0)
00099     throw MCS_FATAL(MSG_ERROR, "max_users <= 0");
00100 
00101     pClient = (UserThread**) malloc(env->max_users * sizeof(UserThread*));
00102     if (! pClient)
00103     throw MCS_FATAL(MSG_OUT_OF_MEMORY);
00104 
00105     env->local=NULL;
00106 
00107     for (i=0; i<env->max_users; i++)
00108       pClient[i]=NULL;
00109 
00110     if (env->cl_createlocal) {
00111     Log(MCS_OK( MSG_CREATING_LOCAL ));
00112     env->local=newLocalThread();
00113     env->local->start();
00114     }
00115 
00116     ServerSocket server(env->interface, env->port,
00117             env->cl_use_ssl, env->sslcert, env->sslpriv);
00118     env->ssl_ctx = server.getSSLContext(); //To be passed to UserThread objects
00119 
00120     Log(MCS_OK( MSG_SERVER_RUNNING, server.ipaddress().c_str(), env->port ));
00121 
00122 
00123     //Write the PIDFILE
00124     {
00125       ofstream of(PIDFILE, ios::out);
00126       pid_t pid = getpid();
00127       of << pid << endl;
00128       of.close();
00129     }
00130 
00131 
00132     for(;;) {
00133       set_cancel_state(true);
00134       if (server.acceptConnection(newsock, 1000)) {
00135     set_cancel_state(false);
00136     newClient(newsock);
00137       }
00138       set_cancel_state(false);
00139 
00140       if (! env->local) {
00141     if (env->cl_local_kills_mcs) {
00142       Log(MCS_OK( MSG_LOCAL_THREAD_DIED ));
00143       return;
00144     }
00145 
00146     else if(env->cl_restartlocal) {
00147       Log(MCS_OK( MSG_CREATING_LOCAL ));
00148       env->local=newLocalThread();
00149       env->local->start();
00150     }
00151       }
00152     }
00153   }
00154   catch(Event e) {
00155     Log(e);
00156     if (e.type() == FATAL)
00157       return;
00158   }
00159 }
00160 
00161 
00162 
00163 
00164 void mcs::Server::notify(int id, Thread* ref)
00165 {
00166 #if ENABLE_DEBUG
00167   Thread::notify(id, ref);
00168 #endif
00169 
00170   //ref->allowTermination();
00171 
00172   if (ref == env->local) {
00173     delete env->local; //TESTING
00174     env->local = NULL;
00175   }
00176   else {
00177     delete pClient[id]; //TESTING
00178     pClient[id]=NULL;
00179   }
00180 }
00181 
00182 
00183 
00184 
00185 int mcs::Server::find_free_id()
00186 {
00187   int i, res=-1;
00188   for (i=0; i<env->max_users; i++)
00189     if (pClient[i] == NULL) {
00190       res=i;
00191       break;
00192     }
00193 
00194   return res;
00195 }
00196 
00197 
00198 
00199 
00200 void mcs::Server::newClient(int newsock)
00201 {
00202   int i=find_free_id();
00203   if (i >= 0) {
00204     Log(MCS_OK( MSG_CREATING_CLIENT, i ));
00205     pClient[i] = newUserThread(i, newsock);
00206     pClient[i]->start();
00207     hk_newClient(i);
00208   }
00209   else {
00210     close(newsock);
00211     Log(MCS_ERROR( MSG_NO_MORE_CLIENT_ALLOWED ));
00212   }
00213 }
00214 
00215 
00216 
00217 void mcs::Server::killClient(int i)
00218 {
00219   if (i>=0 && i<env->max_users)
00220     if (pClient[i]) {
00221       Log(MCS_OK( MSG_KILLING_CLIENT, i ));
00222       pClient[i]->stop(); //TESTING  //pClient[i]->exit(false);
00223     }
00224 }
00225 
00226 
00227 void mcs::Server::killAllClients()
00228 {
00229   if (pClient) {
00230     Log(MCS_OK( MSG_KILLING_ALL_CLIENTS ));
00231     for (int i=0; i<env->max_users; i++)
00232       killClient(i);
00233   }
00234 }
00235 
00236 
00237 RecordSet* mcs::Server::getAll_ClientInfo()
00238 {
00239   RecordSet* ret = new RecordSet();
00240 
00241   for (int i=0; i<env->max_users; i++)
00242     if (pClient[i])
00243       ret->insert(pClient[i]->info());
00244 
00245   return ret;
00246 }
00247 
00248 //vector<string> mcs::Server::clientsInfo()
00249 //{
00250 //    vector<string> ret;
00251 //    string s;
00252 //    static string tab = "\t";
00253 //    struct ClientInfo* info;
00254 //
00255 //
00256 //    for (int i=0; i<env->max_users; i++) {
00257 //  info = NULL;
00258 //  if (pClient[i])
00259 //      info = pClient[i]->clientInfo();
00260 //
00261 //  if (info) {
00262 //      s  = itos(info->id)              + tab;
00263 //      s += info->ipaddress             + tab;
00264 //      s += info->hostname              + tab;
00265 //      s += info->timeConnetcted        + tab;
00266 //      s += info->username              + tab;
00267 //      s += info->lastCommand           + tab;
00268 //      s += info->timeLastCommand       + tab;
00269 //      s += itos(info->commandExecuted) + tab;
00270 //      s += itos(info->logged);
00271 //      ret.push_back(s);
00272 //  }
00273 //    }
00274 //    return ret;
00275 //}
00276 
00277 
00278 
00279 UserThread* mcs::Server::newUserThread(int lID, int newsock)
00280 {
00281   return new UserThread(this, lID, newsock);
00282 }
00283 
00284 LocalThread* mcs::Server::newLocalThread()
00285 {
00286   return new LocalThread(this);
00287 }
00288 
00289 
00290 void mcs::Server::hk_newClient(int i)
00291 {
00292     if (cb_newClient)
00293     (*(cb_newClient))(i);
00294 }
00295 
00296 
00297 
00298 
00299 
00300 
00301 
00302 
00303 mcs::ClientInfo::ClientInfo() :  Record()
00304 {
00305   addField(new Data (NULL, INT,    "id"                 ));
00306   addField(new Data (NULL, STRING, "ipaddress"      , 15));
00307   addField(new Data (NULL, STRING, "hostname"       , 30));
00308   addField(new Data (NULL, TIME,   "timeConnected"      ));
00309   addField(new Data (NULL, STRING, "username"       , 15));
00310   addField(new Data (NULL, STRING, "lastCommand"    , 30));
00311   addField(new Data (NULL, TIME,   "timeLastCommand"    ));
00312   addField(new Data (NULL, INT,    "commandExecuted"    ));
00313   addField(new Data (NULL, TINY,   "logged"             ));
00314 }
00315 
00316 
00317 Data& mcs::ClientInfo::id()               { return operator[](0); }
00318 Data& mcs::ClientInfo::ipaddress()    { return operator[](1); }
00319 Data& mcs::ClientInfo::hostname()     { return operator[](2); }
00320 Data& mcs::ClientInfo::timeConnetcted()   { return operator[](3); }
00321 Data& mcs::ClientInfo::username()     { return operator[](4); }
00322 Data& mcs::ClientInfo::lastCommand()      { return operator[](5); }
00323 Data& mcs::ClientInfo::timeLastCommand()  { return operator[](6); }
00324 Data& mcs::ClientInfo::commandExecuted()  { return operator[](7); }
00325 Data& mcs::ClientInfo::logged()           { return operator[](8); }
00326 
00327 
00328 
00329 //mcs::ClientsInfo_set::ClientsInfo_set(UserThread** pClient, int max_users) :
00330 //  RecordSet()
00331 //{
00332 //  this->pClient = pClient;
00333 //  this->max_users = max_users;
00334 //  lastpos = 0;
00335 //
00336 //  ClientsInfo tmp;
00337 //  metarec() = tmp;
00338 //  init(0, true, true);
00339 //}
00340 //
00341 //
00342 //bool mcs::ClientsInfo_set::fetch(unsigned int newpos, bool random)
00343 //{
00344 //  ClientsInfo tmp;
00345 //
00346 //  for (int i=lastpos; i<max_users; i++)
00347 //    if (pClient[i]) {
00348 //      rec() = pClient[i]->clientsInfo();
00349 //      rec().emptyName();
00350 //      lastpos = i;
00351 //      return true;
00352 //    }
00353 //
00354 //  return false;
00355 //}
00356 

mcslogo

MCS (My Customizable Server) ver. 0.3.3-alpha3
Documentation generated on Thu Mar 22 13:22:23 UTC 2012