botkernel.cpp

Go to the documentation of this file.
00001 /*
00002 #########################################################################
00003 #
00004 #  This file is part of trustyRC.
00005 #
00006 #  trustyRC, fully modular IRC robot 
00007 #  Copyright (C) 2006-2008 Nicoleau Fabien 
00008 #
00009 #  trustyRC is free software: you can redistribute it and/or modify
00010 #  it under the terms of the GNU General Public License as published by
00011 #  the Free Software Foundation, either version 3 of the License, or
00012 #  (at your option) any later version.
00013 #
00014 #  trustyRC is distributed in the hope that it will be useful,
00015 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 #  GNU General Public License for more details.
00018 #
00019 #  You should have received a copy of the GNU General Public License
00020 #  along with trustyRC.  If not, see <http://www.gnu.org/licenses/>.
00021 #
00022 #########################################################################
00023 */
00024 
00030 #include "botkernel.h"
00032 void * threadFunc (void *);
00033 
00041 BotKernel::BotKernel(string confFile)
00042 {
00043         this->author = "eponyme (Nicoleau Fabien)";
00044         this->version = VERSION;
00045         this->description = "trustyRC kernel";
00046         this->in_loop_plugins.clear();
00047         this->in_command_handler_plugins.clear();
00048    this->in_free_command_handler_plugins.clear();
00049         this->in_type_handler_plugins.clear();
00050         this->in_before_treatment_plugins.clear();
00051         this->in_all_msgs_plugins.clear();
00052    this->countDowns.clear();
00053         this->sendQueue.clear();
00054 
00055         this->conff=new ConfigurationFile(confFile);
00056         if(!this->conff->load()) {
00057                 cerr << "Error loading configuration file (" + confFile+ "). Exiting..." <<endl;
00058                 exit(0);
00059         }
00060         if (this->conff->getValue("kernel.verbose")=="1") {
00061       this->displayLicenceHeader() ;
00062                 this->verbose=true;
00063    }
00064         else {
00065                 this->verbose=false;
00066    }
00067    this->initDirs();
00068         this->myLog = new LogFile(this->datasDir+"syslog/"+"trustyrc-",this->verbose,(this->conff->getValue("kernel.logkeepfiles")=="1")?true:false,this->conff->getValue("kernel.logminlevel"),this->conff->getValue("kernel.logperiod"));
00069    if ( ! this->myLog->open() ) {
00070       cerr<< "Error opening log file. Nothing will be logged" << endl;
00071    }
00072    this->conff->addProtectedKey("remotecontrol.port");
00073    this->conff->addProtectedKey("remotecontrol.accounts");
00074    this->conff->addProtectedKey("remotecontrol.maxclients");
00075    this->conff->addProtectedKey("admin.sapass");
00076         this->sock=new Socket(); 
00077    time(&this->startTime);
00078         this->connected=false;
00079         this->turn=true;        
00080         this->loadPlugins(true);
00081    this->AEX.penality = 0;
00082    time(&this->AEX.last_decrease);
00083 }
00084 
00089 BotKernel::~BotKernel()
00090 {
00091         this->myLog->log("Going to delete kernel objects ...",INFO);
00092         this->unloadMyPlugins(false);
00093         delete(this->sock);
00094         delete(this->conff);
00095         delete(this->myLog);
00096 }
00097 
00102 void BotKernel::connect()
00103 {
00104         this->turn=true;
00105         this->myLog->log("Trying to connect to " + this->conff->getValue("kernel.server"),INFO);
00106    while(!this->sock->connectSock(Tools::strToInt(this->conff->getValue("kernel.port")),this->conff->getValue("kernel.server"),this->conff->getValue("kernel.dedicatedIP")))
00107    {    
00108       this->myLog->log("Unable to connect, waiting "+this->conff->getValue("kernel.reco_wait")+" seconds ...",ERROR);
00109       sleep(Tools::strToInt(this->conff->getValue("kernel.reco_wait"))); 
00110    }
00111         this->send(IRCProtocol::identify(this->conff->getValue("kernel.password"),this->conff->getValue("kernel.ident"),this->conff->getValue("kernel.name"),this->conff->getValue("kernel.nick")));
00112         this->setConnected(true);
00113         this->myLog->log("Bot connected : " + this->conff->getValue("kernel.server")+":"+this->conff->getValue("kernel.port")+" (password:"+this->conff->getValue("kernel.password")+") "+this->conff->getValue("kernel.nick")+" "+this->conff->getValue("kernel.ident")+((this->conff->getValue("kernel.dedicatedIP")=="")?"":" through "+this->conff->getValue("kernel.dedicatedIP")),INFO);
00114         this->setNick(this->conff->getValue("kernel.nick"));
00115    time(&this->startOnline);
00116 }
00117 
00122 void BotKernel::reconnect()
00123 {
00124         this->myLog->log("Bot going to reconnect",INFO);
00125    this->sock->closeSock();
00126         delete(this->sock); 
00127         this->sock=new Socket();
00128         this->setConnected(false);
00129         this->connect();
00130 }
00131 
00136 void BotKernel::run()
00137 {
00138         time_t now;
00139    vector<CountDownFunction>::iterator it;
00140    list<string> queue;
00141         bool treatMsg = true;
00142    bool complete;
00143    unsigned int startIndex;
00144         Message m;
00145    string buffer;
00146    vector<string> messages;
00147    Tools::log(this->getDatasDir()+"trustyrc.pid",Tools::intToStr(getpid()),false,true) ;
00148    this->connect();
00149    queue.clear();
00150    while(this->turn)
00151    {
00152       if ((!queue.empty())&&(queue.front()[queue.front().length()-1]=='\n')){ // check if a message is present, and if it's complete
00153         buffer = queue.front();
00154         queue.pop_front();
00155       }
00156       else {
00157          buffer = this->sock->receive();
00158          if (!this->sock->getState()) {
00159             this->myLog->log("Disconnected (read error)",WARNING);
00160             this->setConnected(false);
00161          }
00162          else {
00163             if (buffer.length() > 2 )
00164             {
00165                messages = Tools::stringToVector(buffer,"\n",0);
00166                if ( buffer[buffer.length()-1] == '\n') { // check if last received message is complete
00167                   complete = true;
00168                }
00169                else {
00170                   complete = false;
00171                }
00172                if((!queue.empty())&&(queue.back()[queue.back().length()-1]!='\n')) { // check if last message stored in queue is not complete
00173                   queue.back() += messages[0]+'\n';
00174                   startIndex = 1;
00175                }
00176                else {
00177                   startIndex = 0 ;   
00178                }
00179                for(unsigned int i = startIndex; i < messages.size() ; i ++ ) {
00180                   queue.push_back(messages[i]+'\n');
00181                } 
00182                if (!complete) {
00183                   queue.back() = queue.back().substr(0,queue.back().length()-1);     
00184                }
00185                buffer = queue.front();
00186                queue.pop_front();
00187             }  
00188          }
00189       }
00190       if (buffer.length() > 2 )
00191       {
00192          // \r\n 
00193          if ( buffer[buffer.length()-2] == '\r' ) {
00194             buffer.erase(buffer.length()-2); 
00195          } // \n
00196          else { 
00197             buffer.erase(buffer.length()-1); 
00198          }
00199          if(this->verbose) {
00200             cout << buffer << endl;
00201          }
00202          m.setMessage(buffer);
00203                    treatMsg = true;
00204                    // IN_BEFORE_TREATMENT
00205                    for ( unsigned int i = 0 ; i < this->in_before_treatment_plugins.size() ; i ++ )
00206                    {
00207                       if(!this->executeFunction(&m,this->in_before_treatment_plugins[i])) {
00208                          treatMsg = false;
00209                                 break;
00210                       }
00211                    }  
00212                    if(treatMsg) {
00213                  this->msgTreatment(&m);
00214          }
00215       }
00216                 // IN_LOOP & COUNTDOWN
00217                 time(&now);
00218       it = this->countDowns.begin();
00219       while ( it != this->countDowns.end() ) {
00220          if ( now >= (*it).timestamp ) {
00221             if(this->executeFunction(&((*it).msg),(*it).function)) {
00222                this->countDowns.erase(it);
00223             }
00224             else {
00225                (*it).timestamp = now + (*it).count;
00226                it ++ ;
00227             }
00228          }
00229          else {
00230             it ++ ;
00231          }
00232       }
00233                 for ( unsigned int i = 0 ; i < this->in_loop_plugins.size() ; i ++ )
00234                 {
00235                         if ( this->in_loop_plugins[i].highlightedWord == "") {
00236                                 this->executeFunction(NULL,this->in_loop_plugins[i]);
00237                         }
00238                         else {
00239                                 if ((now-this->in_loop_plugins[i].lastExec)>= Tools::strToInt(this->in_loop_plugins[i].highlightedWord) ) {
00240                                         this->executeFunction(NULL,this->in_loop_plugins[i]);
00241                                         time(&this->in_loop_plugins[i].lastExec);
00242                                 }
00243                         }
00244                 }
00245                 if (!this->connected && this->turn)
00246                 {
00247                         this->myLog->log("Disconnected, waiting 10 seconds ...",INFO);
00248                         sleep(10);
00249                         this->reconnect();
00250                 }
00251    }
00252    this->sock->closeSock();
00253 }
00254 
00258 void BotKernel::stop()
00259 {
00260         this->myLog->log("stopped !",INFO);
00261         this->turn = false;
00262 }
00263 
00268 void BotKernel::loadPlugins(bool checkDependancy)
00269 {
00270         int plugOK=0,plugNOK=0;
00271         vector<string> plugins = Tools::stringToVector(this->conff->getValue("kernel.plugins"),",",0);
00272         for(unsigned int i =0;i < plugins.size() ; i ++ )
00273         {
00274                 if(this->loadPlugin(plugins[i],checkDependancy)) {
00275                         plugOK++;
00276                 }
00277                 else {
00278                         plugNOK++;
00279                 }
00280         }
00281         this->myLog->log(Tools::intToStr(plugOK)+" plugin(s) successfully loaded. "+Tools::intToStr(plugNOK)+" plugin(s) unsuccessfully loaded.",INFO);
00282 }
00283 
00291 bool BotKernel::loadPlugin(string fileName,bool checkDependancy)
00292 {
00293         void*handle;
00294    char * error;
00295         Plugin* obj;
00296    const unsigned int NBPATHS = 3;
00297    vector<string> requirements;
00298         plugin_constructor constructor;
00299         plugin_destructor destructor;
00300         StructFunctionStorage func;
00301         vector<StructFunctionStorage> funcs;
00302         pPlugin plug;
00303    string paths[NBPATHS] = {this->datasDir+"../plugins",PLUGINSDIR,"plugins"};
00304 
00305    for(unsigned int i = 0 ; i < NBPATHS ; i ++ ) {
00306         handle = dlopen((paths[i]+"/"+fileName).c_str(), RTLD_NOW);
00307         if (handle==NULL) {
00308          continue;
00309       }
00310       constructor = (plugin_constructor)(intptr_t) dlsym(handle,("contruct_"+fileName.substr(0,fileName.find("."))).c_str()); //*(void **)(&constructor) = dlsym(handle,("contruct_"+fileName.substr(0,fileName.find("."))).c_str()); //constructor = (plugin_constructor) dlsym(handle,("contruct_"+fileName.substr(0,fileName.find("."))).c_str());
00311       if (constructor==NULL) {
00312                    this->myLog->log("Cannot load symbol create("+fileName+"): " + dlerror(),ERROR);
00313          return false;
00314       }
00315            destructor = (plugin_destructor)(intptr_t) dlsym(handle, ("destroy_"+fileName.substr(0,fileName.find("."))).c_str()); //*(void **)(&destructor) = dlsym(handle, ("destroy_"+fileName.substr(0,fileName.find("."))).c_str()); // destructor = (plugin_destructor) dlsym(handle, ("destroy_"+fileName.substr(0,fileName.find("."))).c_str());
00316       if (destructor==NULL) {
00317                    this->myLog->log("Cannot load symbol destroy("+fileName+"): " + dlerror(),ERROR);
00318          return false;
00319       } 
00320            obj = constructor(this);
00321 
00322         plug.name = obj->getName();
00323         plug.handle = handle;
00324         plug.object = obj ;
00325         plug.creator = constructor;
00326         plug.destructor = destructor;
00327 
00328            if ( !obj->checkMembers() ) {
00329                 this->myLog->log("Attributs error("+fileName+")",ERROR);
00330                    plug.destructor(plug.object);
00331                 dlclose(plug.handle);
00332                 return false;
00333         }
00334         if ( this->pluginLoaded(plug.name) ) {
00335                 this->myLog->log("Plugin \"" + plug.name + "\" already loaded",WARNING);
00336                 plug.destructor(plug.object);
00337                 dlclose(plug.handle);
00338                 return false;
00339         }
00340       if(checkDependancy) {
00341          requirements = plug.object->getRequirements() ;
00342          for(unsigned int i = 0 ; i < requirements.size() ; i ++ ) {
00343             if(!this->pluginLoaded(requirements[i]) ) {
00344                this->myLog->log("Cannot load "+plug.name+". "+requirements[i]+" is required and not loaded",ERROR);
00345                          plug.destructor(plug.object);
00346                          dlclose(plug.handle);
00347                          return false;
00348             }
00349          }
00350       }
00351       plug.object->setHandle(plug.handle);
00352            this->myPlugins.push_back(plug);
00353            funcs = obj->getFunctions();
00354            for (unsigned int i = 0 ; i < funcs.size() ; i ++ ) {
00355                    func = funcs[i];
00356                    func.handle = handle;        
00357          func.function = (plugin_function)(intptr_t) dlsym(handle, func.symbole.c_str()); //*(void **)(&func.function) = dlsym(handle, func.symbole.c_str()); // func.function = (plugin_function) dlsym(handle, func.symbole.c_str());
00358                    if (func.function==NULL) {
00359                            this->myLog->log("Cannot load symbol "+func.symbole+" ("+fileName+"): " + dlerror(),WARNING);
00360                    }    
00361                    else {
00362             this->storeFunction(&func);
00363                    }
00364            }
00365            this->myLog->log("Plugin "+fileName+" successfully loaded",INFO);
00366            return true;
00367    }
00368    error = dlerror();
00369    if ( error != NULL) {
00370       this->myLog->log("Cannot load library " +fileName+":" + error,ERROR);
00371    }
00372    return false;
00373 }
00374 
00382 bool BotKernel::unloadPlugin(string name,bool checkDependancy)
00383 {
00384         void * handle;
00385    vector<pPlugin>::iterator it = this->myPlugins.begin();
00386         vector<StructFunctionStorage>::iterator it2 ;
00387    if (checkDependancy) {
00388       for(unsigned int i = 0 ; i < this->myPlugins.size() ; i++ ) {
00389          if ( this->myPlugins[i].object->requires(name) ) {
00390             this->myLog->log("Cannot unload "+name+". "+myPlugins[i].name+" requires this plugin and is loaded",ERROR);
00391             return false;
00392          }
00393       }
00394    }
00395    while ( it != this->myPlugins.end() )
00396    {
00397       if ( (*it).name == name )
00398       {
00399                         handle = (*it).handle;
00400                         (*it).destructor((*it).object);
00401          this->myPlugins.erase(it);
00402                         it2 = this->in_loop_plugins.begin();
00403                         while ( it2 != this->in_loop_plugins.end() ) {
00404                                 if ( (*it2).handle == handle )
00405                                         this->in_loop_plugins.erase(it2);
00406                                 else 
00407                                         it2 ++;
00408                         }
00409                         it2 = this->in_command_handler_plugins.begin();
00410                         while ( it2 != this->in_command_handler_plugins.end() ) {
00411                                 if ( (*it2).handle == handle )
00412                                         this->in_command_handler_plugins.erase(it2);
00413                                 else 
00414                                         it2 ++;
00415                         }
00416                         it2 = this->in_free_command_handler_plugins.begin();
00417                         while ( it2 != this->in_free_command_handler_plugins.end() ) {
00418                                 if ( (*it2).handle == handle )
00419                                         this->in_free_command_handler_plugins.erase(it2);
00420                                 else 
00421                                         it2 ++;
00422                         }
00423                         it2 = this->in_type_handler_plugins.begin();
00424                         while ( it2 != this->in_type_handler_plugins.end() ) {
00425                                 if ( (*it2).handle == handle )
00426                                         this->in_type_handler_plugins.erase(it2);
00427                                 else 
00428                                         it2 ++;
00429                         }
00430                         it2 = this->in_before_treatment_plugins.begin();
00431                         while ( it2 != this->in_before_treatment_plugins.end() ) {
00432                                 if ( (*it2).handle == handle )
00433                                         this->in_before_treatment_plugins.erase(it2);
00434                                 else 
00435                                         it2 ++;
00436                         }
00437                         it2 = this->in_all_msgs_plugins.begin();
00438                         while ( it2 != this->in_all_msgs_plugins.end() ) {
00439                                 if ( (*it2).handle == handle )
00440                                         this->in_all_msgs_plugins.erase(it2);
00441                                 else 
00442                                         it2 ++;
00443                         }
00444                         it2 = this->in_first_word_plugins.begin();
00445                         while ( it2 != this->in_first_word_plugins.end() ) {
00446                                 if ( (*it2).handle == handle )
00447                                         this->in_first_word_plugins.erase(it2);
00448                                 else 
00449                                         it2 ++;
00450                         }
00451                         it2 = this->out_all_msgs_plugins.begin();
00452                         while ( it2 != this->out_all_msgs_plugins.end() ) {
00453                                 if ( (*it2).handle == handle )
00454                                         this->out_all_msgs_plugins.erase(it2);
00455                                 else 
00456                                         it2 ++;
00457                         }
00458                         this->myLog->log("Plugin "+name + " unloaded",INFO);
00459                         dlclose(handle);
00460          return true;
00461       }
00462       else
00463          it ++ ;
00464    }
00465    return false;
00466 }
00467 
00473 void BotKernel::unloadMyPlugins(bool checkDependancy)
00474 {
00475         while(this->myPlugins.size()>0)
00476         {
00477                 this->unloadPlugin(this->myPlugins[0].name,checkDependancy);
00478         }
00479 }
00480 
00488 bool BotKernel::pluginLoaded(string name)
00489 {
00490         for ( unsigned int i = 0 ; i < this->myPlugins.size() ; i ++ )
00491         {
00492                 if (this->myPlugins[i].name == name )
00493                         return true;
00494         }
00495         return false;
00496 }
00497 
00504 bool BotKernel::pluginLoaded(void*handle)
00505 {
00506         for ( unsigned int i = 0 ; i < this->myPlugins.size() ; i ++ )
00507         {
00508                 if (this->myPlugins[i].handle == handle )
00509                         return true;
00510         }
00511         return false;
00512 }
00513 
00519 plugin_function BotKernel::storeFunction(StructFunctionStorage*func)
00520 {
00521    switch (func->type) {
00522            case IN_LOOP : this->in_loop_plugins.push_back(*func);    
00523                 break;
00524                 case IN_COMMAND_HANDLER : this->in_command_handler_plugins.push_back(*func);
00525                 break;
00526       case IN_FREE_COMMAND_HANDLER : this->in_free_command_handler_plugins.push_back(*func);
00527       break;
00528                 case IN_TYPE_HANDLER : this->in_type_handler_plugins.push_back(*func);
00529                 break;
00530                 case IN_BEFORE_TREATMENT : this->in_before_treatment_plugins.push_back(*func);
00531                 break;
00532                 case IN_ALL_MSGS : this->in_all_msgs_plugins.push_back(*func);
00533                 break;
00534       case IN_FIRST_WORD : this->in_first_word_plugins.push_back(*func) ;
00535       break;
00536       case OUT_ALL_MSGS : this->out_all_msgs_plugins.push_back(*func) ;
00537       break;
00538            default : this->myLog->log("Undefined func type for "+func->symbole,WARNING);
00539                 return NULL;
00540         }
00541    return func->function ;
00542 }
00543 
00556 plugin_function BotKernel::registerFunction(string hlword,Plugin*object,func_type type,string symbole,plugin_function function,time_t lastExec,unsigned int timeout)
00557 {
00558    if (!this->pluginLoaded(object->getHandle())) {
00559       return NULL;
00560    }
00561    StructFunctionStorage store;
00562    store.handle = object->getHandle();
00563    store.highlightedWord = hlword;
00564    store.object = object;
00565    store.type = type;
00566    store.symbole = symbole;
00567    store.function = function;
00568    store.lastExec = lastExec;
00569    store.timeout = timeout;
00570    return this->storeFunction(&store);
00571 }
00572 
00577 void BotKernel::unregisterFunction(plugin_function func)
00578 {
00579    vector<StructFunctionStorage>::iterator it ;
00580    vector<CountDownFunction>::iterator itCount;
00581    it = this->in_loop_plugins.begin();
00582    while ( it != this->in_loop_plugins.end() ) {
00583       if ( (*it).function == func ) { this->in_loop_plugins.erase(it); return; }
00584       it++;
00585         }
00586         it = this->in_command_handler_plugins.begin();
00587    while ( it != this->in_command_handler_plugins.end() ) {
00588       if ( (*it).function == func ) { this->in_command_handler_plugins.erase(it); return; }
00589       it++;
00590         }
00591         it = this->in_free_command_handler_plugins.begin();
00592    while ( it != this->in_free_command_handler_plugins.end() ) {
00593       if ( (*it).function == func ) { this->in_free_command_handler_plugins.erase(it); return; }
00594       it++;
00595         }
00596         it = this->in_type_handler_plugins.begin();
00597    while ( it != this->in_type_handler_plugins.end() ) {
00598       if ( (*it).function == func ) { this->in_type_handler_plugins.erase(it); return; }
00599       it++;
00600         }
00601         it = this->in_before_treatment_plugins.begin();
00602    while ( it != this->in_before_treatment_plugins.end() ) {
00603       if ( (*it).function == func ) { this->in_before_treatment_plugins.erase(it); return; }
00604       it++;
00605         }
00606         it = this->in_all_msgs_plugins.begin();
00607    while ( it != this->in_all_msgs_plugins.end() ) {
00608       if ( (*it).function == func ) { this->in_all_msgs_plugins.erase(it); return; }
00609       it++;
00610         }
00611         it = this->in_first_word_plugins.begin();
00612    while ( it != this->in_first_word_plugins.end() ) {
00613       if ( (*it).function == func ) { this->in_first_word_plugins.erase(it); return; }
00614       it++;
00615         }
00616         it = this->out_all_msgs_plugins.begin();
00617    while ( it != this->out_all_msgs_plugins.end() ) {
00618       if ( (*it).function == func ) { this->out_all_msgs_plugins.erase(it); return; }
00619       it++;
00620         }
00621    itCount = this->countDowns.begin();
00622    while ( itCount != this->countDowns.end() ) {
00623       if ( (*itCount).function.function == func ) { this->countDowns.erase(itCount); return; }
00624       itCount++;
00625         }
00626 }
00627 
00639 plugin_function BotKernel::addCountDown(Plugin*p,plugin_function f,Message* m,unsigned int count,unsigned int timeout)
00640 {  
00641    string max = this->conff->getValue("kernel.maxcountdowns") ;
00642    if ( (max=="") || (max=="0") || (Tools::strToUnsignedInt(max)>=this->countDowns.size()) ) {
00643       time_t now;
00644       time(&now);
00645       StructFunctionStorage sfs ;
00646       CountDownFunction cdf;
00647       Message msg(m->getMessage());
00648       sfs.handle = p->getHandle();
00649       sfs.highlightedWord = "";
00650       sfs.object = p;
00651       sfs.type = COUNTDOWN;
00652       sfs.symbole = "countDown";
00653       sfs.function = f;
00654       sfs.lastExec = 0;
00655       sfs.timeout = timeout;
00656       cdf.function = sfs;
00657       cdf.msg = msg;
00658       cdf.count = count;
00659       cdf.timestamp=now+count;
00660       this->countDowns.push_back(cdf);
00661       return f;
00662    }
00663    else {
00664       this->myLog->log("Max count downs reached : "+Tools::intToStr(this->countDowns.size()),WARNING);
00665       return NULL;
00666    }
00667 }
00668 
00674 void BotKernel::msgTreatment(Message* msg)
00675 {
00676    // IN_FIRST_WORD
00677    for ( unsigned int i = 0 ; i < this->in_first_word_plugins.size() ; i ++ ) {
00678       if ( msg->getPart(0) == this->in_first_word_plugins[i].highlightedWord ) {
00679          this->executeFunction(msg,this->in_first_word_plugins[i]);      
00680       }
00681    }
00682         // IN_TYPE_HANDLER
00683         if ( msg->getSplit().size() >= 2 ) {
00684                 for ( unsigned int i = 0 ; i < this->in_type_handler_plugins.size() ; i ++ ) {
00685                         if ( msg->getPart(1) == this->in_type_handler_plugins[i].highlightedWord ) {
00686                                 this->executeFunction(msg,this->in_type_handler_plugins[i]);
00687          }
00688                 }
00689         }
00690         // IN_COMMAND_HANDLER & IN_FREE_COMMAND_HANDLER
00691         if ( msg->nbParts() >= 4 ) {
00692                 for ( unsigned int i = 0 ; i < this->in_command_handler_plugins.size() ; i ++ ) {
00693                         if ( Tools::to_lower(msg->getPart(3)) == ":"+this->conff->getValue("kernel.command_prefix")+Tools::to_lower(this->in_command_handler_plugins[i].highlightedWord) ) {
00694                                 if(!this->executeFunction(msg,this->in_command_handler_plugins[i])) {
00695                return ;
00696             }
00697          }
00698                 }
00699                 for ( unsigned int i = 0 ; i < this->in_free_command_handler_plugins.size() ; i ++ ) {
00700                         if ( msg->getPart(3) == ":"+this->in_free_command_handler_plugins[i].highlightedWord ) {
00701                                 if(!this->executeFunction(msg,this->in_free_command_handler_plugins[i])) {
00702                return;
00703             }
00704          }
00705                 }  
00706         }
00707         // IN_ALL_MSGS
00708         for ( unsigned int i = 0 ; i < this->in_all_msgs_plugins.size() ; i ++ ) {
00709       this->executeFunction(msg,this->in_all_msgs_plugins[i]);
00710         }
00711 }
00712 
00719 bool BotKernel::executeFunction(Message*m,StructFunctionStorage pfs)
00720 {
00721    //cout << "Execution de : " << pfs.symbole << endl;
00722    sem_t my_sem;
00723    sem_init (&my_sem, 0, 0);
00724    CPPThread th;
00725    ThreadParams tp;
00726    tp.function = &pfs;
00727    tp.b = this;
00728    tp.msg = m;
00729    tp.sem = &my_sem;
00730    struct timespec my_timeout;
00731    struct timeval now;
00732    gettimeofday(&now,NULL);
00733    my_timeout.tv_sec = now.tv_sec + pfs.timeout;
00734    my_timeout.tv_nsec = now.tv_usec * 1000;
00735    th.exec(threadFunc,&tp);
00736    int back = sem_timedwait(&my_sem,&my_timeout);
00737    if ((back == -1)&&(errno == ETIMEDOUT)) {
00738       this->myLog->log(pfs.symbole +" timed out",WARNING);
00739       th.terminate();
00740       if ((m!=NULL) && (pfs.type!=OUT_ALL_MSGS)) {
00741          this->send(IRCProtocol::sendNotice(m->getNickSender(),pfs.symbole +" timed out")) ;
00742       }
00743       return true;
00744    }
00745    else {
00746       th.join();
00747       return pfs.back;
00748    }
00749    return true;
00750 }
00751 
00756 void BotKernel::send(string str)
00757 {
00758    unsigned int diff=0;
00759    time_t now;
00760    Message msg;
00761    const unsigned int MAXCHARS = 450;
00762    string command;
00763    vector<string> messages;
00764    bool sended;
00765    messages.clear();
00766    if ( (str.length() > MAXCHARS) && (str.find("PRIVMSG ")!=string::npos) ){
00767       command = str.substr(0,str.find(":")+1);
00768       for ( unsigned int i = command.length(); i < str.length() ; i += MAXCHARS-command.length() ) {
00769          messages.push_back(command+str.substr(i,MAXCHARS-command.length()));
00770       }
00771    }
00772    else {
00773       messages.push_back(str);
00774    }
00775    for(unsigned int i = 0 ; i < messages.size();i ++ ) {
00776       // OUT_ALL_MSGS
00777       msg.setMessage(messages[i]);
00778         for ( unsigned int j = 0 ; j < this->out_all_msgs_plugins.size() ; j ++ ) {
00779          if (!this->executeFunction(&msg,this->out_all_msgs_plugins[j]) ) {
00780             return;
00781          }
00782         }
00783       sended = false;
00784       if ( this->conff->getValue("kernel.antief") == "1" ) {
00785          while (!sended)
00786          {
00787             time(&now);
00788             diff = now - this->AEX.last_decrease;
00789             if ( diff > 0 ) {
00790                this->AEX.penality -= diff;
00791                if (this->AEX.penality < 0 )
00792                   this->AEX.penality = 0 ;
00793                time(&this->AEX.last_decrease);
00794             }
00795             if (( this->AEX.penality + 2 ) < 10 ) {
00796                if ( !this->sock->sendStr(msg.getMessage()+"\n") ) {
00797                   this->myLog->log("Disconnected (write error)",WARNING);
00798                   this->setConnected(false);
00799                }
00800                sended = true;
00801                this->AEX.penality += 2 ;
00802             } 
00803          }
00804       }
00805       else {
00806          if ( !this->sock->sendStr(msg.getMessage()+"\n") ) {
00807             this->myLog->log("Disconnected (write error)",WARNING);
00808             this->setConnected(false);
00809          }   
00810       }
00811    }
00812 }
00813 
00818 void BotKernel::send(vector<string> vec)
00819 {
00820         for ( unsigned int i = 0 ; i < vec.size() ; i ++ ) {
00821                 this->send(vec[i]);
00822         }
00823 }
00824 
00828 void BotKernel::displayLicenceHeader() {
00829    cout << "You are running trustyRC "<<this->version<<" by "+this->author+". A C++ IRC robot" << endl;
00830    cout << "trustyRC Copyright (C) 2006-2009  Nicoleau Fabien" << endl;
00831    cout << "This program comes with ABSOLUTELY NO WARRANTY." << endl;
00832    cout << "This is free software, and you are welcome to redistribute it under certain conditions." << endl;
00833    cout << "Read COPYING file for details." << endl << endl;
00834 }
00835 
00839 void BotKernel::initDirs() {
00840    char * pHOME = NULL;
00841    DIR*directory = NULL;
00842    pHOME = getenv("HOME");
00843    string confName = this->conff->getFilePath().substr(this->conff->getFilePath().rfind("/")+1,this->conff->getFilePath().rfind(".")-this->conff->getFilePath().rfind("/")-1);
00844    if ( pHOME != NULL ) {
00845       this->datasDir = (string)pHOME+"/.trustyrc/";
00846    }
00847    else {
00848       this->datasDir = "/tmp/trustyrc/";
00849       cerr<< "Wrong datasdir value. Using "+this->datasDir << endl;
00850    }
00851    directory = opendir(this->datasDir.c_str()) ;
00852    if (directory==NULL) {
00853       if (mkdir(this->datasDir.c_str(),0755) == -1 ) {
00854          cerr << "Unable to create datas dir (check write access?). Can't continue ..." << endl;
00855          exit(-1);
00856       }
00857    }
00858    closedir(directory);
00859    directory = opendir((this->datasDir+"plugins").c_str());
00860    if (directory==NULL) {
00861       if (mkdir((this->datasDir+"plugins").c_str(),0755) == -1 ) {
00862          cerr << "Unable to create alias dir (check write access.). Can't continue ..." << endl;
00863          exit(-1);
00864       }
00865    }
00866    closedir(directory);
00867    directory = opendir((this->datasDir+confName).c_str());
00868    if (directory==NULL) {
00869       if (mkdir((this->datasDir+confName).c_str(),0755) == -1 ) {
00870          cerr << "Unable to create alias dir (check write access.). Can't continue ..." << endl;
00871          exit(-1);
00872       }
00873    }
00874    closedir(directory);
00875    this->datasDir += (confName+"/") ;
00876    directory = opendir((this->datasDir+"syslog").c_str());
00877    if (directory==NULL) {
00878       if (mkdir((this->datasDir+"syslog").c_str(),0755) == -1 ) {
00879          cerr << "Unable to create syslog dir (check write access). Nothing will be logged ..." << endl;
00880       }
00881    }
00882    closedir(directory);
00883 }
00884 
00889 ConfigurationFile* BotKernel::getCONFF()
00890 {
00891         return this->conff;
00892 }
00893 
00898 string BotKernel::getAuthor()
00899 {
00900         return this->author;
00901 }
00902 
00907 string BotKernel::getVersion()
00908 {
00909         return this->version;
00910 }
00911 
00916 string BotKernel::getDescription()
00917 {
00918         return this->description;
00919 }
00920 
00925 LogFile* BotKernel::getSysLog()
00926 {
00927         return this->myLog;
00928 }
00929 
00934 string BotKernel::getNick()
00935 {
00936         return this->nick;
00937 }
00938 
00943 void BotKernel::setNick(string nick)
00944 {
00945    //this->conff->setValue("kernel.nick",nick);
00946         this->nick = nick;
00947 }
00948 
00953 bool BotKernel::getConnected()
00954 {
00955    return this->connected;
00956 }
00957 
00963 void BotKernel::setConnected(bool state)
00964 {
00965         this->connected = state;
00966 }
00967 
00975 pPlugin* BotKernel::getPlugin(string name)
00976 {
00977         if ( !this->pluginLoaded(name) )
00978         {
00979                 return NULL;
00980         }
00981         else
00982         {
00983                 for ( unsigned int i = 0 ; i < this->myPlugins.size() ; i ++ )
00984                 {
00985                         if ( this->myPlugins[i].name == name)
00986                         {
00987                                 return &this->myPlugins[i] ;
00988                         }
00989                 }
00990                 return NULL;
00991         }
00992         return NULL;
00993 }
00994 
00999 vector<string> BotKernel::getPluginsList()
01000 {
01001    vector<string> back;
01002         for ( unsigned int i = 0 ; i < this->myPlugins.size() ; i ++ )
01003         {
01004       back.push_back(this->myPlugins[i].name);
01005         }
01006    return back; 
01007 }
01008 
01013 time_t BotKernel::getStartTime()
01014 {
01015    return this->startTime;
01016 }
01017 
01022 time_t BotKernel::getStartOnline()
01023 {
01024    return this->startOnline;
01025 }
01026 
01031 vector<CountDownFunction>* BotKernel::getCountDowns()
01032 {
01033    return &this->countDowns ;
01034 }
01035 
01040 string BotKernel::getDatasDir() 
01041 {
01042    return this->datasDir;
01043 }
01044 
01045 void* threadFunc (void*args) 
01046 {
01047    ThreadParams* tp = (ThreadParams*) args;
01048    StructFunctionStorage* pfs = tp->function;
01049    pfs->back = pfs->function(tp->msg,pfs->object,tp->b);
01050    sem_post (tp->sem);
01051    return NULL;
01052 }
01053 

Generated on Sun Aug 16 15:28:26 2009 for trustyRC by  doxygen 1.5.8