File indexing completed on 2025-10-20 09:03:40
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef ROOT7_RWebWindow
0014 #define ROOT7_RWebWindow
0015
0016 #include <ROOT/RWebDisplayHandle.hxx>
0017
0018 #include "ROOT/RConfig.hxx"
0019
0020 #include <memory>
0021 #include <vector>
0022 #include <string>
0023 #include <queue>
0024 #include <map>
0025 #include <functional>
0026 #include <mutex>
0027 #include <thread>
0028 #include <chrono>
0029
0030 class THttpCallArg;
0031 class THttpServer;
0032
0033 namespace ROOT {
0034
0035
0036
0037 using WebWindowConnectCallback_t = std::function<void(unsigned)>;
0038
0039
0040
0041 using WebWindowDataCallback_t = std::function<void(unsigned, const std::string &)>;
0042
0043
0044
0045
0046
0047
0048 using WebWindowWaitFunc_t = std::function<int(double)>;
0049
0050 class RFileDialog;
0051 class RWebWindowsManager;
0052 class RWebWindowWSHandler;
0053
0054 class RWebWindow {
0055
0056 friend class RWebWindowsManager;
0057 friend class RWebWindowWSHandler;
0058 friend class RWebDisplayHandle;
0059 friend class RFileDialog;
0060
0061 private:
0062 using timestamp_t = std::chrono::time_point<std::chrono::system_clock>;
0063
0064 struct QueueItem {
0065 int fChID{1};
0066 bool fText{true};
0067 std::string fData;
0068 QueueItem(int chid, bool txt, std::string &&data) : fChID(chid), fText(txt), fData(data) {}
0069 };
0070
0071 struct WebConn {
0072 unsigned fConnId{0};
0073 bool fHeadlessMode{false};
0074 bool fWasFirst{false};
0075 std::string fKey;
0076 int fKeyUsed{0};
0077 std::string fNewKey;
0078 std::unique_ptr<RWebDisplayHandle> fDisplayHandle;
0079 std::shared_ptr<THttpCallArg> fHold;
0080 timestamp_t fSendStamp;
0081 bool fActive{false};
0082 unsigned fWSId{0};
0083 int fReady{0};
0084 mutable std::mutex fMutex;
0085 timestamp_t fRecvStamp;
0086 int fRecvCount{0};
0087 int fSendCredits{0};
0088 int fClientCredits{0};
0089 bool fDoingSend{false};
0090 unsigned long fRecvSeq{0};
0091 unsigned long fSendSeq{1};
0092 std::queue<QueueItem> fQueue;
0093 std::map<int,std::shared_ptr<RWebWindow>> fEmbed;
0094 WebConn() = default;
0095 WebConn(unsigned connid) : fConnId(connid) {}
0096 WebConn(unsigned connid, unsigned wsid) : fConnId(connid), fActive(true), fWSId(wsid) {}
0097 WebConn(unsigned connid, bool headless_mode, const std::string &key)
0098 : fConnId(connid), fHeadlessMode(headless_mode), fKey(key)
0099 {
0100 ResetStamps();
0101 }
0102 ~WebConn();
0103
0104 void ResetStamps() { fSendStamp = fRecvStamp = std::chrono::system_clock::now(); }
0105
0106 void ResetData()
0107 {
0108 fActive = false;
0109 fWSId = 0;
0110 fReady = 0;
0111 fDoingSend = false;
0112 fSendCredits = 0;
0113 fClientCredits = 0;
0114 fRecvSeq = 0;
0115 fSendSeq = 1;
0116 while (!fQueue.empty())
0117 fQueue.pop();
0118 }
0119 };
0120
0121 struct MasterConn {
0122 unsigned connid{0};
0123 int channel{-1};
0124 MasterConn(unsigned _connid, int _channel) : connid(_connid), channel(_channel) {}
0125 };
0126
0127 enum EQueueEntryKind { kind_None, kind_Connect, kind_Data, kind_Disconnect };
0128
0129 struct QueueEntry {
0130 unsigned fConnId{0};
0131 EQueueEntryKind fKind{kind_None};
0132 std::string fData;
0133 QueueEntry() = default;
0134 QueueEntry(unsigned connid, EQueueEntryKind kind, std::string &&data) : fConnId(connid), fKind(kind), fData(data) {}
0135 };
0136
0137 using ConnectionsList_t = std::vector<std::shared_ptr<WebConn>>;
0138
0139 std::shared_ptr<RWebWindowsManager> fMgr;
0140 std::shared_ptr<RWebWindow> fMaster;
0141 std::vector<MasterConn> fMasterConns;
0142 std::string fDefaultPage;
0143 std::string fPanelName;
0144 unsigned fId{0};
0145 bool fUseServerThreads{false};
0146 bool fUseProcessEvents{false};
0147 bool fProcessMT{false};
0148 bool fSendMT{false};
0149 bool fRequireAuthKey{true};
0150 std::shared_ptr<RWebWindowWSHandler> fWSHandler;
0151 unsigned fConnCnt{0};
0152 ConnectionsList_t fPendingConn;
0153 ConnectionsList_t fConn;
0154 mutable std::mutex fConnMutex;
0155 unsigned fConnLimit{1};
0156 std::string fConnToken;
0157 bool fNativeOnlyConn{false};
0158 bool fUseCurrentDir{false};
0159 unsigned fMaxQueueLength{10};
0160 WebWindowConnectCallback_t fConnCallback;
0161 WebWindowDataCallback_t fDataCallback;
0162 WebWindowConnectCallback_t fDisconnCallback;
0163 std::thread::id fCallbacksThrdId;
0164 bool fCallbacksThrdIdSet{false};
0165 bool fHasWindowThrd{false};
0166 std::thread fWindowThrd;
0167 std::queue<QueueEntry> fInputQueue;
0168 std::mutex fInputQueueMutex;
0169 unsigned fWidth{0}, fHeight{0};
0170 int fX{-1}, fY{-1};
0171 float fOperationTmout{50.};
0172 std::string fClientVersion;
0173 std::string fProtocolFileName;
0174 int fProtocolCnt{-1};
0175 unsigned fProtocolConnId{0};
0176 std::string fProtocolPrefix;
0177 std::string fProtocol;
0178 std::string fUserArgs;
0179 std::shared_ptr<void> fClearOnClose;
0180 static std::string gJSROOTsettings;
0181
0182 std::shared_ptr<RWebWindowWSHandler> CreateWSHandler(std::shared_ptr<RWebWindowsManager> mgr, unsigned id, double tmout);
0183
0184 bool ProcessWS(THttpCallArg &arg);
0185
0186 void CompleteWSSend(unsigned wsid);
0187
0188 ConnectionsList_t GetWindowConnections(unsigned connid = 0, bool only_active = false) const;
0189
0190
0191 std::shared_ptr<WebConn> FindConnection(unsigned wsid);
0192
0193 void ClearConnection(std::shared_ptr<WebConn> &conn, bool provide_signal = false);
0194
0195 std::shared_ptr<WebConn> RemoveConnection(unsigned wsid, bool provide_signal = false);
0196
0197 bool _CanTrustIn(std::shared_ptr<WebConn> &conn, const std::string &key, const std::string &ntry, bool remote, bool test_first_time);
0198
0199 std::string _MakeSendHeader(std::shared_ptr<WebConn> &conn, bool txt, const std::string &data, int chid);
0200
0201 void ProvideQueueEntry(unsigned connid, EQueueEntryKind kind, std::string &&arg);
0202
0203 void InvokeCallbacks(bool force = false);
0204
0205 void SubmitData(unsigned connid, bool txt, std::string &&data, int chid = 1);
0206
0207 bool CheckDataToSend(std::shared_ptr<WebConn> &conn);
0208
0209 void CheckDataToSend(bool only_once = false);
0210
0211 bool HasKey(const std::string &key, bool also_newkey = false) const;
0212
0213 void RemoveKey(const std::string &key);
0214
0215 std::string GenerateKey() const;
0216
0217 void CheckPendingConnections();
0218
0219 void CheckInactiveConnections();
0220
0221 unsigned AddDisplayHandle(bool headless_mode, const std::string &key, std::unique_ptr<RWebDisplayHandle> &handle);
0222
0223 unsigned AddEmbedWindow(std::shared_ptr<RWebWindow> window, unsigned connid, int channel);
0224
0225 void RemoveEmbedWindow(unsigned connid, int channel);
0226
0227 void AddMasterConnection(std::shared_ptr<RWebWindow> window, unsigned connid, int channel);
0228
0229 std::vector<MasterConn> GetMasterConnections(unsigned connid = 0) const;
0230
0231 void RemoveMasterConnection(unsigned connid = 0);
0232
0233 bool ProcessBatchHolder(std::shared_ptr<THttpCallArg> &arg);
0234
0235 std::string GetConnToken() const;
0236
0237 unsigned MakeHeadless(bool create_new = false);
0238
0239 unsigned FindHeadlessConnection();
0240
0241 static std::function<bool(const std::shared_ptr<RWebWindow> &, unsigned, const std::string &)> gStartDialogFunc;
0242
0243 static void SetStartDialogFunc(std::function<bool(const std::shared_ptr<RWebWindow> &, unsigned, const std::string &)>);
0244
0245 static std::string HMAC(const std::string &key, const std::string &sessionKey, const char *msg, int msglen);
0246
0247 public:
0248
0249 RWebWindow();
0250
0251 ~RWebWindow();
0252
0253
0254 unsigned GetId() const { return fId; }
0255
0256
0257 std::shared_ptr<RWebWindowsManager> GetManager() const { return fMgr; }
0258
0259
0260
0261
0262
0263 void SetDefaultPage(const std::string &page) { fDefaultPage = page; }
0264
0265 void SetPanelName(const std::string &name);
0266
0267
0268 void SetGeometry(unsigned width, unsigned height)
0269 {
0270 fWidth = width;
0271 fHeight = height;
0272 }
0273
0274
0275 void SetPosition(unsigned x, unsigned y)
0276 {
0277 fX = x;
0278 fY = y;
0279 }
0280
0281
0282
0283
0284 unsigned GetWidth() const { return fWidth; }
0285
0286
0287
0288 unsigned GetHeight() const { return fHeight; }
0289
0290
0291
0292 int GetX() const { return fX; }
0293
0294
0295
0296 int GetY() const { return fY; }
0297
0298 void SetConnLimit(unsigned lmt = 0);
0299
0300 unsigned GetConnLimit() const;
0301
0302 void SetConnToken(const std::string &token = "");
0303
0304
0305
0306 void SetMaxQueueLength(unsigned len = 10) { fMaxQueueLength = len; }
0307
0308
0309
0310 unsigned GetMaxQueueLength() const { return fMaxQueueLength; }
0311
0312
0313
0314 void SetNativeOnlyConn(bool on = true) { fNativeOnlyConn = on; }
0315
0316
0317
0318 bool IsNativeOnlyConn() const { return fNativeOnlyConn; }
0319
0320
0321
0322 void SetRequireAuthKey(bool on) { fRequireAuthKey = on; }
0323
0324
0325
0326 bool IsRequireAuthKey() const { return fRequireAuthKey; }
0327
0328
0329
0330 void SetUseCurrentDir(bool on = true) { fUseCurrentDir = on; }
0331
0332
0333
0334 bool IsUseCurrentDir() const { return fUseCurrentDir; }
0335
0336 void SetClientVersion(const std::string &vers);
0337
0338 std::string GetClientVersion() const;
0339
0340 void SetUserArgs(const std::string &args);
0341
0342 std::string GetUserArgs() const;
0343
0344 int NumConnections(bool with_pending = false) const;
0345
0346 unsigned GetConnectionId(int num = 0) const;
0347
0348 std::vector<unsigned> GetConnections(unsigned excludeid = 0) const;
0349
0350 bool HasConnection(unsigned connid = 0, bool only_active = true) const;
0351
0352 void CloseConnections();
0353
0354 void CloseConnection(unsigned connid);
0355
0356
0357 float GetOperationTmout() const { return fOperationTmout; }
0358
0359
0360 void SetOperationTmout(float tm = 50.) { fOperationTmout = tm; }
0361
0362 std::string GetUrl(bool remote = true);
0363
0364 THttpServer *GetServer();
0365
0366 void Sync();
0367
0368 void Run(double tm = 0.);
0369
0370 unsigned Show(const RWebDisplayArgs &args = "");
0371
0372 unsigned GetDisplayConnection() const;
0373
0374
0375 bool IsShown() const { return GetDisplayConnection() != 0; }
0376
0377 bool CanSend(unsigned connid, bool direct = true) const;
0378
0379 int GetSendQueueLength(unsigned connid) const;
0380
0381 void Send(unsigned connid, const std::string &data);
0382
0383 void SendBinary(unsigned connid, const void *data, std::size_t len);
0384
0385 void SendBinary(unsigned connid, std::string &&data);
0386
0387 void RecordData(const std::string &fname = "protocol.json", const std::string &fprefix = "");
0388
0389 std::string GetAddr() const;
0390
0391 _R__DEPRECATED_LATER("Use GetUrl() to get valid connection URL") std::string GetRelativeAddr(const std::shared_ptr<RWebWindow> &win) const;
0392
0393 _R__DEPRECATED_LATER("Use GetAddr() to get valid connection URL") std::string GetRelativeAddr(const RWebWindow &win) const;
0394
0395 void SetCallBacks(WebWindowConnectCallback_t conn, WebWindowDataCallback_t data, WebWindowConnectCallback_t disconn = nullptr);
0396
0397 void Reset();
0398
0399 void SetConnectCallBack(WebWindowConnectCallback_t func);
0400
0401 void SetDataCallBack(WebWindowDataCallback_t func);
0402
0403 void SetDisconnectCallBack(WebWindowConnectCallback_t func);
0404
0405 void SetClearOnClose(const std::shared_ptr<void> &handle = nullptr);
0406
0407 void AssignThreadId();
0408
0409 void UseServerThreads();
0410
0411 int WaitFor(WebWindowWaitFunc_t check);
0412
0413 int WaitForTimed(WebWindowWaitFunc_t check);
0414
0415 int WaitForTimed(WebWindowWaitFunc_t check, double duration);
0416
0417 void StartThread();
0418
0419 void StopThread();
0420
0421 void TerminateROOT();
0422
0423 static std::shared_ptr<RWebWindow> Create();
0424
0425 static unsigned ShowWindow(std::shared_ptr<RWebWindow> window, const RWebDisplayArgs &args = "");
0426
0427 static bool IsFileDialogMessage(const std::string &msg);
0428
0429 static bool EmbedFileDialog(const std::shared_ptr<RWebWindow> &window, unsigned connid, const std::string &args);
0430
0431 static void SetJSROOTSettings(const std::string &json);
0432 };
0433
0434 }
0435
0436 #endif