Skip to content

Commit

Permalink
wip commit
Browse files Browse the repository at this point in the history
Signed-off-by: Rashesh Padia <[email protected]>
Change-Id: I848f853be8c14d3367f8501c603114a3e23a617b
  • Loading branch information
Rash419 committed Aug 14, 2024
1 parent 9dfee82 commit 5760e28
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 6 deletions.
45 changes: 44 additions & 1 deletion wsd/Admin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#include <Poco/JSON/Array.h>
#include <Poco/JSON/Object.h>
#include <config.h>

#include <chrono>
#include <cstddef>
#include <iomanip>
#include <string>
#include <sys/poll.h>
#include <unistd.h>

Expand Down Expand Up @@ -40,7 +44,6 @@

using namespace COOLProtocol;

using Poco::Net::HTTPResponse;
using Poco::Util::Application;

const int Admin::MinStatsIntervalMs = 50;
Expand Down Expand Up @@ -414,6 +417,10 @@ void AdminSocketHandler::handleMessage(const std::vector<char> &payload)
{
_admin->setCloseMonitorFlag();
}
else if (tokens.equals(0, "rollingupdate") && tokens.size() > 1)
{
_admin->setRollingUpdateInfo(tokens[1]);
}
}

AdminSocketHandler::AdminSocketHandler(Admin* adminManager,
Expand Down Expand Up @@ -1303,6 +1310,42 @@ void Admin::deleteMonitorSocket(const std::string& uriWithoutParam)
}
}

void Admin::setRollingUpdateInfo(const std::string& jsonString)
{
Poco::JSON::Object::Ptr object;
if (JsonUtil::parseJSON(jsonString, object))
{
bool status = JsonUtil::getJSONValue<bool>(object, "inprogress");
setRollingUpdateStatus(status);
Poco::JSON::Array::Ptr infoArray = object->getArray("serverinfo");
if (!infoArray.isNull())
{
for(size_t i=0; i < infoArray->size(); i++)
{
if (!infoArray->isObject(i))
{
return;
}
const auto serverInfoObject = infoArray->getObject(i);
const std::string gitHash = JsonUtil::getJSONValue<std::string>(serverInfoObject , "gitHash");
const std::string serverId = JsonUtil::getJSONValue<std::string>(serverInfoObject, "serverId");
const std::string routeToken = JsonUtil::getJSONValue<std::string>(serverInfoObject, "routeToken");
_rollingUpdateInfo.try_emplace(gitHash, RollingUpdateServerInfo(gitHash, serverId, routeToken));
}
}
}
}

std::string Admin::getBuddyServer(const std::string& gitHash)
{
auto iterator = _rollingUpdateInfo.find(gitHash);
if (iterator != _rollingUpdateInfo.end())
{
return iterator->second.getRouteToken();
}
return std::string();
}

void Admin::stop()
{
joinThread();
Expand Down
34 changes: 34 additions & 0 deletions wsd/Admin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

#include "net/WebSocketHandler.hpp"
#include "COOLWSD.hpp"
#include <string>
#include <vector>

class Admin;

Expand Down Expand Up @@ -187,6 +189,14 @@ class Admin : public SocketPoll

void setCloseMonitorFlag() { _closeMonitor = true; }

void setRollingUpdateInfo(const std::string& jsonString);

void setRollingUpdateStatus(bool status) { _rollingUpdateStatus = status; }

bool getRollingUpdateStatus() { return _rollingUpdateStatus; }

std::string getBuddyServer(const std::string& gitHash);

private:
/// Notify Forkit of changed settings.
void notifyForkit();
Expand Down Expand Up @@ -254,6 +264,30 @@ class Admin : public SocketPoll
std::map<std::string, std::shared_ptr<MonitorSocketHandler>> _monitorSockets;

std::atomic<bool> _closeMonitor = false;

class RollingUpdateServerInfo
{
public:
std::string getGitHash() { return _gitHash; }
std::string getServerId() { return _serverId; }
std::string getRouteToken() { return _routeToken; }

RollingUpdateServerInfo(const std::string& gitHash, const std::string& serverId,
const std::string& routeToken)
: _gitHash(gitHash)
, _serverId(serverId)
, _routeToken(routeToken)
{
}

private:
std::string _gitHash;
std::string _serverId;
std::string _routeToken;
};

std::map<std::string, RollingUpdateServerInfo> _rollingUpdateInfo;
std::atomic<bool> _rollingUpdateStatus;
};

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
43 changes: 38 additions & 5 deletions wsd/ClientRequestDispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -718,18 +718,26 @@ void ClientRequestDispatcher::handleIncomingMessage(SocketDisposition& dispositi
{
bool served = false;

std::string requestUri = requestDetails.getURI();
bool versionMismatch = false;
if (requestUri.find("browser/" COOLWSD_VERSION_HASH "/") == std::string::npos &&
requestUri.find("admin/") == std::string::npos)
{
versionMismatch = true;
}

// File server
assert(socket && "Must have a valid socket");
constexpr auto ProxyRemote = "/remote/";
constexpr auto ProxyRemoteLen = sizeof(ProxyRemote) - 1;
constexpr auto ProxyRemoteStatic = "/remote/static/";
const auto uri = requestDetails.getURI();
const auto pos = uri.find(ProxyRemoteStatic);
const auto pos = requestUri.find(ProxyRemoteStatic);
if (pos != std::string::npos)
{
if (uri.ends_with("lokit-extra-img.svg"))
if (requestUri.ends_with("lokit-extra-img.svg"))
{
ProxyRequestHandler::handleRequest(uri.substr(pos + ProxyRemoteLen), socket,
ProxyRequestHandler::handleRequest(requestUri.substr(pos + ProxyRemoteLen),
socket,
ProxyRequestHandler::getProxyRatingServer());
served = true;
}
Expand All @@ -743,12 +751,37 @@ void ClientRequestDispatcher::handleIncomingMessage(SocketDisposition& dispositi
const std::string& serverUri =
unlockImageUri.getScheme() + "://" + unlockImageUri.getAuthority();
ProxyRequestHandler::handleRequest(
uri.substr(pos + sizeof("/remote/static") - 1), socket, serverUri);
requestUri.substr(pos + sizeof("/remote/static") - 1), socket, serverUri);
served = true;
}
}
#endif
}
else if (COOLWSD::IndirectionServerEnabled && versionMismatch &&
Admin::instance().getRollingUpdateStatus())
{
std::string searchString = "/browser/";
size_t startHashPos = requestUri.find(searchString);
if (startHashPos != std::string::npos)
{
startHashPos += searchString.length();
size_t endHashPos = requestUri.find('/', startHashPos);

std::string gitHash;
if (endHashPos != std::string::npos)
{
gitHash = requestUri.substr(startHashPos, endHashPos - startHashPos);
}
else
{
gitHash = requestUri.substr(startHashPos);
}
std::string routeToken = Admin::instance().getBuddyServer(gitHash);
if (!routeToken.empty())
requestUri = requestUri + "?RouteToken=" + routeToken;
ProxyRequestHandler::handleRequest(requestUri, socket);
}
}
else
{
FileServerRequestHandler::ResourceAccessDetails accessDetails;
Expand Down
74 changes: 74 additions & 0 deletions wsd/ProxyRequestHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,80 @@
std::unordered_map<std::string, std::shared_ptr<http::Response>> ProxyRequestHandler::CacheFileHash;
std::chrono::system_clock::time_point ProxyRequestHandler::MaxAge;

// TODO: merge below functions into one, to reduce the code duplication
void ProxyRequestHandler::handleRequest(const std::string& requestUri,
const std::shared_ptr<StreamSocket>& socket)
{
Poco::URI uriProxy(requestUri);
constexpr const auto zero = std::chrono::system_clock::time_point();
const auto timeNow = std::chrono::system_clock::now();

if (MaxAge > zero && timeNow > MaxAge)
{
CacheFileHash.clear();
MaxAge = zero;
}

const auto cacheEntry = CacheFileHash.find(uriProxy.getPath());
if (cacheEntry != CacheFileHash.end())
{
socket->sendAndShutdown(*cacheEntry->second);
return;
}

std::cerr << "proxyUri: " << uriProxy.toString() << "\n";
auto protocol = uriProxy.getScheme() == "https" ? http::Session::Protocol::HttpSsl
: http::Session::Protocol::HttpUnencrypted;

auto sessionProxy = http::Session::create(uriProxy.getHost(), protocol, uriProxy.getPort());

sessionProxy->setTimeout(std::chrono::seconds(10));
http::Request requestProxy(uriProxy.getPathAndQuery());
http::Session::FinishedCallback proxyCallback =
[socket, zero](const std::shared_ptr<http::Session>& httpSession)
{
try
{
const auto callbackNow = std::chrono::system_clock::now();
std::shared_ptr<http::Response> httpResponse = httpSession->response();
if (httpResponse->statusLine().statusCode() == http::StatusCode::OK)
{
if (MaxAge == zero)
{
MaxAge = callbackNow + std::chrono::hours(10);
}

CacheFileHash[httpSession->getUrl()] = httpResponse;

// We're proxying, we take responsibility.
httpResponse->set("Server", http::getServerString());

socket->sendAndShutdown(*httpResponse);
}
else
{
HttpHelper::sendErrorAndShutdown(http::StatusCode::BadRequest, socket);
}
}
catch (std::exception& exc)
{
LOG_ERR("ProxyCallback: " << exc.what());
HttpHelper::sendErrorAndShutdown(http::StatusCode::BadRequest, socket);
}
catch (...)
{
LOG_ERR("ProxyCallback: Unknown exception");
HttpHelper::sendErrorAndShutdown(http::StatusCode::BadRequest, socket);
}
};

sessionProxy->setFinishedHandler(std::move(proxyCallback));
if (!sessionProxy->asyncRequest(requestProxy, *COOLWSD::getWebServerPoll()))
{
HttpHelper::sendErrorAndShutdown(http::StatusCode::BadRequest, socket);
}
}

void ProxyRequestHandler::handleRequest(const std::string& relPath,
const std::shared_ptr<StreamSocket>& socket,
const std::string& serverUri)
Expand Down
4 changes: 4 additions & 0 deletions wsd/ProxyRequestHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ class ProxyRequestHandler
static void handleRequest(const std::string& relPath,
const std::shared_ptr<StreamSocket>& socket,
const std::string& serverUri);

static void handleRequest(const std::string& requestUri,
const std::shared_ptr<StreamSocket>& socket);

static std::string getProxyRatingServer() { return ProxyRatingServer; }

private:
Expand Down

0 comments on commit 5760e28

Please sign in to comment.