CMS 3D CMS Logo

IgSocket.cc

Go to the documentation of this file.
00001 //<<<<<< INCLUDES                                                       >>>>>>
00002 
00003 #include <classlib/utils/Log.h>
00004 # undef emit
00005 
00006 #include "Iguana/WebFramework/interface/IgSocket.h"
00007 #include "Iguana/WebFramework/interface/IgServerSocket.h"
00008 #include "Iguana/WebFramework/interface/IgWebServiceRegistry.h"
00009 #include "Iguana/WebFramework/interface/IgServerPool.h"
00010 #include "Iguana/Framework/interface/IgState.h"
00011 #include <classlib/utils/StringOps.h>
00012 #include <qstring.h>
00013 #include <qstringlist.h>
00014 #include <qbuffer.h>
00015 #include <qregexp.h>
00016 #include <qtextstream.h>
00017 #include <iostream>
00018 #include <stdlib.h>
00019 #include <string>
00020 #include <map>
00021 #include <sys/socket.h>
00022 
00023 //<<<<<< PRIVATE DEFINES                                                >>>>>>
00024 //<<<<<< PRIVATE CONSTANTS                                              >>>>>>
00025 //<<<<<< PRIVATE TYPES                                                  >>>>>>
00026 //<<<<<< PRIVATE VARIABLE DEFINITIONS                                   >>>>>>
00027 //<<<<<< PUBLIC VARIABLE DEFINITIONS                                    >>>>>>
00028 
00029 lat::logflag LFsocket = { 0, "socket", true, -1 };
00030 
00031 //<<<<<< CLASS STRUCTURE INITIALIZATION                                 >>>>>>
00032 //<<<<<< PRIVATE FUNCTION DEFINITIONS                                   >>>>>>
00033 //<<<<<< PUBLIC FUNCTION DEFINITIONS                                    >>>>>>
00034 //<<<<<< MEMBER FUNCTION DEFINITIONS                                    >>>>>>
00035 
00036 IgSocket::IgSocket (IgState *state)
00037     : m_state (state),
00038       m_userAgent("")
00039 { }
00040 
00041 void
00042 IgSocket::dump (void) 
00043 {
00044     LOG (0, trace, LFsocket, "Connection on port: " 
00045          << this->port () << lat::indent << std::endl);
00046 
00047     if (! this->canReadLine ())
00048     {
00049         LOG (0, trace, LFsocket, "No HTTP command found " 
00050              << lat::undent << std::endl);
00051         
00052         return; 
00053     }
00054     
00055     QString commandLine = this->readLine ();
00056     LOG (0, trace, LFsocket, std::string ("HTTP command line: ") 
00057          << commandLine.ascii () << std::endl);
00058     
00059     QStringList tokens = QStringList::split (QRegExp ("[ \n\r][ \n\r]*"), 
00060                                              commandLine);
00061     std::string command = tokens[0].ascii ();
00062     
00063     typedef std::map <std::string, std::string> CookieMap;
00064 
00065     CookieMap cookieMap;
00066         
00067     if (! this->canReadLine ())
00068     {
00069         LOG (0, trace, LFsocket, std::string ("HTTP request has no additional info") 
00070              << commandLine.ascii () << std::endl);
00071     }
00072     
00073 
00074     QString httpsOptLine = this->readLine ();
00075     int postSize = 0;
00076     
00077     while (httpsOptLine.contains (":"))
00078     {   
00079         LOG (0, trace, LFsocket, std::string ("HTTP Option Line:") 
00080              << httpsOptLine.ascii () << std::endl);
00081             
00082         QStringList httpsOptTokens = QStringList::split (QRegExp ("[ \n\r][ \n\r]*"), 
00083                                                         httpsOptLine);
00084 
00085         if (httpsOptTokens[0] == "Cookie:")
00086         {
00087             for (unsigned int i = 1;
00088                  i < httpsOptTokens.size ();
00089                  i++)
00090             {
00091                 QStringList keyValue = QStringList::split ("=", httpsOptTokens[i]);
00092                 if (keyValue.size () == 2)
00093                 {
00094                     cookieMap.insert (CookieMap::value_type (keyValue [0], 
00095                                                              keyValue [1].remove (";")));            
00096                 }           
00097             }
00098         }
00099         else if (httpsOptTokens[0] == "Content-Length:")
00100         {
00101             postSize = atoi (httpsOptTokens[1]);     
00102             LOG (0, trace, LFsocket, std::string ("Post size: ") 
00103                  << httpsOptTokens[1].ascii () << std::endl);
00104         }
00105         else if(httpsOptTokens[0] == "User-Agent:")
00106         {
00107             m_userAgent = httpsOptLine.mid(11).stripWhiteSpace ().latin1();
00108         }
00109         else
00110         {       
00111             LOG (0, trace, LFsocket, std::string ("Unrecognized option:") 
00112                  << httpsOptTokens[0].ascii () << std::endl);
00113 
00114         }           
00115         httpsOptLine = this->readLine ();
00116     }
00117     
00118     QByteArray bodyData;
00119     
00120     // Get the remainings.
00121     if (postSize > 0)
00122     {
00123         std::string continueMsg = "HTTP/1.1 100 Continue\r\n\r\nConnection: close\r\n\r\n";
00124         
00125         this->writeBlock (continueMsg.c_str (), continueMsg.size ());
00126         this->flush ();
00127 
00128         LOG (0, trace, LFsocket, "Sending request to continue" << std::endl);
00129         
00130         char * buffer = new char[postSize];
00131         int sizeRead = this->readBlock (buffer, postSize);
00132         
00133         if (sizeRead != postSize)
00134         {
00135             LOG (0, trace, LFsocket, std::string ("WARNING: expecting ")
00136                  << QString::number (postSize).ascii () << " bytes, but only "
00137                  << QString::number (sizeRead).ascii () << " read" << std::endl);
00138         }
00139         
00140         bodyData.assign (buffer, postSize);
00141         LOG (0, trace, LFsocket, std::string ("Body:")
00142              << QString (bodyData).ascii () << std::endl);
00143     }                          
00144 
00145     
00146     // Cookie logging
00147     LOG (0, trace, LFsocket, "Client sent the following cookies: " 
00148          << lat::indent << std::endl);
00149     for (CookieMap::iterator i = cookieMap.begin ();
00150          i != cookieMap.end ();
00151          i++)
00152     {
00153         LOG (0, trace, LFsocket, i->first 
00154              << "=" 
00155              << i->second << std::endl);        
00156     }
00157     LOG (0, trace, LFsocket, lat::undent);
00158         
00159     std::string idCookie = cookieMap["USER"];
00160 
00161     LOG (0, trace, LFsocket, "IDCookie: " << idCookie << std::endl);
00162     std::string url = tokens[1].ascii ();
00163     
00164     IgServerSocket *server = IgServerSocket::get (m_state);
00165     std::string proxy = server->cmdLineProxy();
00166     std::string url1(url);
00167     int index = url1.size()-1;
00168     while((index>0) && (url1.rfind("/") == index))
00169     {url1=url1.substr(0, index); index--;}
00170     if ((cookieMap.find("cookies")==cookieMap.end()) || 
00171         (url1 == proxy + "/iguanainit") ||
00172         (url1 == proxy + "/iguana") ||
00173         (url1 == proxy + "/"))
00174     {
00175         server->clientInitialization (this);
00176         return;
00177     }
00178     
00179     if (url1 == proxy + "/ping")
00180     {
00181         server->ping (this);
00182         return;
00183     }
00184     else if (url1 == "/favicon.ico")
00185     {
00186         this->close ();
00187         return;
00188     }
00189     
00190     IgServerPool *serverPool = IgServerPool::get (m_state);
00191     if (serverPool)
00192     {
00193         sendData (serverPool->redirect (url, idCookie));
00194         serverPool->addServer ();
00195     }
00196     else
00197     {
00198         IgWebServiceRegistry *registry 
00199             = IgWebServiceRegistry::get (m_state);
00200         if (! registry)
00201         {
00202             LOG (0, trace, LFsocket, "FATAL: webservice registry not found "
00203                   << std::endl);
00204         }
00205 
00206         std::string clientCookieID = server->getClientCookieID();
00207         bool executeURL = false;
00208         if (clientCookieID.empty ())
00209         {
00210             //We will be here only when this server is not already serving
00211             //any other client. This mean either main server has redirected
00212             //a client to this or a client has directly contacted.
00213             
00214             //If cookie is "unknown user" then this mean that client has tried
00215             //to connect directly. In this case redirect him/her to main server
00216             //else reserve this server for this client
00217             url = server->cmdLineProxy() + "/Studio/login";
00218             if (idCookie.empty ())
00219             {
00220                 server->generateCookie (idCookie);
00221                 if (!server->cmdLineMainHostUrl ().empty ())
00222                 {
00223                     sendData (server->redirect (url, server->cmdLineMainHostUrl (),
00224                                                 idCookie));
00225                 }
00226                 else
00227                 {
00228                     server->setClientCookieID(idCookie);
00229                     sendData (server->redirect (url, server->hostnameUrl (),
00230                                                 idCookie));
00231                 }
00232             }
00233             else
00234             {
00235                 server->setClientCookieID(idCookie);
00236                 executeURL = true;
00237             }
00238         }
00239         else if (clientCookieID != idCookie)
00240         {
00241             //This server is already serving a different clicnt
00242             //so redirect it to main server if exists otherwise 
00243             //tell the client that server is already busy
00244             if (!server->cmdLineMainHostUrl ().empty ())
00245             {
00246                 sendData (server->redirect (proxy + "/Studio/login",
00247                                             server->cmdLineMainHostUrl (),
00248                                             server->generateCookie (idCookie)));
00249             }
00250             else
00251                 serverBusyMessage ();
00252         }
00253         else
00254             executeURL = true;
00255         if (executeURL)
00256         {
00257             registry->executeURL (*this, 
00258                                   url, 
00259                                   idCookie, 
00260                                   bodyData);
00261             this->close ();
00262             server->startTimer ();
00263         }
00264     }
00265 
00266     LOG (0, trace, LFsocket, lat::undent);
00267 }
00268 
00269 const std::string&
00270 IgSocket::userAgent (void) const
00271 { return m_userAgent; }
00272 
00273 void
00274 IgSocket::sendData (const std::string& data)
00275 {
00276     QTextStream client (this);
00277     client << data;
00278     this->close ();
00279     this->flush ();
00280 }
00281 
00282 void
00283 IgSocket::serverBusyMessage ()
00284 {
00285     std::string result = "HTTP/1.1 200 Ok\r\n"
00286                  "Content-Type: text/html; charset=\"utf-8\"\r\n\r\n"
00287                  "<html><body>"      
00288                  "<style  type=\"text/css\">"
00289                  "a {color:#FFFFFF}"
00290                  "</style>"
00291                  "<h3>Server is busy.</h3>"
00292                  "Server is already serving to other client please try server."
00293                  "</body>"
00294                  "</html>\r\n\r\n";
00295     sendData(result);            
00296 }

Generated on Tue Jun 9 17:39:04 2009 for CMSSW by  doxygen 1.5.4