/home/croftj/photogrotto/photogrotto.cpp

00001 /*********************************************************************************
00002 **
00003 **   $Id: //depot/WorkInProgress/photogrotto/photogrotto.cpp#6 $
00004 **   Copyright (c) 2007 Joe Croft joe@croftj.net
00005 **   
00006 **   This file is part of Photogrotto
00007 **
00008 **   Photogrotto is free software; you can redistribute it and/or modify
00009 **   it under the terms of the GNU General Public License as published by
00010 **   the Free Software Foundation; either version 2 of the License, or
00011 **   (at your option) any later version.
00012 **
00013 **   Foobar is distributed in the hope that it will be useful,
00014 **   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 **   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 **   GNU General Public License for more details.
00017 **
00018 **   You should have received a copy of the GNU General Public License
00019 **   along with Foobar; if not, write to the Free Software
00020 **   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 **
00022 *********************************************************************************/
00023 
00024 # include <errno.h>
00025 # include <stdio.h>
00026 # include <string.h>
00027 # include <QFile>
00028 # include "photogrotto.h"
00029 
00030 FILE *logfp;
00031 
00032 /*!
00033        \class PhotoGrotto
00034        
00035        \brief  Controlling  class  for  creating  a  http  server  for
00036        processing incomming connections and requests.
00037        
00038        This  class  functions as an  http server which accepts connections
00039        from   external  clients.  The  definition  of  the  server  is
00040        specified  in an XML file.
00041 */ 
00042 
00043 /*!
00044        \fn PhotoGrotto::PhotoGrotto(QString confName, QObject *parent)
00045        
00046        This functioncreates a PhotoGrotto object. The  definition  of 
00047        the  server  is specified in an XML file. the file named by the
00048        parameter  \a  confName.  The Parameter \a parent points to the
00049        parent object of this one is any.
00050 */ 
00051 PhotoGrotto::PhotoGrotto(QString confName, QObject *parent) :
00052       QTcpServer(parent)
00053 {
00054    int line, col;
00055 
00056    logfp = stderr;
00057 
00058    /*
00059           Open the XML file for the application.
00060    */ 
00061    QFile file( confName );
00062    if ( !file.open( IO_ReadOnly ) )
00063    {
00064       error_str = "Could not open file: " + confName;
00065       return;
00066    }
00067 
00068    /*
00069           Try  parsing the file. If there are any erros, spit them out
00070           to stderr.
00071    */ 
00072    if ( !doc.setContent( &file, &err, &line, &col ) ) {
00073       file.close();
00074       error_str = "Error parsing xml doc: " + confName + "The error reported as: " + err + " found on line: " + QString::number(line) + ", column: " + QString::number(col);
00075       fprintf(stderr, "PhotoGrotto::PhotoGrotto(): Error in setContent file\n%s\n", qPrintable(error_str));
00076       return;
00077    }
00078 
00079    /*
00080           Set  up to listen on the address and port defined in the XML
00081           document. COmplain if you can't
00082    */ 
00083    getTcpParms();
00084    if ( ! listen(address, port) ) 
00085    {
00086       fprintf(logfp, "Error listening\n");
00087       return;
00088    }
00089 }
00090 
00091 /*!
00092       \fn void PhotoGrotto::incomingConnection(int sock)
00093 
00094        This   function  overloads  the  like  named  function  in  the
00095        QTcpServer class and is called whenever a new tcp connection is
00096        made.  It  creates  a new DbPhoto Object to handle the requests
00097        for the object and starts the thread for that object to run on.
00098        It   also  connects  the  appropriate  signals  and  slots  for
00099        controlling the thread.
00100 */ 
00101 void PhotoGrotto::incomingConnection(int sock)
00102 {
00103    fprintf(logfp, "PhotoGrotto::incomingConnection(): Enter, sock = %d\n", sock);
00104    fflush(logfp);
00105 
00106    /*
00107           Create   a   new   service  object  to  handle  this  socket
00108           connection.  Connect  the  appropriate  signals and slots to
00109           control it.
00110    */ 
00111    DbPhotoService *p = new DbPhotoService(sock, &doc, 120);
00112    connect(p, SIGNAL(send(QTcpSocket*, QByteArray)), this, SLOT(sendData(QTcpSocket*, QByteArray)));
00113    connect(p, SIGNAL(closeSocket(QTcpSocket*)), this, SLOT(haveCloseSocket(QTcpSocket*)));
00114 
00115    p->setMaxCache(2000);
00116 
00117    /*
00118           Start the thread to handle the requests.
00119    */ 
00120    p->start();
00121    fprintf(logfp, "PhotoGrotto::incomingConnection(): exit\n");
00122    fflush(logfp);
00123 }
00124 
00125 /*!
00126       \fn void PhotoGrotto::getTcpParms()
00127 
00128        This  function  retrieves the name of the log file and opens it
00129        for  logging.  It  also  retrieves the address and port for the
00130        server  to  listen  on  and  populates  the  class variables \a
00131        address and \a port with the defined information.
00132 */ 
00133 void PhotoGrotto::getTcpParms()
00134 {
00135    port = 80;
00136    address.setAddress(QHostAddress::Any);
00137 
00138    QDomElement docElem = doc.documentElement();
00139    QDomNode n = docElem.firstChild();
00140    while ( !n.isNull() ) 
00141    {
00142       QDomElement e = n.toElement();
00143 
00144       /*
00145              Have  a  logfile  tag,  get  the name and open the log if
00146              possible.
00147       */ 
00148       if ( e.tagName() == "logfile" ) 
00149       {
00150          if ( e.attribute("name").size() > 0 ) 
00151          {
00152             FILE *fp = fopen(qPrintable(e.attribute("name")), "a");
00153             if ( fp != 0 ) 
00154             {
00155                logfp = fp;
00156                stdout = fp;
00157                stderr = fp;
00158             }
00159             else
00160                fprintf(logfp, "Error opening logfile %s: %s\n", qPrintable(e.attribute("name")), strerror(errno));
00161          }
00162       }
00163 
00164       /*
00165              Have  the  listen tag. Get the address and port to listen
00166              on and save them for later.
00167       */ 
00168       else if ( e.tagName() == "listen" ) 
00169       {
00170          if ( e.attribute("addr").size() > 0 ) 
00171          {
00172             fprintf(logfp, "Listening on address: %s\n", qPrintable(e.attribute("addr")));
00173             address.setAddress(e.attribute("addr"));
00174          }
00175          else if ( e.attribute("address").size() > 0 ) 
00176          {
00177             fprintf(logfp, "Listening on address: %s\n", qPrintable(e.attribute("address")));
00178             address.setAddress(e.attribute("address"));
00179          }
00180 
00181          if ( e.attribute("port").size() > 0 ) 
00182             port = e.attribute("port").toInt();
00183          break;
00184       }
00185       n = n.nextSibling();
00186    }
00187    fprintf(logfp, "Listening on port: %d\n", port);
00188    fflush(logfp);
00189 }        
00190 
00191 /*!
00192        \fn  void  PhotoGrotto::sendData(QTcpSocket *sock, QByteArray  buf)
00193        
00194        This  function  writes the buffer \a buf of data to the socket \a sock.
00195        This  is  called  by  the  thread handling the requests for the
00196        socket.
00197 */ 
00198 void PhotoGrotto::sendData(QTcpSocket *sock, QByteArray buf)
00199 {
00200    fprintf(logfp, "PhotoGrotto::sendData(): Enter, sending %d bytes to sock %d\n", buf.count(), sock->socketDescriptor());
00201    fflush(logfp);
00202    sock->write(buf);
00203    fprintf(logfp, "PhotoGrotto::sendData(): Exit\n");
00204    fflush(logfp);
00205 }
00206 
00207 /*!
00208        \fn void PhotoGrotto::haveCloseSocket(QTcpSocket *sock)
00209        
00210        This function is called then the socket \a sock is closed. It cleans up the 
00211        socket object.
00212 */ 
00213 void PhotoGrotto::haveCloseSocket(QTcpSocket *sock)
00214 {
00215    fprintf(logfp, "PhotoGrotto::haveCloseSocket(): Enter, sock %d\n", sock->socketDescriptor());
00216    fflush(logfp);
00217    sock->disconnectFromHost();
00218    fprintf(logfp, "PhotoGrotto::haveClocseSocket(): Exit\n");
00219    fflush(logfp);
00220 }
00221 

Generated on Fri May 4 11:21:12 2007 for PhotoGrotto by  doxygen 1.5.0