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