/////////////////////////////////////////////////////////////// // Test.cpp - test Prototype HttpServer // // // // Jim Fawcett, CSE775 - Distributed Objects, Spring 2012 // /////////////////////////////////////////////////////////////// /* * Note: * ----- * I haven't been able to fully integrate my sockets class * into this demonstration. Multiple Socket objects seem * to have a race condition when passed to functions. I haven't * sorted that out yet but I am using a lot of the class's * functionality by passing a win32 SOCK and then wrapping * in a Socket. * * 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. */ #include "../Sockets/Sockets.h" #include "../Threads/Threads.h" #include "../BlockingQueue/BlockingQueue.h" #include #include #include #include /////////////////////////////////////////////////////////////// // Request Handler thread processing std::ostream out(std::cout.rdbuf()); class HttpProcessor : public Thread_Processing { public: HttpProcessor(SOCKET httpSocket) : _httpSocket(httpSocket) {} std::string parseRequestName(std::string& temp) { std::string resourceName, nameSize; size_t pos = temp.find("GET /", 0); if(pos < temp.size()) { resourceName = temp.substr(pos+5); pos = resourceName.find_first_of(" ", 0); resourceName = resourceName.substr(0,pos); resourceName = std::string(" ") + resourceName + ""; } return resourceName; } //----< convert an interger size to a string >--------------- std::string sizeToString(size_t size) { std::ostringstream out; out << size; return out.str(); } //----< are there any bytes left in recv buffer? >----------- size_t bytesLeft(SOCKET s_) { unsigned long bytes; ::ioctlsocket(s_,FIONREAD,&bytes); return (size_t)bytes; } //----< process incoming HTTP request >---------------------- void run() { std::string nameSize; std::string resourceName = " "; std::string buffer; // Read Browser Request Socket httpSock = Socket(_httpSocket); for(int i=0; ;++i) { if(httpSock.bytesLeft() < 1) break; std::string temp = httpSock.ReadLine().append("\n"); if(i == 0) { resourceName = parseRequestName(temp); nameSize = sizeToString(resourceName.size()); } buffer.append(temp); } if(buffer.size() > 0) { out << "\n received message:"; out << "\n-------------------------\n"; out << buffer.c_str(); out << "-------------------------\n"; out << "\n ResourceName: " << resourceName; out << "\n size: " << resourceName.size() << std::endl; // Send Reply consisting of the name of the requested resource std::string reply = "HTTP/1.0 200 OK\n"; reply.append("Content-Type : text/html\n"); reply.append(std::string("Content-Length : ") + nameSize + "\n\n"); reply.append(resourceName); out << "\n sending message:"; out << "\n-------------------------\n"; out << reply; out << "\n-------------------------\n"; httpSock.WriteLine(reply); } else out << "\n Received empty message"; closesocket(_httpSocket); out << "\n HttpProcessor thread terminating\n"; } private: SOCKET _httpSocket; }; /////////////////////////////////////////////////////////////// // 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(); }