50 const char *undef =
"<undefined>";
52 if (!
value)
return dflt;
53 std::string svalue =
value;
54 if (svalue == undef)
return dflt;
56 if (svalue ==
"yes")
return 1;
57 if (svalue ==
"no")
return 0;
81 static std::shared_ptr<RWebWindowsManager> sInstance = std::make_shared<RWebWindowsManager>();
133 printf(
"\nWARNING!\n");
134 printf(
"Disabling loopback mode may leads to security problem.\n");
135 printf(
"See https://root.cern/about/security/ for more information.\n\n");
137 printf(
"Enforce session key to safely work on public network.\n");
138 printf(
"One may call RWebWindowsManager::SetUseSessionKey(false); to disable it.\n");
180 if (server_prefix.empty() || files_path.empty())
183 std::string prefix = server_prefix;
184 if (prefix.back() !=
'/')
186 loc[prefix] = files_path;
190 for (
auto &entry : loc) {
193 cfg.
Append(entry.first.c_str());
195 cfg.
Append(entry.second.c_str());
200 auto serv =
Instance()->GetServer();
202 serv->AddLocation(prefix.c_str(), files_path.c_str());
211 std::map<std::string, std::string> res;
217 while(
auto obj = next()) {
252 std::vector<unsigned char> buf(keylen, 0);
255 R__ASSERT(res == keylen &&
"Error in gSystem->GetCryptoRandom");
258 for (
int n = 0;
n < keylen;
n++) {
259 if ((
n > 0) && (
n % 4 == 0))
264 key.append(t.Data());
308 if (!fname || !*fname)
313 R__LOG_ERROR(
WebGUILog()) <<
"Problem with open listener socket " << fname <<
", check ROOT_LISTENER_SOCKET environment variable";
317 int res = s.
SendRaw(msg.c_str(), msg.length());
432 if (
gROOT->GetWebDisplay() ==
"off")
436 std::lock_guard<std::recursive_mutex> grd(
fMutex);
440 fServer = std::make_unique<THttpServer>(
"basic_sniffer");
451 if (send_thrds != -1)
472 R__LOG_ERROR(
WebGUILog()) <<
"Path to ROOT ui5 sources " << ui5dir <<
" not found, set ROOTUI5SYS correctly";
476 fServer->AddLocation(
"rootui5sys/", ui5dir.
Data());
479 for (
auto &entry : loc)
480 fServer->AddLocation(entry.first.c_str(), entry.second.c_str());
483 if (!with_http ||
fServer->IsAnyEngine())
487 int http_min =
gEnv->
GetValue(
"WebGui.HttpPortMin", 8800);
488 int http_max =
gEnv->
GetValue(
"WebGui.HttpPortMax", 9800);
489 int http_timer =
gEnv->
GetValue(
"WebGui.HttpTimer", 10);
490 int http_thrds =
gEnv->
GetValue(
"WebGui.HttpThreads", 10);
491 int http_wstmout =
gEnv->
GetValue(
"WebGui.HttpWSTmout", 10000);
492 int http_maxage =
gEnv->
GetValue(
"WebGui.HttpMaxAge", -1);
493 const char *extra_args =
gEnv->
GetValue(
"WebGui.HttpExtraArgs",
"");
494 int fcgi_port =
gEnv->
GetValue(
"WebGui.FastCgiPort", 0);
495 int fcgi_thrds =
gEnv->
GetValue(
"WebGui.FastCgiThreads", 10);
496 const char *fcgi_serv =
gEnv->
GetValue(
"WebGui.FastCgiServer",
"");
499 const char *http_bind =
gEnv->
GetValue(
"WebGui.HttpBind",
"");
501 const char *ssl_cert =
gEnv->
GetValue(
"WebGui.ServerCert",
"rootserver.pem");
503 const char *unix_socket =
gSystem->
Getenv(
"ROOT_WEBGUI_SOCKET");
504 if (!unix_socket || !*unix_socket)
506 const char *unix_socket_mode =
gEnv->
GetValue(
"WebGui.UnixSocketMode",
"0700");
507 bool use_unix_socket = unix_socket && *unix_socket;
510 fcgi_port = http_port = -1;
517 if ((http_port < 0) && (fcgi_port <= 0) && !use_unix_socket) {
532 if (http_max - http_min < ntry)
533 ntry = http_max - http_min;
542 while (ntry-- >= 0) {
543 if ((http_port == 0) && (fcgi_port <= 0) && !use_unix_socket) {
544 if ((http_min <= 0) || (http_max <= http_min)) {
545 R__LOG_ERROR(
WebGUILog()) <<
"Wrong HTTP range configuration, check WebGui.HttpPortMin/Max variables";
549 http_port = (
int)(http_min + (http_max - http_min) *
gRandom->
Rndm(1));
554 engine.
Form(
"fastcgi:%d?thrds=%d", fcgi_port, fcgi_thrds);
555 if (!
fServer->CreateEngine(engine))
557 if (fcgi_serv && (strlen(fcgi_serv) > 0))
563 if (use_unix_socket) {
564 engine.
Form(
"socket:%s?socket_mode=%s&", unix_socket, unix_socket_mode);
566 url = use_secure ?
"https://" :
"http://";
567 engine.
Form(
"%s:%d?", (use_secure ?
"https" :
"http"), http_port);
568 if (assign_loopback) {
569 engine.
Append(
"loopback&");
571 }
else if (http_bind && (strlen(http_bind) > 0)) {
579 engine.
Append(
TString::Format(
"webgui&top=remote&thrds=%d&websocket_timeout=%d", http_thrds, http_wstmout));
581 if (http_maxage >= 0)
584 if (use_secure && !strchr(ssl_cert,
'&')) {
585 engine.
Append(
"&ssl_cert=");
589 if (!use_unix_socket && !assign_loopback && extra_args && strlen(extra_args) > 0) {
591 engine.
Append(extra_args);
594 if (
fServer->CreateEngine(engine)) {
595 if (use_unix_socket) {
597 fAddr.append(unix_socket);
599 }
else if (http_port > 0) {
602 fAddr.append(std::to_string(http_port));
607 use_unix_socket =
false;
622 std::lock_guard<std::recursive_mutex> grd(
fMutex);
629 std::shared_ptr<RWebWindow>
win = std::make_shared<RWebWindow>();
636 double dflt_tmout =
gEnv->
GetValue(
"WebGui.OperationTmout", 50.);
641 std::string fname, prefix;
643 prefix = std::string(
"f") + std::to_string(
fIdCnt) +
"_";
644 fname = std::string(
"protcol") + std::to_string(
fIdCnt) +
".json";
646 fname =
"protocol.json";
648 win->RecordData(fname, prefix);
655 win->fUseProcessEvents =
true;
659 win->UseServerThreads();
661 const char *token =
gEnv->
GetValue(
"WebGui.ConnToken",
"");
663 win->SetConnToken(token);
665 fServer->RegisterWS(wshandler);
693 std::string addr =
"/";
694 addr.append(
win.fWSHandler->GetName());
701 if (
win.IsRequireAuthKey() || produced_key) {
702 key =
win.GenerateKey();
704 addr.append(
"?key=");
707 std::unique_ptr<ROOT::RWebDisplayHandle> dummy;
708 win.AddDisplayHandle(
false, key, dummy);
711 auto token =
win.GetConnToken();
712 if (!token.empty()) {
713 addr.append(qmark ?
"&" :
"?");
714 addr.append(
"token=");
793 auto handle = std::make_unique<RWebDisplayHandle>(
"");
794 win.AddDisplayHandle(
false,
"", handle);
811 if (!normal_http && (
gEnv->
GetValue(
"WebGui.ForceHttp", 0) == 1))
816 std::string url =
GetUrl(
win, normal_http, &key);
822 std::lock_guard<std::recursive_mutex> grd(
fMutex);
839 auto winurl = args.
GetUrl();
840 winurl.erase(0,
fAddr.length());
845 std::cout <<
"New web window: " << args.
GetUrl() << std::endl;
849 if (
fAddr.compare(0,9,
"socket://") == 0)
852#if !defined(R__MACOSX) && !defined(R__WIN32)
854 const char *varname =
"WebGui.CheckRemoteDisplay";
857 if (displ && *displ && (*displ !=
':')) {
860 "ROOT web-based widget started in the session where DISPLAY set to " << displ <<
"\n" <<
861 "Means web browser will be displayed on remote X11 server which is usually very inefficient\n"
862 "One can start ROOT session in server mode like \"root -b --web=server:8877\" and forward http port to display node\n"
863 "Or one can use rootssh script to configure port forwarding and display web widgets automatically\n"
864 "Find more info on https://root.cern/for_developers/root7/#rbrowser\n"
865 "This message can be disabled by setting \"" << varname <<
": no\" in .rootrc file\n";
873 if (
win.IsUseCurrentDir())
874 server->AddLocation(
"currentdir/",
".");
903 int res = 0, cnt = 0;
906 auto start = std::chrono::high_resolution_clock::now();
912 while ((res = check(spent)) == 0) {
921 std::this_thread::sleep_for(std::chrono::milliseconds(cnt > 5000 ? 10 : 1));
923 std::chrono::duration<double, std::milli> elapsed = std::chrono::high_resolution_clock::now() - start;
925 spent = elapsed.count() * 1
e-3;
927 if (timed && (spent > timelimit))
#define R__LOG_ERROR(...)
static bool gWebWinMainThrdSet
static std::thread::id gWebWinMainThrd
This thread id used to identify main application thread, where ROOT event processing runs To inject c...
static bool gWebWinLoopbackMode
static bool gWebWinUseSessionKey
R__EXTERN TApplication * gApplication
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void on
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t win
R__EXTERN TRandom * gRandom
R__EXTERN TSystem * gSystem
Holds different arguments for starting browser with RWebDisplayHandle::Display() method.
std::string GetBrowserName() const
Returns configured browser name.
EBrowserKind GetBrowserKind() const
returns configured browser kind, see EBrowserKind for supported values
RWebDisplayArgs & SetX(int x=-1)
set preferable web window x position, negative is default
bool IsSupportHeadless() const
returns true if browser supports headless mode
RWebDisplayArgs & SetUrl(const std::string &url)
set window url
int GetWidth() const
returns preferable web window width
const std::string & GetUrl() const
returns window url
void AppendUrlOpt(const std::string &opt)
append extra url options, add "&" as separator if required
int GetY() const
set preferable web window y position
int GetHeight() const
returns preferable web window height
void SetHttpServer(THttpServer *serv)
set http server instance, used for window display
RWebDisplayArgs & SetWidth(int w=0)
set preferable web window width
bool IsInteractiveBrowser() const
returns true if interactive browser window supposed to be started
RWebDisplayArgs & SetY(int y=-1)
set preferable web window y position, negative is default
bool IsHeadless() const
returns headless mode
RWebDisplayArgs & SetHeight(int h=0)
set preferable web window height
@ kServer
indicates that ROOT runs as server and just printouts window URL, browser should be started by the us...
@ kOff
disable web display, do not start any browser
@ kEmbedded
window will be embedded into other, no extra browser need to be started
int GetX() const
set preferable web window x position
static bool NeedHttpServer(const RWebDisplayArgs &args)
Check if http server required for display.
static std::unique_ptr< RWebDisplayHandle > Display(const RWebDisplayArgs &args)
Create web display.
static int GetBoolEnv(const std::string &name, int dfl=-1)
Parse boolean gEnv variable which should be "yes" or "no".
Represents web window, which can be shown in web browser or any other supported environment.
static void AddServerLocation(const std::string &server_prefix, const std::string &files_path)
Configure server location which can be used for loading of custom scripts or files When THttpServer i...
static std::string GenerateKey(int keylen=32)
Static method to generate cryptographic key Parameter keylen defines length of cryptographic key in b...
bool fUseSessionKey
! is session key has to be used for data signing
bool CreateServer(bool with_http=false)
Creates http server, if required - with real http engine (civetweb) One could configure concrete HTTP...
static void SetUseConnectionKey(bool on=true)
Enable or disable usage of connection key (default on) If enabled, each connection (and reconnection)...
bool fExternalProcessEvents
! indicate that there are external process events engine
std::recursive_mutex fMutex
! main mutex, used for window creations
RWebWindowsManager()
window manager constructor Required here for correct usage of unique_ptr<THttpServer>
int WaitFor(RWebWindow &win, WebWindowWaitFunc_t check, bool timed=false, double tm=-1)
Waits until provided check function or lambdas returns non-zero value Regularly calls WebWindow::Sync...
static void ClearServerLocations()
Clear all server locations Does not change configuration of already running HTTP server.
WebWindowShowCallback_t fShowCallback
! function called for each RWebWindow::Show call
WebWindowDeleteCallback_t fDeleteCallback
! function called when RWebWindow is destroyed
unsigned ShowWindow(RWebWindow &win, const RWebDisplayArgs &args)
Show window in specified location, see Show() method for more details.
std::string fAddr
! HTTP address of the server
void Terminate()
Terminate http server and ROOT application.
unsigned fIdCnt
! counter for identifiers
~RWebWindowsManager()
window manager destructor Required here for correct usage of unique_ptr<THttpServer>
THttpServer * GetServer() const
Returns THttpServer instance.
std::string fSessionKey
! secret session key used on client to code connections keys
bool fUseHttpThrd
! use special thread for THttpServer
static void AssignMainThrd()
Re-assigns main thread id Normally main thread id recognized at the moment when library is loaded It ...
static void SetUseSessionKey(bool on=true)
Enable or disable usage of session key (default on) If enabled, secrete session key used to calculate...
bool IsUseHttpThread() const
Returns true if http server use special thread for requests processing (default off)
bool fUseSenderThreads
! use extra threads for sending data from RWebWindow to clients
std::unique_ptr< THttpServer > fServer
! central communication with the all used displays
static void SetLoopbackMode(bool on=true)
Set loopback mode for THttpServer used for web widgets By default is on.
static bool IsMainThrd()
Returns true when called from main process Main process recognized at the moment when library is load...
static std::shared_ptr< RWebWindowsManager > & Instance()
Returns default window manager Used to display all standard ROOT elements like TCanvas or TFitPanel.
bool InformListener(const std::string &msg)
If ROOT_LISTENER_SOCKET variable is configured, message will be sent to that unix socket.
float fLaunchTmout
! timeout in seconds to start browser process, default 30s
static std::map< std::string, std::string > GetServerLocations()
Returns server locations as <std::string, std::string> Key is location name (with slash at the end) a...
std::string GetUrl(RWebWindow &win, bool remote=false, std::string *produced_key=nullptr)
Provide URL address to access specified window from inside or from remote.
void Unregister(RWebWindow &win)
Release all references to specified window Called from RWebWindow destructor.
static bool IsLoopbackMode()
Returns true if loopback mode used by THttpServer for web widgets.
std::shared_ptr< RWebWindow > CreateWindow()
Creates new window To show window, RWebWindow::Show() have to be called.
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
virtual void SetValue(const char *name, const char *value, EEnvLevel level=kEnvChange, const char *type=nullptr)
Set the value of a resource or create a new resource.
Bool_t Connect(const char *signal, const char *receiver_class, void *receiver, const char *slot)
Non-static method is used to connect from the signal of this object to the receiver slot.
Bool_t Disconnect(const char *signal=nullptr, void *receiver=nullptr, const char *slot=nullptr)
Disconnects signal of this object from slot of receiver.
static const TString & GetDataDir()
Get the data directory in the installation. Static utility function.
virtual void SetSeed(ULong_t seed=0)
Set the random generator seed.
Double_t Rndm() override
Machine independent random number generator.
virtual void Close(Option_t *opt="")
Close the socket.
virtual Int_t SendRaw(const void *buffer, Int_t length, ESendRecvOptions opt=kDefault)
Send a raw buffer of specified length.
virtual Bool_t IsValid() const
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Ssiz_t First(char c) const
Find first occurrence of a character c.
const char * Data() const
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
TString & Append(const char *cs)
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
static TString Itoa(Int_t value, Int_t base)
Converts an Int_t to a TString with respect to the base specified (2-36).
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
virtual const char * Getenv(const char *env)
Get environment variable.
virtual Int_t GetCryptoRandom(void *buf, Int_t len)
Return cryptographic random number Fill provided buffer with random values Returns number of bytes wr...
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
static void SingleShot(Int_t milliSec, const char *receiver_class, void *receiver, const char *method)
This static function calls a slot after a given time interval.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
ROOT::Experimental::RLogChannel & WebGUILog()
Log channel for WebGUI diagnostics.
std::function< int(double)> WebWindowWaitFunc_t
function signature for waiting call-backs Such callback used when calling thread need to waits for so...