void MetaCDNReceiver::handle_delete(http_request message) {
	/*
	Use cases:
	1. when CDN deletes a file from itself to store some other file because of its limited capacity

	JSON Format
	Request
	{
		"FileName": "a.txt",
		"CdnId" : 2
	}

	Response: status OK or Forbidden (no json object included)
	*/
	try {
		int result;
		if(message.headers().content_type()==U("application/json")) {
			cout << endl << "---------------"<< endl;
			cout << message.to_string() << endl <<endl;

			json::value jsonObj = message.extract_json().get();
			int cdnId = jsonObj.at(U("CdnId")).as_integer();
			string fileName = utility::conversions::to_utf8string(jsonObj.at(U("FileName")).as_string());
			result = m_meta->deleteCdnFromMetaEntry(fileName, cdnId);
			message.reply(status_codes::OK, result==0? U("Deleted successfully") : U("Delete failed"));
		} else {
			message.reply(status_codes::Forbidden, U("Json object is required"));
		}
	} catch(json::json_exception &e) {
		message.reply(status_codes::Forbidden, U("Invalid json object"));
		return;
	}
}
void MetaCDNReceiver::handle_register(http_request message) {
	/*
	-when a new CDN joins, it has to register itself to Meta Server

	JSON Format
	Request
	{
		"Type": 0, //0=for cdn, 1=for fss
		"IP": "1.1.1.1:4000", //the sender CDN's IP address + port(listening to incoming requests)
		"Lat": 23.00, //the sender CDN's location
		"Lng": 148.12
	}
	Response
	{
		"CdnId": 1 //the assigned id for the cdn
	}

	*/
	try {

		int assignedId = -1;
		if(message.headers().content_type()==U("application/json")) {
			cout << endl << "---------------"<< endl;
			cout << message.to_string() << endl <<endl;

			json::value jsonObj = message.extract_json().get();
			if(jsonObj.at(U("Type")).as_integer() == 0) {
				string ipAddr = utility::conversions::to_utf8string(jsonObj.at(U("IP")).as_string());
				//TODO: validate ip address
				Address cdnAddr(make_pair(jsonObj.at(U("Lat")).as_double(), jsonObj.at(U("Lng")).as_double()), ipAddr);
				assignedId = m_meta->registerCdn(cdnAddr);
				json::value respFinal = json::value::object();
				respFinal[U("CdnId")] = json::value::number(assignedId);
				message.reply(assignedId!=-1? status_codes::OK : status_codes::NotFound, respFinal);
			} else if(jsonObj.at(U("Type")).as_integer() == 1){
				string ipAddr = utility::conversions::to_utf8string(jsonObj.at(U("IP")).as_string());
				//TODO: validate ip address
				Address fssAddr(make_pair(jsonObj.at(U("Lat")).as_double(), jsonObj.at(U("Lng")).as_double()), ipAddr);
				m_meta->setFssAddr(fssAddr);
				message.reply(status_codes::OK, "FSS registration complete");
			} else {
				message.reply(status_codes::Forbidden, U("Invalid type"));
			}
		} else {
			message.reply(status_codes::Forbidden, U("Json object is required"));
		}
	} catch(json::json_exception &e) {
		message.reply(status_codes::Forbidden, U("Invalid json object"));
		return;
	}
}
void MetaCDNReceiver::handle_update(http_request message) {
	/*
	Use cases:
	0. when CDN pulls a file from FSS (syncdown flow)
	1. when CDN updates an existing file (syncup flow; need invalidation process)
	2. when CDN creates a new file and stores in FSS and itself

	JSON Format
	Request
	{
		"Type": 0, // 0=CDN pulls a file from FSS, 1=CDN updates a file (+invalidation process), 2=CDN creates a new file and stores in FSS
		"FileName": "a.txt",
		"FileHash": "ahash", //could be empty string when Type=0 //only for type 1,2
		"CdnId": 1
		"TimeStamp": "12312312312" //REQUIRED for use case 1 and 2
	}

	Response: status OK or Forbidden (no json object included)
	*/

	try {
		if(message.headers().content_type()==U("application/json")) {
			cout << endl << "---------------"<< endl;
			cout << message.to_string() << endl <<endl;

			json::value jsonObj = message.extract_json().get();
			int cdnId = jsonObj.at(U("CdnId")).as_integer();
			string fileName = utility::conversions::to_utf8string(jsonObj.at(U("FileName")).as_string());
			
			int result;
			if(jsonObj.at(U("Type")).as_integer() == 0) {
				result = m_meta->addCdnToMetaEntry(fileName, cdnId);
			} else if(jsonObj.at(U("Type")).as_integer() == 1) {
				string fileHash = utility::conversions::to_utf8string(jsonObj.at(U("FileHash")).as_string());
				vector<int> newCdnList;
				newCdnList.push_back(cdnId);
				result = m_meta->updateMetaEntry(fileName, fileHash, newCdnList);
				if(result == 0) {
					result = m_meta->updateTimeStamp(fileName, jsonObj.at(U("TimeStamp")).as_string());
				} else {
					cout<<"MetaCDNReceiver::handle_update() - failed to update meta entry"<<endl;
					return;
				}

				//now, send invalidation msgs to other cdns
				unordered_map<int, Address>::const_iterator itr = m_meta->getCdnIdToAddrMap().begin();
				while(itr != m_meta->getCdnIdToAddrMap().end()) {
					if(itr->first == cdnId) {
						++itr;
						continue;
					}
					http_client cdn_client = http_client("http://" + itr->second.ipAddr);
					http_response resp = cdn_client.request(methods::DEL, "cdn/cache"+fileName).get();
					if (resp.status_code() != status_codes::OK) {
						cout<<"MetaCDNReceiver::handle_update() - failed to send invalidation message to "+itr->second.ipAddr<<endl;
					}
					++itr;
				}

			} else if(jsonObj.at(U("Type")).as_integer() == 2) {
				string fileHash = utility::conversions::to_utf8string(jsonObj.at(U("FileHash")).as_string());
				vector<int> newCdnList;
				newCdnList.push_back(cdnId);
				result = m_meta->addNewMetaEntry(fileName, fileHash, newCdnList);
				if(result == 0)
					result = m_meta->addNewTimeStamp(fileName, jsonObj.at(U("TimeStamp")).as_string());
			} else {
				message.reply(status_codes::Forbidden, U("Undefined Type"));
				return;
			}
			message.reply(result==0? status_codes::OK : status_codes::NotFound, result==0? U("Updated successfully") : U("Update failed"));

		} else {
			message.reply(status_codes::Forbidden, U("Json object is required"));
		}
	} catch(json::json_exception &e) {
		message.reply(status_codes::Forbidden, U("Invalid json object"));
		return;
	}
}
Exemplo n.º 4
0
void MyListener::handle_post(http_request message)
{
	string resp;
	json::value jvalue = message.extract_json().get();
	if (jvalue.is_null())
		message.reply(status_codes::BadRequest, "No json");
	else
	{
		//utility::stringstream_t stream;
		std::stringstream stream;
		jvalue.serialize(stream);
		boost::property_tree::ptree pt;
		try
		{
			boost::property_tree::read_json(stream, pt);
		}
		catch (boost::property_tree::json_parser_error& error)
		{
			cout
				<< error.message() << ": "
				<< error.filename() << ", line "
				<< error.line() << endl;
		}
		try
		{
			string login = pt.get<string>("login");
			//// ***** Проверка логина ****
			for (auto iter = login.begin(); iter != login.end(); ++iter)
			{
				if (!(*iter >= 'a' && *iter <= 'z'))
					resp += "Error in login. Unacceptable symbols\n";
			}

			string password = pt.get<string>("password");
			// ***** Проверка пароля *****
				if (password.length() < 8)
					resp += "Error in password. Insufficient password length\n";
				for (auto iter = password.begin(); iter != password.end(); ++iter)
				{
					//if (!isdigit(*iter) && !isalpha(*iter) && !ispunct(*iter))
					if (!(*iter >= 33 && *iter <= 126))
					{
						resp += "Error in password. Unacceptable symbols\n";
					}
				}

			//resp += login + " " + password;
		}
		catch (const boost::property_tree::ptree_bad_data& error)
		{
			//cout << error.what() << endl;
			resp += error.what();
		}
		catch (const boost::property_tree::ptree_bad_path& error)
		{
			//cout << error.what() << endl;
			resp += error.what();
		}
		
		////message.reply(status_codes::OK, "Yes json");
		//// ***** Проверка логина *****
		//if (!jvalue[L"login"].is_null())
		//{
		//	string login = utility::conversions::to_utf8string(jvalue[L"login"].as_string());
		//	for (auto iter = login.begin(); iter != login.end(); ++iter)
		//	{
		//		if (!(*iter >= 'a' && *iter <= 'z'))
		//			resp += "Error in login. Unacceptable symbols\n";
		//	}
		//}
		//// ***** Проверка пароля *****
		//if (!jvalue[L"password"].is_null())
		//{
		//	string password = utility::conversions::to_utf8string(jvalue[L"password"].as_string());
		//	if (password.length() < 8)
		//		resp += "Error in password. Insufficient password length\n";
		//	for (auto iter = password.begin(); iter != password.end(); ++iter)
		//	{
		//		//if (!isdigit(*iter) && !isalpha(*iter) && !ispunct(*iter))
		//		if (!(*iter >= 33 && *iter <= 126))
		//		{
		//			resp += "Error in password. Unacceptable symbols\n";
		//		}
		//	}
		//}
		if (resp.empty())
			resp = "OK";
		json::value response = json::value::string(utility::conversions::to_string_t(resp));
		message.reply(status_codes::OK, response);
		//message.reply(status_codes::OK, message.to_string());
	}

}