remotecontrol.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 
00029 #include "remotecontrol.h"
00030 
00031 extern "C" void * myThread (void *);
00032 
00036 RemoteControl::RemoteControl(BotKernel*b)
00037 {
00038         this->author = "eponyme";
00039         this->description = "Plugin that allows remote control via a TCP communication";
00040         this->version = VERSION;
00041         this->name = "remotecontrol"; 
00042 
00043    this->MYPORT = Tools::strToUnsignedInt(b->getCONFF()->getValue(this->getName()+".port")) ; 
00044    this->MAXCLIENTS = Tools::strToUnsignedInt(b->getCONFF()->getValue(this->getName()+".maxclients")) ; 
00045    this->clients = new int[this->MAXCLIENTS];
00046         this->pt = new CPPThread();
00047         if (!pt->exec(myThread,(void*)b)) {
00048       b->getSysLog()->log("Unable to launch tcp thread",WARNING);
00049    } 
00050    // Just a trick to avoid load error. This function will be unregistered at first call
00051    this->bindFunction("PING",IN_FIRST_WORD,"myUselessFunction",0,5);
00052 }
00053 
00057 RemoteControl::~RemoteControl()
00058 {
00059    for ( unsigned int i = 0 ; i < this->MAXCLIENTS ; i ++ ) {
00060       if ( this->clients[i] != 0 ) {
00061          close(this->clients[i]);
00062       }
00063    }
00064    close(this->sockfd);
00065    delete [] this->clients;
00066    delete(this->pt);
00067 }
00068 
00077 void* RemoteControl::tcpServer(BotKernel*b) 
00078 {
00079    int  new_fd; // socket for new client
00080    int highest = 0 ;
00081    int reuse_addr = 1;
00082    char buffer[RemoteControl::MAXDATASIZE] ;
00083    int slot;
00084    int numbytes;
00085    struct sockaddr_in my_addr,their_addr;
00086    socklen_t sin_size;
00087    struct timeval tv;
00088    fd_set readfds;
00089 
00090    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
00091       b->getSysLog()->log("remotecontrol - socket : "+(string)strerror(errno),ERROR);
00092       return NULL;
00093    }
00094    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr)) == -1) {
00095       b->getSysLog()->log("remotecontrol - setsockopt : "+(string)strerror(errno),ERROR);
00096       return NULL;
00097    }
00098 
00099    my_addr.sin_family = AF_INET;         /* host byte order */
00100    my_addr.sin_port = htons(this->MYPORT);     /* short, network byte order */
00101    my_addr.sin_addr.s_addr = INADDR_ANY; /* auto-remplissage avec mon IP */
00102    bzero(&(my_addr.sin_zero), 8);        /* zero pour le reste de struct */
00103    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
00104       b->getSysLog()->log("remotecontrol - bind : "+(string)strerror(errno),ERROR);
00105       return NULL;
00106    }
00107    if (listen(sockfd, RemoteControl::BACKLOG) == -1) {
00108       b->getSysLog()->log("remotecontrol - listen : "+(string)strerror(errno),ERROR);
00109       return NULL;
00110    }
00111    bzero(clients,this->MAXCLIENTS*sizeof(int));
00112    highest = sockfd ;
00113    while(true) {
00114       sin_size = sizeof(struct sockaddr_in);      
00115       this->setSocketList(&tv,&readfds);
00116       if (select(highest+1, &readfds, NULL, NULL, &tv) >=0 ) {
00117          if (FD_ISSET(sockfd, &readfds)) {
00118             if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
00119                b->getSysLog()->log("accept : "+(string)strerror(errno),ERROR);
00120                continue;
00121             }  
00122             if ( (slot = this->manageNewConnection(new_fd)) >= 0 ) {
00123                if ( new_fd > highest ) {
00124                   highest = new_fd ;
00125                }
00126                b->getSysLog()->log("remotecontrol : connexion received from "+(string)inet_ntoa(their_addr.sin_addr)+" (slot "+Tools::intToStr(slot)+")",INFO);
00127                send(new_fd,"Welcome on trustyRC remote control. Enter your password :\n",58,MSG_NOSIGNAL); // Just for test. In the futur, the client will have to auth as a bot admin
00128             }     
00129             else {
00130                send(new_fd, "Sorry, no free slot! bye\n",25,MSG_NOSIGNAL); 
00131                close(new_fd);   
00132             }
00133          }
00134          for ( unsigned int i = 0 ; i < this->MAXCLIENTS ; i ++ ) {
00135             if ( FD_ISSET(clients[i],&readfds) ) {
00136                if ( (numbytes=recv(clients[i],buffer,RemoteControl::MAXDATASIZE,0)) <= 0 ) {
00137                   b->getSysLog()->log("remotecontrol : connexion lost from slot "+Tools::intToStr(i),INFO);  
00138                   close(clients[i]);
00139                   clients[i] = 0 ;
00140                }
00141                else {
00142                   buffer[numbytes] = '\0';
00143                   cout << "Received from slot " << i << " : " << buffer;  // to delete
00144                }
00145             }
00146          }
00147       } 
00148       else {
00149          b->getSysLog()->log("remotecontrol : select error",WARNING);
00150          return NULL;
00151       }
00152    }
00153    return NULL;
00154 }
00155 
00162 void RemoteControl::setSocketList(struct timeval*tv,fd_set*readfds) 
00163 {
00164    tv->tv_sec = 0;
00165    tv->tv_usec = 250000; // 0.25 seconds
00166    FD_ZERO(readfds);
00167    for ( unsigned int i = 0 ; i < this->MAXCLIENTS ; i ++ ) {
00168       if ( this->clients[i] != 0 ) {
00169          FD_SET(this->clients[i],readfds);
00170       } 
00171    }
00172    FD_SET(this->sockfd,readfds);
00173 }
00174 
00181 int RemoteControl::manageNewConnection(int sock)
00182 {
00183    for(unsigned int i = 0 ; i < this->MAXCLIENTS ; i ++ ) {
00184       if ( this->clients[i] == 0 ) {
00185          this->clients[i] = sock ;
00186          return i;
00187       }
00188    }
00189    return -1;
00190 }
00191 
00192 extern "C"
00193 {
00194         Plugin *contruct_remotecontrol(BotKernel*b)
00195         {
00196                 return new RemoteControl(b);
00197         }
00198         void destroy_remotecontrol(Plugin*p)
00199         {
00200                 delete p;
00201         }
00202    void * myThread(void * arg)
00203    {
00204       BotKernel* b = (BotKernel*)arg;
00205       // wait for plugin loaded
00206       while (b->getPlugin("remotecontrol")==NULL) {
00207          usleep(10);
00208       }
00209       RemoteControl* rc = (RemoteControl*)b->getPlugin("remotecontrol")->object ;
00210       rc->tcpServer(b);
00211            return NULL;
00212    }
00213         bool myUselessFunction (Message*m,Plugin*p,BotKernel*b)
00214         {
00215       b->unregisterFunction(myUselessFunction);
00216                 return true;
00217         }
00218 }

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