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;
}
// ------------------------------------ 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);
	}
}
Exemple #3
0
//receriveFile
void MsgClient::receiveFile(Socket& socket) {
	HttpMessage msg;
	while (true)
	{
		std::string attribString = socket.recvString('\n');
		if (attribString.size() > 1)
		{
			HttpMessage::Attribute attrib = HttpMessage::parseAttribute(attribString);
			msg.addAttribute(attrib);
		}
		else
		{
			break;
		}
	}

	std::string filename = msg.findValue("file");
	if (filename != "")
	{
		size_t contentSize;
		std::string sizeString = msg.findValue("content-length");
		if (sizeString != "")
			contentSize = Converter<size_t>::toValue(sizeString);
		downloadFile(filename, contentSize, socket);
		Show::write("Client download file "+filename + "\n");
	}
}
// -----------------< prepare error message >--------------------
HttpMessage ClientHandler::errorMessage(HttpMessage msg, std::string body) {
	HttpMessage message;
	message.addAttribute(HttpMessage::attribute("type", "error"));
	message.addAttribute(HttpMessage::attribute("fromAddr", msg.findValue("toAddr")));
	message.addAttribute(HttpMessage::attribute("toAddr", msg.findValue("fromAddr")));
	message.addBody(body);
	return message;
}
// ------------------< 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();
}
// --------------< save the file to the clients machine >------------------
void ClientHandler::saveFileClient(HttpMessage msg, Socket& socket) {
	std::string filename = msg.findValue("file").substr(msg.findValue("file").find_last_of("/") + 1);
	std::string path = "../TestFileClient/";
	FileSystem::Directory::create(path);
	size_t contentSize;
	std::string sizeString = msg.findValue("content-length");
	if (sizeString != "")
		contentSize = Converter<size_t>::toValue(sizeString);
	else
		return;
	readFile(filename, contentSize, socket, path);
}
// ----------------< get the list of files in a specified package >-------------
HttpMessage ClientHandler::getFileNameList(HttpMessage msg) {
	std::vector<std::string> fileList = FileSystem::Directory::getFiles("../TestFileServer/" + msg.findValue("dir"));
	std::string body = "";
	for (size_t i = 0; i < fileList.size(); ++i)
		if (fileList[i] != "." && fileList[i] != "..")
			body += "\n  " + fileList[i];
	body += "\n";
	HttpMessage message;
	message.addAttribute(HttpMessage::attribute("fromAddr", msg.findValue("toAddr")));
	message.addAttribute(HttpMessage::attribute("toAddr", msg.findValue("fromAddr")));
	message.addAttribute(HttpMessage::attribute("type", "returnList"));
	message.addBody(body);
	return message;
}
// -------------< 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;
		}
}
// ---------------< construct a general message to be sent as acknowledgement >---------
HttpMessage ClientHandler::constructMessage(HttpMessage msg) {
		msg.removeAttribute("content-length");
		std::string bodyString = "<file>" + msg.findValue("file") + "</file>";
		std::string sizeString = Converter<size_t>::toString(bodyString.size());
		msg.addAttribute(HttpMessage::Attribute("content-length", sizeString));
		msg.addBody(bodyString);
		return msg;
}
// -----------------< 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;
}
// --------------------  This Function sends the requested file to the client and checks if the dependencies need to be sent--------------------
void Server::sendServerFiles(HttpMessage msg)
{	
	SocketSystem ss;
	SocketConnecter si;
	std::string cPort = msg.findValue("From-Port");
	int ClientPort = Converter<int>::toValue(cPort);	
	while (!si.connect("localhost", ClientPort))
	{
		::Sleep(100);
	}																					// Searches for the revlevant folder and then sends the file
	Sender send;	
	std::string DepsFlag = msg.findValue("ExtractWithDepsFlag");
	std::string fileToSend = msg.findValue("file");
	std::string path;	
	std::vector<std::string> dirs = FileSystem::Directory::getDirectories("./ServerDrive", fileToSend+"*");	
	if (dirs.size() == 0)
		Show::write("No such file present in the repository => " + fileToSend + "\n");
	if (dirs.size() == 1)
	{
		std::vector<std::string> files = FileSystem::Directory::getFiles("./ServerDrive/" + dirs[0], fileToSend + "*");
	    Show::write("\n Sending File :: " + files[0] + " to Client @: " + cPort);
		send.sendFile("./ServerDrive/" + dirs[0] + "/" + files[0], si, getServerPort(), ClientPort);
		path = "./ServerDrive/" + dirs[0] + "/";
		if (DepsFlag == "Yes")
			sendFileDependencies(msg, path,si);
	}
	if (dirs.size() > 1)
	{
		std::string latest_dir = getLatestDir(dirs,fileToSend);
		std::vector<std::string> files = FileSystem::Directory::getFiles("./ServerDrive/" + latest_dir, fileToSend + "*");
		Show::write("\n Sending File :: " + files[0] + " to Client @: " + cPort);
		send.sendFile("./ServerDrive/" + latest_dir + "/" + files[0], si , getServerPort(), ClientPort);
		path = "./ServerDrive/" + latest_dir + "/";
		if (DepsFlag == "Yes")
			sendFileDependencies(msg, path,si);
	}
	msg = makeMessage(1, "quit", "toAddr:localhost:"+cPort);
	send.sendMessage(msg, si);
}
// --------------------  This Function sends the Dependent files to the client--------------------
void Server::sendFileDependencies(HttpMessage msg, std::string path, Socket & socket)
{
	std::string cPort = msg.findValue("From-Port");
	int ClientPort = Converter<int>::toValue(cPort);
	std::string requestedFile = msg.findValue("file");
	Sender send;
	std::vector<std::string> depFile = FileSystem::Directory::getFiles(path, "*.xml");
	std::string src = path + depFile[0];
	XmlParser parser(src);
	XmlDocument* pDoc = parser.buildDocument();
	std::vector<std::string> depFileNames;
	std::vector<sPtr> found = pDoc->element("Dependencies").descendents().select();					// Read the dependencies xml
	if (found.size() > 0)
	{
		for (auto pElem : found)
		{		
			if (pElem->value() != "dep") 
				depFileNames.push_back(pElem->value());			
		}
	}
	for (std::string f : depFileNames) {																			// Sending each of the dependency file if exists
		std::string fileToSend = Utilities::StringHelper::trim(f);		
		std::vector<std::string> dirs = FileSystem::Directory::getDirectories("./ServerDrive/", fileToSend +"*");		
		if (dirs.size() == 0)
			Show::write("No such file present in the repository => " + fileToSend + "\n");		
		if (dirs.size() > 0)
		{
			std::string latest_dir = getLatestDir(dirs, fileToSend);			
			std::vector<std::string> files = FileSystem::Directory::getFiles("./ServerDrive/" + latest_dir, fileToSend + "*");
			Show::write("\nSending Dependency File of "+ requestedFile+ " => " + files[0] + " to client @: "+cPort);
			send.sendFile("./ServerDrive/" + latest_dir + "/" + files[0], socket , getServerPort(), ClientPort);
			path = "./ServerDrive/" + latest_dir + "/";			
		}
	}
	msg = makeMessage(1, "quit", "toAddr:localhost:"+cPort);
	send.sendMessage(msg, socket);
}
Exemple #13
0
HttpMessage	MsgClient::readMessage(Socket& socket) {
	Show::write("Client readMessage \n");
	//connectionClosed_ = false;
	HttpMessage msg;
	//read attribute
	while (true)
	{
		std::string attribString = socket.recvString('\n');
		if (attribString.size() > 1)
		{
			HttpMessage::Attribute attrib = HttpMessage::parseAttribute(attribString);
			msg.addAttribute(attrib);
		}
		else
		{
			break;
		}
	}

	if (msg.attributes().size() == 0)
	{
		return msg;
	}

	if (msg.attributes()[0].first == "POST")
	{
		
		std::string filePath = msg.findValue("filePath");
		if (filePath != "")
		{
			Show::write("Test for get FolderList");
			size_t numBytes = 0;
			size_t pos = msg.findAttribute("content-length");
			if (pos < msg.attributes().size())
			{
				numBytes = Converter<size_t>::toValue(msg.attributes()[pos].second);
				Socket::byte* buffer = new Socket::byte[numBytes + 1];
				socket.recv(numBytes, buffer);
				buffer[numBytes] = '\0';
				std::string msgBody(buffer);
				msg.addBody(msgBody);
				Show::write("getFolderList:" + msgBody + "\n");
			}

		}
	}
	return msg;
}
//----< 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();
}
// -----------< save a file to the server >---------------
void ClientHandler::saveFileServer(HttpMessage msg, Socket& socket) {
	FileSystem::Directory::create("../TestFileServer/");
	std::string filename = msg.findValue("file") + ".ver1";
	std::string packageName = msg.findValue("dir") + "." + getCurrentDate();
	std::string path = "../TestFileServer/" + packageName + "/";
	FileSystem::Directory::create(path);
	std::string dependencies = msg.findValue("deps");
	std::vector<std::string> deps;
	if(dependencies != "") deps = findDeps(dependencies);
	std::vector<std::string> files;
	for (auto fileSpec : FileSystem::Directory::getFiles(path, msg.findValue("file") + ".ver*"))
		if (fileSpec.substr(fileSpec.find_last_of(".")) != ".xml") files.push_back(fileSpec);
	if (files.size() > 0) {
		std::string name = files[files.size() - 1];
		int ver = std::stoi(name.substr(name.find_last_of(".") + 4));
		filename = msg.findValue("file") + ".ver" + std::to_string(ver + 1);
	}

	std::string xmlpath = path + filename + ".xml";
	XmlDocument doc = builDocument(filename, deps);
	FileSystem::File file(xmlpath);
	
	file.open(FileSystem::File::out, FileSystem::File::text);
	if (file.isGood())
		file.putLine(doc.toString());
	file.close();

	size_t contentSize;
	std::string sizeString = msg.findValue("content-length");
	if (sizeString != "")
		contentSize = Converter<size_t>::toValue(sizeString);
	else
		return;
	readFile(filename, contentSize, socket, path);
	updateXML(packageName, msg.findValue("file"), deps);
}
// ----------------< close a package to prevent addditional updating >-------------
HttpMessage ClientHandler::closePackage(HttpMessage msg) {
	HttpMessage message;
	if (!FileSystem::Directory::exists("../TestFileServer/" + msg.findValue("dir"))) {
		message.addAttribute(HttpMessage::attribute("type", "error"));
		message.addAttribute(HttpMessage::attribute("fromAddr", msg.findValue("toAddr")));
		message.addAttribute(HttpMessage::attribute("toAddr", msg.findValue("fromAddr")));
		std::string str = "\n  no package with the name " + msg.findValue("dir");
		message.addBody(str);
		return message;
	}
	std::string name = "../TestFileServer/" + msg.findValue("dir") + "/" + msg.findValue("dir") + "." + getCurrentDate() + ".xml";
	XmlDocument doc(name, XmlDocument::file);
	sPtr close = makeTaggedElement("close");
	close->addChild(makeTextElement("true"));
	doc.xmlRoot()->addChild(close);
	FileSystem::File::remove(name);
	FileSystem::File xml(name);
	xml.open(FileSystem::File::out, FileSystem::File::text);
	if (xml.isGood()) xml.putLine(doc.toString());
	xml.close();
	return message;
}
// --------------< construct a message based on custom body string >----------------
HttpMessage ClientHandler::constructMessage(HttpMessage msg, std::string body) {
	Sender sndr(msg.findValue("toAddr"));
	HttpMessage message = sndr.makeMessage(0, body, msg.findValue("fromAddr"));
	return message;
}