/////////////////////////////////////////////////////////////// // Test.cpp - test Prototype HttpServer // // // // Jim Fawcett, CSE775 - Distributed Objects, Spring 2012 // /////////////////////////////////////////////////////////////// /* * Note: * ----- * This demo shows how to receive HTTP messages and send back * a reply. I'm not sending back a file, just extracting the * resource name and sending that back as a demo. * * This code is in a very early state. It only works with * Chrome and has very little functionality. */ #include "../Sockets/Sockets.h" #include "../Threads/Threads.h" #include "../BlockingQueue/BlockingQueue.h" #include "../Utilities/Utilities.h" #include #include #include #include #include #ifdef HTTPTRACING #include "..\threads\locks.h" #define TRACE(msg) sout << "\n " << msg; #else #define TRACE(msg) ; #endif std::ostream out(std::cout.rdbuf()); /////////////////////////////////////////////////////////////// // HttpMessage class class HttpMessage { public: enum CommandType { Get, Post, Put, Delete }; std::string& message() { return _message; } std::string& resource() { return _resource; } std::string& command() { return _command; } private: std::string _message; std::string _command; std::string _resource; std::map _headers; }; /////////////////////////////////////////////////////////////// // Request Handler thread processing class HttpProcessor : public Thread_Processing { public: HttpProcessor(Socket& httpSocket) : _httpSocket(httpSocket) {} //----< parse request command >------------------------------ bool readAndParseCommand() { std::string line = _httpSocket.ReadLine(); TRACE(std::string("command: ") + line); if(line.size() == 0) return false; int pos1 = line.find(" "); _command = line.substr(0,pos1); int pos2 = line.find(" ",++(++pos1)); _resource = line.substr(pos1,pos2-pos1); _message.append(line).append("\n"); return true; } //----< parse command headers >------------------------------ bool readAndParseHeaders() { while(_httpSocket.bytesLeft() > 2) { std::string line = _httpSocket.ReadLine(); if(line.size() == 0) { TRACE("empty line in parseHeaders"); return false; } else { _message.append(line).append("\n"); TRACE(std::string("header: ") + line); int pos1 = line.find(":"); std::string key = line.substr(0,pos1); std::string value = line.substr(++(++pos1),line.size()-pos1); TRACE(std::string("key = ") + key + std::string(", value = ") +value); _headers[key] = value; } } return true; } //----< parse body of message >------------------------------ bool readAndParseBody() { return true; } //----< process incoming HTTP request >---------------------- void run() { // Read Browser Request readAndParseCommand(); readAndParseHeaders(); readAndParseBody(); if(_message.size() > 0) { out << "\n received message:"; out << "\n-------------------------\n"; out << _message.c_str(); out << "-------------------------\n"; out << "\n Resource: " << _resource; out << "\n size: " << _resource.size() << std::endl; // Send Reply consisting of the name of the requested resource _resource = std::string("

") + _resource + "

"; std::string reply = "HTTP/1.0 200 OK\n"; reply.append("Content-Type : text/html\n"); reply.append(std::string("Content-Length : ") + ToString(_resource.size()) + "\n\n"); reply.append(_resource); reply.append("\n"); out << "\n sending message:"; out << "\n-------------------------\n"; out << reply; out << "\n-------------------------\n"; _httpSocket.WriteLine(reply); } else out << "\n Received empty message"; closesocket(_httpSocket); out << "\n HttpProcessor thread terminating\n"; } private: Socket _httpSocket; std::string _command; std::string _resource; std::string _message; std::map _headers; }; /////////////////////////////////////////////////////////////// // Listener Thread processing class ListenProc : public Thread_Processing { public: ListenProc(int port) : _port(port), _pListener(new SocketListener(port)) {} ~ListenProc() { delete _pListener; } void run() { while(true) { Socket httpSocket = _pListener->waitForConnect(); out << "\n got a connection"; IThread_Processing& proc = HttpProcessor(httpSocket); tthread* pTthread = new tthread(proc); out << "\n starting HttpProcessing thread"; pTthread->start(); } } private: SocketListener* _pListener; int _port; }; //----< Server Entry Point >----------------------------------- int main() { std::cout << "\n Starting Http Processing Test"; std::cout << "\n ==============================="; ListenProc lp(8080); thread listenerThread(lp); out <<"\n starting http listener\n"; listenerThread.start(); std::cerr << "\n press any key to quit: "; std::cin.get(); }