int main() { ::SetConsoleTitle("ClientHandler"); Show::attach(&std::cout); Show::start(); Show::title("\n ClientHandler Server started"); BlockingQueue<HttpMessage> msgQ; SocketSystem ss; SocketListener sl(8080, Socket::IP6); ClientHandler cp(msgQ); sl.start(cp); try { while (true) { HttpMessage msg = msgQ.deQ(); std::cout << "\n\n clienthandler " + msg.findValue("toAddr") + " recvd message contents:\n " + msg.bodyString() + "\n from client " + msg.findValue("fromAddr") + "\n"; if (msg.bodyString() == "closeServer") { ::Sleep(100); } } } catch (std::exception& exc) { Show::write("\n Exeception caught: "); std::string exMsg = "\n " + std::string(exc.what()) + "\n\n"; Show::write(exMsg); } std::cout << "\n\n"; return 0; }
// -------------< establish client handler and start receiving messages >-------------- void Receiver::start() { ClientHandler ch(rcvrQ); size_t port = stoi(localUrl.substr(localUrl.find(":") + 1, 4)); SocketSystem ss; SocketListener sl(port, Socket::IP6); sl.start(ch); while (true) { HttpMessage msg = rcvrQ.deQ(); std::cout << "\n\n " + msg.findValue("toAddr") + " recvd message contents:\n " + msg.bodyString() + "\n from " + msg.findValue("fromAddr"); if (msg.bodyString() == "closeServer") break; } }
// ------------------------------------ Starts Receiver for the this component --------------------------- void Server::startReceiverThread() { BlockingQueue<HttpMessage> msgQ; try { SocketSystem ss; SocketListener sl(getServerPort(), Socket::IP6); Receiver cp(msgQ,"Server"); sl.start(cp); /* * Since this is a server the loop below never terminates. * We could easily change that by sending a distinguished * message for shutdown. */ while (true) { HttpMessage msg = msgQ.deQ(); std::string cPort = msg.findValue("From-Port"); if (msg.attributes()[0].first == "GET") { // Checks if its an file extraction request std::string filename = msg.findValue("file"); Show::write("\n\n Client @: "+cPort+ " => requested file :: " + filename); sendServerFiles(msg); } else Show::write("\n\n Message from client @:"+cPort +" => " + msg.bodyString()); } } catch (std::exception& exc) { Show::write("\n Exeception caught: "); std::string exMsg = "\n " + std::string(exc.what()) + "\n\n"; Show::write(exMsg); } }
//----< receiver functionality is defined by this function >--------- void ClientHandler::operator()(Socket socket) { std::function<void()> threadProc = [&]() { while (true) { HttpMessage msg = readMessage(socket); // read a message from socket if (msg.attributes().size() == 0 || msg.bodyString() == "quit") break; if (msg.findValue("type") == "returnList") { sendMessage(msg); continue; } else if (msg.findValue("type") == "returnFiles") { Sender sndr(msg.findValue("fromAddr")); sndr.start(); std::vector<std::string> files = splitString(msg.bodyString()); for (std::string file : files) { std::string fileSpec = searchFile(file); FileSystem::FileInfo fi(fileSpec); FileSystem::File fileIn(fileSpec); fileIn.open(FileSystem::File::in, FileSystem::File::binary); if (!fileIn.isGood()) { std::cout << "\n could not open file " << file; continue; } size_t fileSize = fi.size(); std::string sizeString = Converter<size_t>::toString(fileSize); HttpMessage message = sndr.makeMessage(4, "", msg.findValue("toAddr")); message.addAttribute(HttpMessage::Attribute("file", fileSpec)); message.addAttribute(HttpMessage::Attribute("content-length", sizeString)); sndr.postMessage(message); } sndr.postMessage(sndr.makeMessage(0, "closeServer", msg.findValue("toAddr"))); sndr.postMessage(sndr.makeMessage(0, "quit", msg.findValue("toAddr"))); sndr.wait(); continue; } else if (msg.attributes()[0].second == "error") { sendMessage(msg); continue; } msgQ_.enQ(msg); } }; std::thread receiveThread(threadProc); receiveThread.join(); }
// ------------------< prepare and send message to recepient >------------- void ClientHandler::sendMessage(HttpMessage msg) { HttpMessage message; Sender sndr(msg.findValue("fromAddr")); sndr.start(); message = sndr.makeMessage(0, msg.bodyString(), msg.findValue("toAddr")); sndr.postMessage(message); sndr.postMessage(sndr.makeMessage(0, "closeServer", msg.findValue("toAddr"))); sndr.postMessage(sndr.makeMessage(0, "quit", msg.findValue("toAddr"))); sndr.wait(); }
// -----------------< get the requested files, with or without dependencies >------------ HttpMessage ClientHandler::getFiles(HttpMessage msg, std::string type) { HttpMessage message; if (!FileSystem::Directory::exists("../TestFileServer/" + msg.bodyString())) return errorMessage(msg, "\n no package " + msg.bodyString()); std::string path = "../TestFileServer/" + msg.bodyString() + "/"; std::vector<std::string> files = FileSystem::Directory::getFiles(path, "*.ver*"); if (files.size() == 0) return errorMessage(msg, "\n so files in package " + msg.bodyString()); std::vector<std::string> sendFiles; for (int i = files.size() - 1; i >= 0; --i) { // figure out the latest version of the files std::string ext = files[i].substr(files[i].find_last_of(".") + 1); if (ext == "xml") continue; std::string name = files[i].substr(0, files[i].find_last_of(".")); if (find(sendFiles, name) == sendFiles.size()) sendFiles.push_back(files[i]); // add only unique file names to be sent } std::vector<std::shared_ptr<AbstractXmlElement>> deps; if (type == "FileWithDeps") { // figure out dependencies of files to be sent for (int i = 0; i < sendFiles.size(); ++i) { std::string file = sendFiles[i]; if (!FileSystem::File::exists("../TestFileServer/" + msg.bodyString() + "/" + file)) continue; std::string xmlname = "../TestFileServer/" + msg.bodyString() + "/" + file + ".xml"; XmlDocument doc(xmlname, XmlDocument::file); deps = doc.element("deps").descendents().select(); for (auto dep : deps) if (dep->tag() == "") { // prevent circular dependencies to be stuck in a loop std::string depName = dep->value().substr(0, dep->value().find("\n")); if (find(sendFiles, depName.substr(0, depName.find_last_of("."))) == sendFiles.size()) sendFiles.push_back(depName); } } } std::string body; for (size_t i = 0; i < sendFiles.size() - 1; ++i) body += sendFiles[i] + ","; body += sendFiles[sendFiles.size() - 1]; message.addAttribute(HttpMessage::attribute("fromAddr", msg.findValue("toAddr"))); message.addAttribute(HttpMessage::attribute("toAddr", msg.findValue("fromAddr"))); message.addAttribute(HttpMessage::attribute("type", "returnFiles")); message.addBody(body); return message; }
int main() { Utils::Title("Testing HttpMessage class", '='); HttpMessage msg; msg.addAttribute(HttpMessage::attribute("Command", "GetFiles")); msg.addAttribute(HttpMessage::attribute("ToAddr", "127.0.0.1:8080")); msg.addAttribute(HttpMessage::attribute("FromAddr", "127.0.0.1:8081")); msg.addAttribute(HttpMessage::attribute("Mode", "OneWay")); msg.addAttribute(HttpMessage::attribute("content_length", "10")); msg.addBody(std::vector<HttpMessage::byte> { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }); std::cout << "\n" << Utils::addHeaderAndFooterLines(msg.toString()); Utils::title("testing headerString(), bodyString(), and toString()"); std::cout << "\nheader string:"; std::cout << "\n" << msg.headerString(); std::cout << "\nbody string:"; std::cout << "\n" << msg.bodyString(); std::cout << "\n\nmessage string:"; std::cout << "\n" << StringHelper::addHeaderAndFooterLines(msg.toString()); Utils::title("Testing removeAttribute"); putline(); msg.removeAttribute("content_length"); std::cout << msg.toString(); putline(); Utils::title("Testing addBody(const std::string&)"); std::string msgBody = "<msg>this is a message</msg>"; msg.addAttribute(HttpMessage::Attribute("content_length", Converter<size_t>::toString(msgBody.size()))); msg.addBody(msgBody); std::cout << "\n" << StringHelper::addHeaderAndFooterLines(msg.toString()); Utils::title("Testing parseAttribute(const std::string&)"); std::string test2 = "name:value"; std::cout << "\n input = \"" << test2 << "\""; Attribute attrib2 = HttpMessage::parseAttribute(test2); std::cout << "\n result is: " << HttpMessage::attribString(attrib2); test2 = " name : value "; std::cout << "\n input = \"" << test2 << "\""; attrib2 = HttpMessage::parseAttribute(test2); std::cout << "\n result is: " << HttpMessage::attribString(attrib2); Utils::title("Testing Message parsing"); MockSocket sock(msg); HttpMessage msg2; while (true) { std::string line = sock.recvString(); if (line.size() == 0) break; Attribute attrib = HttpMessage::parseAttribute(line); msg2.addAttribute(attrib); } Value val = msg2.findValue("content_length"); if (val.size() > 0) { size_t numBytes = Converter<size_t>::toValue(val); byte* pBuffer = new byte[numBytes]; sock.recv(numBytes, pBuffer); msg2.addBody(numBytes, pBuffer); } std::cout << "\n" << Utils::addHeaderAndFooterLines(msg2.toString()); std::cout << "\n\n"; }