Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmstcpserver.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2013 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
00031  **************************************************************************/
00032 
00033 #include "mmstools/mmstcpserver.h"
00034 #include "mmstools/tools.h"
00035 #include <netdb.h>
00036 #include <arpa/inet.h>
00037 #include <sys/select.h>
00038 #include <fcntl.h>
00039 #include <string.h>
00040 #include <cerrno>
00041 
00042 MMSTCPServer::MMSTCPServer(vector<MMSServerInterface *> interfaces,
00043                            string host, unsigned int port, string identity) : MMSThread(identity) {
00044 
00045     // create threads and link a interface to each
00046     this->st_size = interfaces.size();
00047     for (size_t i = 0; i < this->st_size; i++)
00048         this->sthreads.push_back(new MMSTCPServerThread(interfaces.at(i)));
00049     this->st_cnt = 0;
00050 
00051     // connection data
00052     this->host = host;
00053     this->port = port;
00054     this->s = -1;
00055 }
00056 
00057 MMSTCPServer::MMSTCPServer(MMSServerInterface *interface,
00058                            string host, unsigned int port, string identity) : MMSThread(identity) {
00059 
00060     // create threads and link a interface to each
00061     this->st_size = 1;
00062     this->sthreads.push_back(new MMSTCPServerThread(interface));
00063     this->st_cnt = 0;
00064 
00065     // connection data
00066     this->host = host;
00067     this->port = port;
00068     this->s = -1;
00069 }
00070 
00071 void MMSTCPServer::threadMain() {
00072     struct hostent      *he;
00073     struct in_addr      ia;
00074     struct sockaddr_in  sa;
00075     struct sockaddr_in  sac;
00076     fd_set              readfds;
00077     fd_set              writefds;
00078     fd_set              errorfds;
00079     struct timeval      timeout;
00080     int                 new_s;
00081     socklen_t           saclen = sizeof(struct sockaddr_in);
00082 
00083     // get host ip in network byte order
00084     he = gethostbyname(this->host.c_str());
00085 
00086     // get host ip in numbers-and-dots
00087     ia.s_addr = *((unsigned long int*)*(he->h_addr_list));
00088     this->hostip = inet_ntoa(ia);
00089     WRITE_MSGI("ip: %s", this->hostip.c_str());
00090 
00091     // get a socket
00092     if ((this->s = socket(AF_INET, SOCK_STREAM, 0))<=0) return;
00093 
00094     // bind to hostip
00095     memset(&sa, 0, sizeof(sa));
00096     sa.sin_family = AF_INET;
00097     sa.sin_port = htons(this->port);
00098     sa.sin_addr.s_addr = inet_addr(this->hostip.c_str());
00099     WRITE_MSGI("bind at %d(%d)",this->port, sa.sin_port);
00100 
00101     // set socket options
00102     int optbuf = 1;
00103     if(setsockopt(this->s, SOL_SOCKET, SO_REUSEADDR, &optbuf, sizeof(optbuf)) < 0) {
00104         WRITE_ERRI("socket error: cannot set socket option");
00105     }
00106 
00107     fcntl(this->s, F_SETFD, FD_CLOEXEC);
00108 
00109     if(bind(this->s, (struct sockaddr *)&sa, sizeof(struct sockaddr_in))!=0) {
00110         WRITE_ERRI("Error while binding at %s:%d: %s", this->hostip.c_str(), this->port, strerror(errno));
00111         return;
00112     }
00113 
00114     if (listen(this->s,SOMAXCONN)!=0) {
00115         WRITE_ERRI("Error while listening at %s:%d: %s", this->hostip.c_str(), this->port, strerror(errno));
00116         return;
00117     }
00118 
00119     // listen/select/accept loop
00120     while (1) {
00121         // set filedescriptor
00122         FD_ZERO(&readfds);
00123         FD_ZERO(&writefds);
00124         FD_ZERO(&errorfds);
00125         FD_SET(this->s, &readfds);
00126         FD_SET(this->s, &writefds);
00127         FD_SET(this->s, &errorfds);
00128 
00129         // set timeout
00130         timeout.tv_sec = 1;
00131         timeout.tv_usec = 0;
00132 
00133         // check socket
00134         if (select(this->s+1, &readfds, &writefds, &errorfds, &timeout)<0) {
00135             WRITE_ERRI("select failed");
00136             return;
00137         }
00138         if (FD_ISSET(this->s, &readfds)) {
00139             // going to accept the new connection
00140             if ((new_s = accept(this->s, (struct sockaddr *)&sac, &saclen))<0) {
00141                 WRITE_ERRI("accept failed");
00142                 continue;
00143             }
00144 
00145             WRITE_MSGI("check st_size");
00146             // call next server thread
00147             if (this->st_size<=0) {
00148                 shutdown(new_s, 2);
00149                 close(new_s);
00150                 continue;
00151             }
00152             WRITE_MSGI("set and start thread");
00153             if (this->st_cnt >= this->st_size) this->st_cnt=0;
00154             while(this->sthreads.at(this->st_cnt)->isRunning()) {
00155                 //fprintf(stderr, "still running \n");
00156                 usleep(50);
00157             }
00158             this->sthreads.at(this->st_cnt)->setSocket(new_s);
00159             this->sthreads.at(this->st_cnt)->start();
00160             this->st_cnt++;
00161         }
00162         else
00163         if (FD_ISSET(this->s, &writefds)) {
00164             //DEBUGOUT ("WRITEFDS\n");
00165             return;
00166         }
00167         else
00168         if (FD_ISSET(this->s, &errorfds)) {
00169             //DEBUGOUT ("ERRORFDS\n");
00170             return;
00171         }
00172         else {
00173             //DEBUGMSG("MMSTCPServer", "select timeout");
00174         }
00175     }
00176 }

Generated by doxygen