00001
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
00024
00025
00026
00027
00028
00029 lat::logflag LFsocket = { 0, "socket", true, -1 };
00030
00031
00032
00033
00034
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
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
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
00211
00212
00213
00214
00215
00216
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
00242
00243
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 }