Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TCivetweb.cxx
Go to the documentation of this file.
1// Author: Sergey Linev 21/12/2013
2
3/*************************************************************************
4 * Copyright (C) 1995-2022, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10
11#include "TCivetweb.h"
12
13#include <cstdlib>
14#include <cstring>
15
16#ifdef _MSC_VER
17#include <windows.h>
18#include <tchar.h>
19#endif
20
21#include "THttpServer.h"
22#include "THttpWSEngine.h"
23#include "TUrl.h"
24#include "TSystem.h"
25
26//////////////////////////////////////////////////////////////////////////
27/// TCivetwebWSEngine
28///
29/// Implementation of THttpWSEngine for Civetweb
30
32protected:
34
35 /// True websocket requires extra thread to parallelize sending
36 Bool_t SupportSendThrd() const override { return kTRUE; }
37
38public:
40
41 virtual ~TCivetwebWSEngine() = default;
42
43 UInt_t GetId() const override { return TString::Hash((void *)&fWSconn, sizeof(void *)); }
44
45 void ClearHandle(Bool_t terminate) override
46 {
47 if (fWSconn && terminate)
49 fWSconn = nullptr;
50 }
51
52 void Send(const void *buf, int len) override
53 {
54 if (fWSconn)
56 }
57
58 /////////////////////////////////////////////////////////
59 /// Special method to send binary data with text header
60 /// For normal websocket it is two separated operation, for other engines could be combined together,
61 /// but emulates as two messages on client side
62 void SendHeader(const char *hdr, const void *buf, int len) override
63 {
64 if (fWSconn) {
67 }
68 }
69
70 void SendCharStar(const char *str) override
71 {
72 if (fWSconn)
74 }
75};
76
77//////////////////////////////////////////////////////////////////////////
78
79int websocket_connect_handler(const struct mg_connection *conn, void *)
80{
81 const struct mg_request_info *request_info = mg_get_request_info(conn);
82 if (!request_info)
83 return 1;
84
85 TCivetweb *engine = (TCivetweb *)request_info->user_data;
86 if (!engine || engine->IsTerminating())
87 return 1;
88 THttpServer *serv = engine->GetServer();
89 if (!serv)
90 return 1;
91
92 auto arg = std::make_shared<THttpCallArg>();
93 arg->SetPathAndFileName(request_info->local_uri); // path and file name
94 arg->SetQuery(request_info->query_string); // query arguments
95 arg->SetWSId(TString::Hash((void *)&conn, sizeof(void *)));
96 arg->SetMethod("WS_CONNECT");
97
98 Bool_t execres = serv->ExecuteWS(arg, kTRUE, kTRUE);
99
100 return execres && !arg->Is404() ? 0 : 1;
101}
102
103//////////////////////////////////////////////////////////////////////////
104
105void websocket_ready_handler(struct mg_connection *conn, void *)
106{
107 const struct mg_request_info *request_info = mg_get_request_info(conn);
108
109 TCivetweb *engine = (TCivetweb *)request_info->user_data;
110 if (!engine || engine->IsTerminating())
111 return;
112 THttpServer *serv = engine->GetServer();
113 if (!serv)
114 return;
115
116 auto arg = std::make_shared<THttpCallArg>();
117 arg->SetPathAndFileName(request_info->local_uri); // path and file name
118 arg->SetQuery(request_info->query_string); // query arguments
119 arg->SetMethod("WS_READY");
120
121 // delegate ownership to the arg, id will be automatically set
122 arg->CreateWSEngine<TCivetwebWSEngine>(conn);
123
124 serv->ExecuteWS(arg, kTRUE, kTRUE);
125}
126
127
128//////////////////////////////////////////////////////////////////////////
129
130void websocket_close_handler(const struct mg_connection *conn, void *)
131{
132 const struct mg_request_info *request_info = mg_get_request_info(conn);
133
134 // check if connection was already closed
135 if (mg_get_user_connection_data(conn) == (void *) conn)
136 return;
137
138 TCivetweb *engine = (TCivetweb *)request_info->user_data;
139 if (!engine || engine->IsTerminating())
140 return;
141 THttpServer *serv = engine->GetServer();
142 if (!serv)
143 return;
144
145 auto arg = std::make_shared<THttpCallArg>();
146 arg->SetPathAndFileName(request_info->local_uri); // path and file name
147 arg->SetQuery(request_info->query_string); // query arguments
148 arg->SetWSId(TString::Hash((void *)&conn, sizeof(void *)));
149 arg->SetMethod("WS_CLOSE");
150
151 serv->ExecuteWS(arg, kTRUE, kFALSE); // do not wait for result of execution
152}
153
154//////////////////////////////////////////////////////////////////////////
155
156int websocket_data_handler(struct mg_connection *conn, int code, char *data, size_t len, void *)
157{
158 const struct mg_request_info *request_info = mg_get_request_info(conn);
159
160 // check if connection data set to connection itself - means connection was closed already
161 std::string *conn_data = (std::string *) mg_get_user_connection_data(conn);
162 if ((void *) conn_data == (void *) conn)
163 return 1;
164
165 // see https://datatracker.ietf.org/doc/html/rfc6455#section-5.2
166 int fin = code & 0x80, opcode = code & 0x0F;
167
168 // recognized operation codes, all other should fails
169 enum { OP_CONTINUE = 0, OP_TEXT = 1, OP_BINARY = 2, OP_CLOSE = 8 };
170
171 // close when normal close is detected
172 if (fin && (opcode == OP_CLOSE)) {
173 if (conn_data) delete conn_data;
174 websocket_close_handler(conn, nullptr);
175 mg_set_user_connection_data(conn, conn); // mark connection as closed
176 return 1;
177 }
178
179 // ignore empty data
180 if (len == 0)
181 return 1;
182
183 // close connection when unrecognized opcode is detected
184 if ((opcode != OP_CONTINUE) && (opcode != OP_TEXT) && (opcode != OP_BINARY)) {
185 if (conn_data) delete conn_data;
186 websocket_close_handler(conn, nullptr);
187 mg_set_user_connection_data(conn, conn); // mark connection as closed
188 return 1;
189 }
190
191 TCivetweb *engine = (TCivetweb *)request_info->user_data;
192 if (!engine || engine->IsTerminating())
193 return 1;
194 THttpServer *serv = engine->GetServer();
195 if (!serv)
196 return 1;
197
198 // this is continuation of the request
199 if (!fin) {
200 if (!conn_data) {
201 conn_data = new std::string(data,len);
203 } else {
204 conn_data->append(data,len);
205 }
206 return 1;
207 }
208
209 auto arg = std::make_shared<THttpCallArg>();
210 arg->SetPathAndFileName(request_info->local_uri); // path and file name
211 arg->SetQuery(request_info->query_string); // query arguments
212 arg->SetWSId(TString::Hash((void *)&conn, sizeof(void *)));
213 arg->SetMethod("WS_DATA");
214
215 if (conn_data) {
216 mg_set_user_connection_data(conn, nullptr);
217 conn_data->append(data,len);
218 arg->SetPostData(std::move(*conn_data));
219 delete conn_data;
220 } else {
221 arg->SetPostData(std::string(data,len));
222 }
223
224 serv->ExecuteWS(arg, kTRUE, kTRUE);
225
226 return 1;
227}
228
229
230//////////////////////////////////////////////////////////////////////////
231
232static int log_message_handler(const struct mg_connection *conn, const char *message)
233{
234 const struct mg_context *ctx = mg_get_context(conn);
235
236 TCivetweb *engine = (TCivetweb *)mg_get_user_data(ctx);
237
238 if (engine)
239 return engine->ProcessLog(message);
240
241 // provide debug output
242 if ((gDebug > 0) || (strstr(message, "cannot bind to") != 0))
243 fprintf(stderr, "Error in <TCivetweb::Log> %s\n", message);
244
245 return 0;
246}
247
248//////////////////////////////////////////////////////////////////////////
249
250static int begin_request_handler(struct mg_connection *conn, void *)
251{
252 const struct mg_request_info *request_info = mg_get_request_info(conn);
253
254 TCivetweb *engine = (TCivetweb *)request_info->user_data;
255 if (!engine || engine->IsTerminating())
256 return 0;
257 THttpServer *serv = engine->GetServer();
258 if (!serv)
259 return 0;
260
261 auto arg = std::make_shared<THttpCallArg>();
262
264
265 Bool_t execres = kTRUE, debug = engine->IsDebugMode();
266
267 if (!debug && serv->IsFileRequested(request_info->local_uri, filename)) {
268 if ((filename.Length() > 3) && ((filename.Index(".js") != kNPOS) || (filename.Index(".css") != kNPOS))) {
269 std::string buf = THttpServer::ReadFileContent(filename.Data());
270 if (buf.empty()) {
271 arg->Set404();
272 } else {
273 arg->SetContentType(THttpServer::GetMimeType(filename.Data()));
274 arg->SetContent(std::move(buf));
275 if (engine->GetMaxAge() > 0)
276 arg->AddHeader("Cache-Control", TString::Format("max-age=%d", engine->GetMaxAge()));
277 else
278 arg->AddNoCacheHeader();
279 arg->SetZipping();
280 }
281 } else {
282 arg->SetFile(filename.Data());
283 }
284 } else {
285 arg->SetPathAndFileName(request_info->local_uri); // path and file name
286 arg->SetQuery(request_info->query_string); // query arguments
287 arg->SetTopName(engine->GetTopName());
288 arg->SetMethod(request_info->request_method); // method like GET or POST
289 if (request_info->remote_user)
290 arg->SetUserName(request_info->remote_user);
291
292 TString header;
293 for (int n = 0; n < request_info->num_headers; n++)
294 header.Append(
295 TString::Format("%s: %s\r\n", request_info->http_headers[n].name, request_info->http_headers[n].value));
296 arg->SetRequestHeader(header);
297
298 const char *len = mg_get_header(conn, "Content-Length");
299 Int_t ilen = len ? TString(len).Atoi() : 0;
300
301 if (ilen > 0) {
302 std::string buf;
303 buf.resize(ilen);
304 Int_t iread = mg_read(conn, (void *) buf.data(), ilen);
305 if (iread == ilen)
306 arg->SetPostData(std::move(buf));
307 }
308
309 if (debug) {
310 TString cont;
311 cont.Append("<title>Civetweb echo</title>");
312 cont.Append("<h1>Civetweb echo</h1>\n");
313
314 static int count = 0;
315
316 cont.Append(TString::Format("Request %d:<br/>\n<pre>\n", ++count));
317 cont.Append(TString::Format(" Method : %s\n", arg->GetMethod()));
318 cont.Append(TString::Format(" PathName : %s\n", arg->GetPathName()));
319 cont.Append(TString::Format(" FileName : %s\n", arg->GetFileName()));
320 cont.Append(TString::Format(" Query : %s\n", arg->GetQuery()));
321 cont.Append(TString::Format(" PostData : %ld\n", arg->GetPostDataLength()));
322 if (arg->GetUserName())
323 cont.Append(TString::Format(" User : %s\n", arg->GetUserName()));
324
325 cont.Append("</pre><p>\n");
326
327 cont.Append("Environment:<br/>\n<pre>\n");
328 for (int n = 0; n < request_info->num_headers; n++)
329 cont.Append(
330 TString::Format(" %s = %s\n", request_info->http_headers[n].name, request_info->http_headers[n].value));
331 cont.Append("</pre><p>\n");
332
333 arg->SetContentType("text/html");
334
335 arg->SetContent(cont);
336
337 } else {
338 execres = serv->ExecuteHttp(arg);
339 }
340 }
341
342 if (!execres || arg->Is404()) {
343 std::string hdr = arg->FillHttpHeader("HTTP/1.1");
344 mg_printf(conn, "%s", hdr.c_str());
345 } else if (arg->IsFile()) {
346 filename = (const char *)arg->GetContent();
347#ifdef _MSC_VER
348 if (engine->IsWinSymLinks()) {
349 // resolve Windows links which are not supported by civetweb
350 auto hFile = CreateFile(filename.Data(), // file to open
351 GENERIC_READ, // open for reading
352 FILE_SHARE_READ, // share for reading
353 NULL, // default security
354 OPEN_EXISTING, // existing file only
355 FILE_ATTRIBUTE_NORMAL, // normal file
356 NULL); // no attr. template
357
358 if( hFile != INVALID_HANDLE_VALUE) {
359 const int BUFSIZE = 2048;
360 TCHAR Path[BUFSIZE];
361 auto dwRet = GetFinalPathNameByHandle( hFile, Path, BUFSIZE, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS );
362 // produced file name may include \\?\ symbols, which are indicating long file name
363 if(dwRet < BUFSIZE) {
364 if (dwRet > 4 && Path[0] == '\\' && Path[1] == '\\' && Path[2] == '?' && Path[3] == '\\')
365 filename = Path + 4;
366 else
367 filename = Path;
368 }
369 CloseHandle(hFile);
370 }
371 }
372#endif
373 const char *mime_type = THttpServer::GetMimeType(filename.Data());
374 if (mime_type)
375 mg_send_mime_file(conn, filename.Data(), mime_type);
376 else
377 mg_send_file(conn, filename.Data());
378 } else {
379
380 Bool_t dozip = kFALSE;
381 switch (arg->GetZipping()) {
382 case THttpCallArg::kNoZip: dozip = kFALSE; break;
384 if (arg->GetContentLength() < 10000) break;
386 // check if request header has Accept-Encoding
387 for (int n = 0; n < request_info->num_headers; n++) {
388 TString name = request_info->http_headers[n].name;
389 if (name.Index("Accept-Encoding", 0, TString::kIgnoreCase) != 0)
390 continue;
391 TString value = request_info->http_headers[n].value;
392 dozip = (value.Index("gzip", 0, TString::kIgnoreCase) != kNPOS);
393 break;
394 }
395
396 break;
397 case THttpCallArg::kZipAlways: dozip = kTRUE; break;
398 }
399
400 if (dozip)
401 arg->CompressWithGzip();
402
403 std::string hdr = arg->FillHttpHeader("HTTP/1.1");
404 mg_printf(conn, "%s", hdr.c_str());
405
406 if (arg->GetContentLength() > 0)
407 mg_write(conn, arg->GetContent(), (size_t)arg->GetContentLength());
408 }
409
410 // Returning non-zero tells civetweb that our function has replied to
411 // the client, and civetweb should not send client any more data.
412 return 1;
413}
414
415/** \class TCivetweb
416\ingroup http
417
418THttpEngine implementation, based on civetweb embedded server
419
420It is default kind of engine, created for THttpServer
421Currently v1.15 from https://github.com/civetweb/civetweb is used
422
423Additional options can be specified:
424
425 top=foldername - name of top folder, seen in the browser
426 thrds=N - use N threads to run civetweb server (default 5)
427 auth_file - global authentication file
428 auth_domain - domain name, used for authentication
429
430Example:
431
432 new THttpServer("http:8080?top=MyApp&thrds=3");
433
434For the full list of supported options see TCivetweb::Create() documentation
435
436When `auth_file` and `auth_domain` parameters are specified, access
437to running http server will be possible only after user
438authentication, using so-call digest method. To generate
439authentication file, htdigest routine should be used:
440
441 [shell] htdigest -c .htdigest domain_name user
442
443When creating server, parameters should be:
444
445 auto serv = new THttpServer("http:8080?auth_file=.htdigets&auth_domain=domain_name");
446
447*/
448
449////////////////////////////////////////////////////////////////////////////////
450/// constructor
451
453 : THttpEngine("civetweb", "compact embedded http server"),
454 fOnlySecured(only_secured)
455{
456}
457
458////////////////////////////////////////////////////////////////////////////////
459/// destructor
460
462{
463 if (fCtx && !fTerminating)
464 mg_stop(fCtx);
465}
466
467////////////////////////////////////////////////////////////////////////////////
468/// process civetweb log message, can be used to detect critical errors
469
470Int_t TCivetweb::ProcessLog(const char *message)
471{
472 if ((gDebug > 0) || (strstr(message, "cannot bind to") != 0))
473 Error("Log", "%s", message);
474
475 return 0;
476}
477
478////////////////////////////////////////////////////////////////////////////////
479/// Creates embedded civetweb server
480///
481/// @param args string with civetweb server configuration
482///
483/// As main argument, http port should be specified like "8090".
484/// Or one can provide combination of ipaddress and portnumber like "127.0.0.1:8090"
485/// Or one can specify unix socket name like "x/tmp/root.socket"
486/// Extra parameters like in URL string could be specified after '?' mark:
487///
488/// thrds=N - there N is number of threads used by the civetweb (default is 10)
489/// top=name - configure top name, visible in the web browser
490/// ssl_certificate=filename - SSL certificate, see docs/OpenSSL.md from civetweb
491/// auth_file=filename - authentication file name, created with htdigets utility
492/// auth_domain=domain - authentication domain
493/// websocket_timeout=tm - set web sockets timeout in seconds (default 300)
494/// websocket_disable - disable web sockets handling (default enabled)
495/// bind - ip address to bind server socket
496/// loopback - bind specified port to loopback 127.0.0.1 address
497/// debug - enable debug mode, server always returns html page with request info
498/// log=filename - configure civetweb log file
499/// max_age=value - configures "Cache-Control: max_age=value" http header for all file-related requests, default 3600
500/// socket_mode=value - configures unix socket mode, default is 0700
501/// nocache - try to fully disable cache control for file requests
502/// winsymlinks=no - do not resolve symbolic links on file system (Windows only), default true
503/// dirlisting=no - enable/disable directory listing for browsing filesystem (default no)
504///
505/// Examples of valid args values:
506///
507/// serv->CreateEngine("http:8080?websocket_disable");
508/// serv->CreateEngine("http:7546?thrds=30&websocket_timeout=20");
509
510Bool_t TCivetweb::Create(const char *args)
511{
512 memset(&fCallbacks, 0, sizeof(struct mg_callbacks));
513 // fCallbacks.begin_request = begin_request_handler;
515 TString sport = IsSecured() ? "8480s" : "8080",
516 num_threads = "10",
517 websocket_timeout = "300000",
518 dir_listening = "no",
519 auth_file,
520 auth_domain,
521 log_file,
522 ssl_cert,
523 max_age;
524 Int_t socket_mode = 0700;
525 bool use_ws = kTRUE, is_socket = false;
526
527 // extract arguments
528 if (args && *args) {
529
530 // first extract port number
531 sport = "";
532
533 is_socket = *args == 'x';
534
535 while ((*args != 0) && (*args != '?') && (is_socket || (*args != '/')))
536 sport.Append(*args++);
537 if (IsSecured() && (sport.Index("s") == kNPOS) && !is_socket)
538 sport.Append("s");
539
540 // than search for extra parameters
541 while ((*args != 0) && (*args != '?'))
542 args++;
543
544 if (*args == '?') {
545 TUrl url(TString::Format("http://localhost/folder%s", args));
546
547 if (url.IsValid()) {
548 url.ParseOptions();
549
550 const char *top = url.GetValueFromOptions("top");
551 if (top)
552 fTopName = top;
553
554 const char *log = url.GetValueFromOptions("log");
555 if (log)
556 log_file = log;
557
558 Int_t thrds = url.GetIntValueFromOptions("thrds");
559 if (thrds > 0)
560 num_threads.Form("%d", thrds);
561
562 const char *afile = url.GetValueFromOptions("auth_file");
563 if (afile)
564 auth_file = afile;
565
566 const char *adomain = url.GetValueFromOptions("auth_domain");
567 if (adomain)
568 auth_domain = adomain;
569
570 const char *sslc = url.GetValueFromOptions("ssl_cert");
571 if (sslc)
572 ssl_cert = sslc;
573
574 Int_t wtmout = url.GetIntValueFromOptions("websocket_timeout");
575 if (wtmout > 0) {
576 websocket_timeout.Format("%d", wtmout * 1000);
577 use_ws = kTRUE;
578 }
579
580 if (url.HasOption("websocket_disable"))
581 use_ws = kFALSE;
582
583 if (url.HasOption("debug"))
584 fDebug = kTRUE;
585
586 const char *winsymlinks = url.GetValueFromOptions("winsymlinks");
587 if (winsymlinks)
588 fWinSymLinks = strcmp(winsymlinks,"no") != 0;
589
590 const char *dls = url.GetValueFromOptions("dirlisting");
591 if (dls && (!strcmp(dls,"no") || !strcmp(dls,"yes")))
592 dir_listening = dls;
593
594 const char *smode = url.GetValueFromOptions("socket_mode");
595 if (smode)
596 socket_mode = std::stoi(smode, nullptr, *smode=='0' ? 8 : 10);
597
598 if (url.HasOption("loopback") && (sport.Index(":") == kNPOS))
599 sport = TString("127.0.0.1:") + sport;
600
601 if (url.HasOption("bind") && (sport.Index(":") == kNPOS)) {
602 const char *addr = url.GetValueFromOptions("bind");
603 if (addr && strlen(addr))
604 sport = TString(addr) + ":" + sport;
605 }
606
607 if (GetServer() && url.HasOption("cors")) {
608 const char *cors = url.GetValueFromOptions("cors");
609 GetServer()->SetCors(cors && *cors ? cors : "*");
610 }
611
612 if (url.HasOption("nocache"))
613 fMaxAge = 0;
614
615 if (url.HasOption("max_age"))
616 fMaxAge = url.GetIntValueFromOptions("max_age");
617
618 max_age.Form("%d", fMaxAge);
619 }
620 }
621 }
622
623 const char *options[25];
624 int op = 0;
625
626 Info("Create", "Starting HTTP server on port %s", sport.Data());
627
628 options[op++] = "listening_ports";
629 options[op++] = sport.Data();
630 options[op++] = "num_threads";
631 options[op++] = num_threads.Data();
632
633 if (use_ws) {
634 options[op++] = "websocket_timeout_ms";
635 options[op++] = websocket_timeout.Data();
636 }
637
638 if ((auth_file.Length() > 0) && (auth_domain.Length() > 0)) {
639 options[op++] = "global_auth_file";
640 options[op++] = auth_file.Data();
641 options[op++] = "authentication_domain";
642 options[op++] = auth_domain.Data();
643 } else {
644 options[op++] = "enable_auth_domain_check";
645 options[op++] = "no";
646 }
647
648 if (log_file.Length() > 0) {
649 options[op++] = "error_log_file";
650 options[op++] = log_file.Data();
651 }
652
653 if (ssl_cert.Length() > 0) {
654 options[op++] = "ssl_certificate";
655 options[op++] = ssl_cert.Data();
656 } else if (IsSecured()) {
657 Error("Create", "No SSL certificate file configured");
658 }
659
660 if (max_age.Length() > 0) {
661 options[op++] = "static_file_max_age";
662 options[op++] = max_age.Data();
663 }
664
665 options[op++] = "enable_directory_listing";
666 options[op++] = dir_listening.Data();
667
668 options[op++] = nullptr;
669
670 // try to remove socket file - if any
671 if (is_socket && !sport.Contains(","))
672 gSystem->Unlink(sport.Data()+1);
673
674 // Start the web server.
675 fCtx = mg_start(&fCallbacks, this, options);
676
677 if (!fCtx)
678 return kFALSE;
679
681
682 if (use_ws)
685
686 // try to remove socket file - if any
687 if (is_socket && !sport.Contains(","))
688 gSystem->Chmod(sport.Data()+1, socket_mode);
689
690 return kTRUE;
691}
bool Bool_t
Definition RtypesCore.h:63
int Int_t
Definition RtypesCore.h:45
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
constexpr Ssiz_t kNPOS
Definition RtypesCore.h:124
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
int websocket_connect_handler(const struct mg_connection *conn, void *)
Definition TCivetweb.cxx:79
static int begin_request_handler(struct mg_connection *conn, void *)
static int log_message_handler(const struct mg_connection *conn, const char *message)
int websocket_data_handler(struct mg_connection *conn, int code, char *data, size_t len, void *)
void websocket_close_handler(const struct mg_connection *conn, void *)
void websocket_ready_handler(struct mg_connection *conn, void *)
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
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 TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
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 TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
char name[80]
Definition TGX11.cxx:110
#define INVALID_HANDLE_VALUE
Definition TMapFile.cxx:84
Int_t gDebug
Definition TROOT.cxx:585
R__EXTERN TSystem * gSystem
Definition TSystem.h:560
#define BUFSIZE
const char * mime_type
Definition civetweb.c:8026
int mg_printf(struct mg_connection *conn, const char *fmt,...)
Definition civetweb.c:6935
void mg_send_file(struct mg_connection *conn, const char *path)
Definition civetweb.c:10192
struct mg_context * mg_start(const struct mg_callbacks *callbacks, void *user_data, const char **options)
Definition civetweb.c:20251
void mg_set_websocket_handler(struct mg_context *ctx, const char *uri, mg_websocket_connect_handler connect_handler, mg_websocket_ready_handler ready_handler, mg_websocket_data_handler data_handler, mg_websocket_close_handler close_handler, void *cbdata)
Definition civetweb.c:13771
void mg_send_mime_file(struct mg_connection *conn, const char *path, const char *mime_type)
Definition civetweb.c:10199
const char * mg_get_header(const struct mg_connection *conn, const char *name)
Definition civetweb.c:3800
int mg_write(struct mg_connection *conn, const void *buf, size_t len)
Definition civetweb.c:6694
const struct mg_request_info * mg_get_request_info(const struct mg_connection *conn)
Definition civetweb.c:3486
void mg_set_user_connection_data(const struct mg_connection *const_conn, void *data)
Definition civetweb.c:3188
void * mg_get_user_connection_data(const struct mg_connection *conn)
Definition civetweb.c:3201
int mg_read(struct mg_connection *conn, void *buf, size_t len)
Definition civetweb.c:6586
void mg_set_request_handler(struct mg_context *ctx, const char *uri, mg_request_handler handler, void *cbdata)
Definition civetweb.c:13749
struct mg_context * mg_get_context(const struct mg_connection *conn)
Definition civetweb.c:3151
void mg_stop(struct mg_context *ctx)
Definition civetweb.c:19460
void * mg_get_user_data(const struct mg_context *ctx)
Definition civetweb.c:3158
int mg_websocket_write(struct mg_connection *conn, int opcode, const char *data, size_t data_len)
@ MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE
Definition civetweb.h:861
@ MG_WEBSOCKET_OPCODE_BINARY
Definition civetweb.h:860
@ MG_WEBSOCKET_OPCODE_TEXT
Definition civetweb.h:859
TCivetwebWSEngine.
Definition TCivetweb.cxx:31
struct mg_connection * fWSconn
Definition TCivetweb.cxx:33
UInt_t GetId() const override
Definition TCivetweb.cxx:43
void SendCharStar(const char *str) override
Envelope for sending string via the websocket.
Definition TCivetweb.cxx:70
void ClearHandle(Bool_t terminate) override
Definition TCivetweb.cxx:45
Bool_t SupportSendThrd() const override
True websocket requires extra thread to parallelize sending.
Definition TCivetweb.cxx:36
void SendHeader(const char *hdr, const void *buf, int len) override
Special method to send binary data with text header For normal websocket it is two separated operatio...
Definition TCivetweb.cxx:62
void Send(const void *buf, int len) override
Definition TCivetweb.cxx:52
virtual ~TCivetwebWSEngine()=default
TCivetwebWSEngine(struct mg_connection *conn)
Definition TCivetweb.cxx:39
THttpEngine implementation, based on civetweb embedded server.
Definition TCivetweb.h:19
struct mg_context * fCtx
! civetweb context
Definition TCivetweb.h:21
Bool_t fWinSymLinks
! resolve symbolic links on Windows
Definition TCivetweb.h:28
Bool_t IsTerminating() const
Definition TCivetweb.h:44
Int_t GetMaxAge() const
Definition TCivetweb.h:50
const char * GetTopName() const
Definition TCivetweb.h:40
TCivetweb(Bool_t only_secured=kFALSE)
constructor
Int_t fMaxAge
! max-age parameter
Definition TCivetweb.h:27
Int_t ProcessLog(const char *message)
process civetweb log message, can be used to detect critical errors
TString fTopName
! name of top item
Definition TCivetweb.h:23
Bool_t fTerminating
! server doing shutdown and not react on requests
Definition TCivetweb.h:25
Bool_t Create(const char *args) override
Creates embedded civetweb server.
Bool_t IsSecured() const
Definition TCivetweb.h:32
Bool_t IsDebugMode() const
Definition TCivetweb.h:42
virtual ~TCivetweb()
destructor
Bool_t IsWinSymLinks() const
Definition TCivetweb.h:46
Bool_t fDebug
! debug mode
Definition TCivetweb.h:24
struct mg_callbacks fCallbacks
! call-back table for civetweb webserver
Definition TCivetweb.h:22
Abstract class for implementing http protocol for THttpServer.
Definition THttpEngine.h:19
THttpServer * GetServer() const
Returns pointer to THttpServer associated with engine.
Definition THttpEngine.h:40
Online http server for arbitrary ROOT application.
Definition THttpServer.h:31
Bool_t IsFileRequested(const char *uri, TString &res) const
Check if file is requested, thread safe.
Bool_t ExecuteWS(std::shared_ptr< THttpCallArg > &arg, Bool_t external_thrd=kFALSE, Bool_t wait_process=kFALSE)
Execute WS request.
Bool_t ExecuteHttp(std::shared_ptr< THttpCallArg > arg)
Execute HTTP request.
void SetCors(const std::string &domain="*")
Enable CORS header to ProcessRequests() responses Specified location (typically "*") add as "Access-C...
static char * ReadFileContent(const char *filename, Int_t &len)
Reads content of file from the disk.
static const char * GetMimeType(const char *path)
Guess mime type base on file extension.
Internal instance used to exchange WS functionality between THttpServer and THttpWSHandler.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:970
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:944
Basic string class.
Definition TString.h:139
Int_t Atoi() const
Return integer value of string.
Definition TString.cxx:1966
const char * Data() const
Definition TString.h:380
@ kIgnoreCase
Definition TString.h:279
UInt_t Hash(ECaseCompare cmp=kExact) const
Return hash value.
Definition TString.cxx:670
TString & Append(const char *cs)
Definition TString.h:576
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2356
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:636
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
virtual int Chmod(const char *file, UInt_t mode)
Set the file permission bits. Returns -1 in case or error, 0 otherwise.
Definition TSystem.cxx:1509
virtual int Unlink(const char *name)
Unlink, i.e.
Definition TSystem.cxx:1384
This class represents a WWW compatible URL.
Definition TUrl.h:33
const char * GetValueFromOptions(const char *key) const
Return a value for a given key from the URL options.
Definition TUrl.cxx:660
Bool_t IsValid() const
Definition TUrl.h:79
Int_t GetIntValueFromOptions(const char *key) const
Return a value for a given key from the URL options as an Int_t, a missing key returns -1.
Definition TUrl.cxx:672
void ParseOptions() const
Parse URL options into a key/value map.
Definition TUrl.cxx:626
Bool_t HasOption(const char *key) const
Returns true if the given key appears in the URL options list.
Definition TUrl.cxx:683
const Int_t n
Definition legend1.C:16
int(* log_message)(const struct mg_connection *, const char *message)
Definition civetweb.h:240
const char * value
Definition civetweb.h:145
const char * name
Definition civetweb.h:144
struct mg_header http_headers[(64)]
Definition civetweb.h:179
const char * local_uri
Definition civetweb.h:157
void * user_data
Definition civetweb.h:175
const char * request_method
Definition civetweb.h:151
const char * query_string
Definition civetweb.h:162
void * conn_data
Definition civetweb.h:176
const char * remote_user
Definition civetweb.h:164