Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

WebServer.cpp

Go to the documentation of this file.
00001 #include "headers.h"
00002 #include <algorithm>
00007 
00008 
00012 WebServer::WebServer() {
00013     // start the server thread
00014     pthread_attr_t attr;
00015         pthread_attr_init(&attr);
00016         
00017     // Create thread
00018     pthread_create(&m_serverThreadId, &attr, WebServer::run, NULL);
00019 
00020     // Cleanup
00021         pthread_attr_destroy(&attr);
00022 }
00023 
00024 
00025 WebServer::~WebServer() {
00026     void* statusp;
00027     pthread_cancel(m_serverThreadId);
00028     pthread_join(m_serverThreadId, &statusp);
00029 }
00030 
00031 
00032 void*
00033 WebServer::run(void* nothing) {
00034     int serviceNumber;
00035      
00036     debug(DEBUG_WS, "WEB SERVER UP");
00037 
00038     while (true) {
00039         pthread_testcancel();
00040         //debug(DEBUG_WS, "SERVER: listening for connection");
00041         serviceNumber = GlobalObjects::instance()->getTransportLayer()->listenAccept();
00042         if (serviceNumber == TransportLayer::DEAD) {
00043             debug(DEBUG_WS, "Transport layer is dead");
00044             return NULL;
00045         }
00046         if (serviceNumber <= 0) {
00047             debug(DEBUG_WS, "SERVER: accepted on bad service number!");
00048             continue;
00049         }
00050         //debug(DEBUG_WS, "SERVER: Connection accepted");
00051         
00052         // spawn a thread to deal with it
00053         pthread_attr_t attr;
00054         pthread_attr_init(&attr);
00055         pthread_t workerThreadId;
00056         // Create thread
00057         pthread_create(&workerThreadId, &attr, WebServer::handleConnection, &serviceNumber);
00058         
00059         // Cleanup
00060         pthread_attr_destroy(&attr);
00061     }
00062 }
00063 
00064 
00065 void*
00066 WebServer::handleConnection(void* arg) {
00067     pthread_detach(pthread_self());
00068     int serviceNumber = *((int*)arg);
00069     const int bufSize = 32768;
00070     vector<char> buf(bufSize);
00071 
00072     debug(DEBUG_WS, "HANDLE CONNECTION THREAD");
00073 
00074     //
00075     // Read the request
00076     //
00077     int bytesRead;
00078     int totalBytesRead = 0;
00079     do {
00080         // get request
00081         bytesRead = GlobalObjects::instance()->getTransportLayer()->receive(serviceNumber, (unsigned char*)(&buf[totalBytesRead]), (buf.capacity() - totalBytesRead));
00082         if (bytesRead > 0) {
00083             totalBytesRead += bytesRead;
00084         }
00085 
00086         // check for errors while reading
00087         if (bytesRead <= 0) {
00088             debug(DEBUG_CMD, "SERVER: Error reading data");
00089             GlobalObjects::instance()->getTransportLayer()->disconnect(serviceNumber);
00090             return NULL;
00091         }
00092         
00093         // find out if we have read the entire first line of the HTTP request
00094     } while (find(buf.begin(), buf.end(), '\n') == buf.end());
00095 
00096     // copy request into a string
00097     string request(buf.begin(), buf.begin() + totalBytesRead);
00098 
00099     //debug(DEBUG_WS, "SERVER: read data \"%s\"", request.c_str());
00100     
00101 
00102     // get server IP and port number
00103     SocketAddress serverSocketAddress = getSocketAddressFromHttp(request);
00104 
00105     // Check if it is a LAN IP address or loopback address - this is a security violation
00106     if (serverSocketAddress.getIpAddress().isLanIp() ||
00107         serverSocketAddress.getIpAddress().isLoopback()) {
00108         GlobalObjects::instance()->getTransportLayer()->disconnect(serviceNumber);
00109         return NULL;
00110     }
00111 
00112     //
00113     // connect to the server
00114     //
00115     debug(DEBUG_WS, "Connecting to %s", serverSocketAddress.toCStr());
00116 
00117     TcpConnection connection(serverSocketAddress);
00118     int success = connection.connect();
00119         
00120     // send the request
00121     connection.write((unsigned char*)request.data(), request.size());
00122 
00123     // stream the reply
00124 
00125     // send anything we get back from the server - reuse buf
00126     int totalBytesWritten = 0;
00127     totalBytesRead = 0;
00128     while ((bytesRead = connection.read((unsigned char*)&buf[0], buf.capacity(), 0)) > 0 ) {
00129         totalBytesRead += bytesRead;
00130         int bytesWritten = GlobalObjects::instance()->getTransportLayer()->send(serviceNumber, (unsigned char*)&buf[0], bytesRead);
00131         if (bytesWritten < 0) {
00132             debug(DEBUG_WS, "SERVER: error during transmission");
00133             GlobalObjects::instance()->getTransportLayer()->disconnect(serviceNumber);
00134             return NULL;
00135         }
00136         totalBytesWritten += bytesWritten;
00137         //
00138         // WARNING : YOU WILL OVERFLOW THE STACK IF YOU DO SOMETHING LIKE THE FOLLOWING:
00139         // string tmp(&buf[0], bytesRead);
00140         // debug(DEBUG_WS, "%s", tmp.c_str());
00141         //
00142     }
00143     //debug(DEBUG_WS, "SERVER: read %d bytes, sent %d bytes of data back to originator", totalBytesRead ,totalBytesWritten);
00144     
00145     // disconnect from the web server
00146     connection.close();
00147 
00148     // disconnect from the remote peer
00149     if (!GlobalObjects::instance()->getTransportLayer()->disconnect(serviceNumber)) {
00150         debug(DEBUG_WS, "SERVER: Error while attempting to disconnect");
00151         return NULL;
00152     }
00153     debug(DEBUG_WS, "SERVER: disconnect");
00154     return NULL;
00155 }
00156 
00157 
00161 SocketAddress
00162 WebServer::getSocketAddressFromHttp(string request) {
00163     // find the beginning of the URL
00164     std::string::size_type urlStartIndex = request.find("http://");
00165     
00166     // get the server name
00167     std::string::size_type serverNameStartIndex = urlStartIndex + strlen("http://");
00168     std::string::size_type serverNameEndIndex = request.find_first_of("/:", serverNameStartIndex) - 1;
00169     string serverName = request.substr(serverNameStartIndex, serverNameEndIndex - serverNameStartIndex + 1);
00170 
00171     SocketAddress socketAddress;
00172 
00173     // get the server port
00174     string serverPortString = "80";
00175     if (request[serverNameEndIndex+1] == ':') {
00176         std::string::size_type portEndIndex = request.find('/', serverNameEndIndex + 1);
00177         serverPortString = request.substr(serverNameEndIndex+1, portEndIndex - serverNameEndIndex + 1);
00178     }
00179 
00180     socketAddress.setPort(serverPortString);
00181     socketAddress.setIpAddress(serverName);
00182     return socketAddress;
00183 } // fn parseServerAndPort
00184 

Generated at Thu Jul 11 13:31:53 2002 for Peekabooty by doxygen1.2.9 written by Dimitri van Heesch, © 1997-2001