36 buf->base = (
char*)
malloc(suggested_size);
37 buf->len = suggested_size;
50 LOG(
error) <<
"Error in write callback: " << uv_strerror(status);
66 if (nread == UV_EOF) {
67 LOG(detail) <<
"websocket_server_callback: communication with driver closed upon EOF";
72 LOG(
error) <<
"websocket_server_callback: Error while reading from websocket" << uv_strerror((
int)nread);
81 LOG(
error) <<
"Error while parsing request: " << err.what;
90 LOG(
error) <<
"uv_write error: " << uv_err_name(status);
129 float* positions = (
float*)
frame;
134 char isClicked = *
frame;
139 int movement = *
frame;
149 int lat = *((
int*)
frame);
150 lat = lat < 20 ? 20 : lat;
184 mServerContext{context}
191 throw WSError{400,
"Bad Request"};
197 if (
s !=
"/" &&
s !=
"/status") {
203void populateHeader(std::map<std::string, std::string>& headers, std::string_view
const& k, std::string_view
const&
v)
207 std::transform(kk.begin(), kk.end(), kk.begin(),
208 [](
unsigned char c) { return std::tolower(c); });
209 if (kk !=
"sec-websocket-accept" && kk !=
"sec-websocket-key") {
210 std::transform(vv.begin(), vv.end(), vv.begin(),
211 [](
unsigned char c) { return std::tolower(c); });
213 headers.insert(std::make_pair(kk, vv));
221 void* frame =
nullptr;
222 void* draw_data =
nullptr;
228 if (
renderer->gui->lastFrame ==
nullptr || frameLatency / 1000000 > 15) {
229 renderer->gui->plugin->pollGUIPreRender(
renderer->gui->window, (
float)frameLatency / 1000000000.0f);
233 draw_data =
renderer->gui->lastFrame;
239 std::vector<uv_buf_t> outputs;
246 if (frameLatency / 1000000 > 15) {
248 *(
renderer->gui->frameCost) = (frameEnd - frameStart) / 1000000.f;
249 *(
renderer->gui->frameLatency) = frameLatency / 1000000.f;
250 renderer->gui->frameLast = frameStart;
251 renderer->gui->lastFrame = draw_data;
263 if (
mHeaders[
"upgrade"] !=
"websocket") {
264 throw WSError{400,
"Bad Request: not a websocket upgrade"};
267 if (
mHeaders[
"connection"].find(
"upgrade") == std::string::npos) {
268 throw WSError{400,
"Bad Request: connection not for upgrade"};
270 if (
mHeaders[
"sec-websocket-protocol"] !=
"dpl") {
271 throw WSError{400,
"Bad Request: websocket protocol not \"dpl\"."};
273 if (
mHeaders.count(
"sec-websocket-key") == 0) {
274 throw WSError{400,
"Bad Request: sec-websocket-key missing"};
276 if (
mHeaders[
"sec-websocket-version"] !=
"13") {
277 throw WSError{400,
"Bad Request: wrong protocol version"};
280 LOG(
debug) <<
"Got upgrade request with nonce " <<
mHeaders[
"sec-websocket-key"].c_str();
284 uv_buf_t bfr = uv_buf_init(strdup(reply.data()), reply.size());
285 auto* info_req = (uv_write_t*)
malloc(
sizeof(uv_write_t));
303 mHandler = std::unique_ptr<WebSocketHandler>(statusHandler);
307 LOG(info) <<
"Connection not bound to a PID";
320 LOGP(warning,
"Connection not bound to a PID however {} is not set. Skipping.",
322 throw WSError{418,
"Remote GUI not enabled"};
336 LOG(
error) <<
"uv_write error: " << uv_err_name(status);
349 LOG(
error) <<
"uv_write error: " << uv_err_name(status);
353 auto*
buffers = (std::vector<uv_buf_t>*)
h->data;
365 uv_buf_t bfr = uv_buf_init(strdup(
message),
s);
366 auto* write_req = (uv_write_t*)
malloc(
sizeof(uv_write_t));
367 write_req->data = bfr.base;
373 if (outputs.empty()) {
376 auto* write_req = (uv_write_t*)
malloc(
sizeof(uv_write_t));
377 auto*
buffers =
new std::vector<uv_buf_t>;
386 static constexpr auto errorFMT =
"HTTP/1.1 {} {}\r\ncontent-type: text/plain\r\n\r\n{}: {}\r\n";
388 char* reply = strdup(
error.data());
389 uv_buf_t bfr = uv_buf_init(reply,
error.size());
390 auto* error_rep = (uv_write_t*)
malloc(
sizeof(uv_write_t));
391 error_rep->data = reply;
397 LOG(
debug) <<
"Closing websocket connection to server";
405 assert(context->client);
409 if (nread == UV_EOF) {
410 LOG(
debug) <<
"EOF received from server, closing.";
418 LOG(
error) <<
"Error while reading from websocket";
424 LOG(
debug) <<
"Data received from server";
429 LOG(
error) <<
"Error while parsing request: " << err.what;
435 : mNonce{
"dGhlIHNhbXBsZSBub25jZQ=="}
452 std::vector<std::pair<std::string, std::string>> headers = {
454 {{
"x-dpl-id"}, spec.
id},
455 {{
"x-dpl-name"}, spec.name}};
457 this->
write(handShakeString.c_str(), handShakeString.size());
462 if (
s !=
"HTTP/1.1") {
482 LOG(info) << k <<
": " <<
v;
489 if (
mHeaders[
"upgrade"] !=
"websocket") {
493 if (
mHeaders[
"connection"].find(
"upgrade") == std::string::npos) {
496 if (
mHeaders.count(
"sec-websocket-accept") == 0) {
501 if (
mHeaders[
"sec-websocket-accept"] != expectedAccept) {
502 throw runtime_error_f(R
"(Invalid accept received: "%s", expected "%s")", mHeaders["sec-websocket-accept"].c_str(), expectedAccept.c_str());
505 LOG(info) <<
"Correctly handshaken websocket connection.";
526 LOG(
error) <<
"uv_write error: " << uv_err_name(status);
532 if (context->buf.base) {
533 free(context->buf.base);
546 LOG(
error) <<
"uv_write error: " << uv_err_name(status);
550 constexpr size_t kMaxFreeChunks = 4;
551 for (
auto&
b : context->buffers) {
552 if (context->freeList &&
b.base && context->freeList->size() < kMaxFreeChunks) {
553 context->freeList->push_back(
b.base);
572 context->buf = uv_buf_init(strdup(
message),
s);
573 auto* write_req = (uv_write_t*)
malloc(
sizeof(uv_write_t));
574 write_req->data = context;
580 if (outputs.empty()) {
583 auto* write_req = (uv_write_t*)
malloc(
sizeof(uv_write_t));
585 context->buffers.swap(outputs);
586 write_req->data = context;
587 uv_write(write_req, (uv_stream_t*)
mStream, &context->buffers.at(0),
593 if (outputs.empty()) {
596 auto* write_req = (uv_write_t*)
malloc(
sizeof(uv_write_t));
598 context->buffers.swap(outputs);
599 context->freeList = &freeList;
600 write_req->data = context;
601 uv_write(write_req, (uv_stream_t*)
mStream, &context->buffers.at(0),
struct uv_handle_s uv_handle_t
configStandalone Light OpenGL display display_light Apply smoothing to points Enable Z buffer Highlight links Highlight seeds Highlight sector tracks Highlight final tracks Show individual Show related Highlight grid Show only individual collision Color clusters belonging to track objects Set line Enable drawing TPC data Enable drawing TOF data Enable drawing magnetic field Set field line step count Invert colors configStandalone Heavy OpenGL display display_heavy Show tracks with ITS contribution Show tracks with TOF contribution Enable propagation of loopers Show clusters at nominal x of pad row for early transformed data Split CE tracks when they cross the central Mark clusters Mark adjacent clusters Hide rejected tracks Apply filter on tracks to be displayed Separate increase X h renderer
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error s
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char Directory with events to Events directory is and not inside events Show standalone event Run event generator maximum time bin of continuous for triggered for automatic continuous for automatic continuous triggered uint64_t
char error[CURL_ERROR_SIZE]
Class for time synchronization of RawReader instances.
GLboolean GLboolean GLboolean b
GLuint GLsizei const GLchar * message
GLenum GLuint GLenum GLsizei const GLchar * buf
Defining ITS Vertex explicitly as messageable.
RuntimeErrorRef runtime_error(const char *)
void ws_handshake_done_callback(uv_write_t *h, int status)
void populateHeader(std::map< std::string, std::string > &headers, std::string_view const &k, std::string_view const &v)
void websocket_client_callback(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
void close_client_websocket(uv_handle_t *stream)
void encode_websocket_frames(std::vector< uv_buf_t > &outputs, char const *src, size_t size, WebSocketOpCode opcode, uint32_t mask)
void websocket_server_close_callback(uv_handle_t *handle)
Free any resource associated with the device - driver channel.
void ws_error_write_callback(uv_write_t *h, int status)
void parse_http_request(char *start, size_t size, HTTPParser *parser)
std::string encode_websocket_handshake_request(const char *endpoint, const char *protocol, int version, char const *nonce, std::vector< std::pair< std::string, std::string > > headers)
void ws_client_bulk_write_callback(uv_write_t *h, int status)
void decode_websocket(char *start, size_t size, WebSocketHandler &handler)
void ws_server_write_callback(uv_write_t *h, int status)
void remoteGuiCallback(uv_timer_s *ctx)
RuntimeError & error_from_ref(RuntimeErrorRef)
void ws_client_write_callback(uv_write_t *h, int status)
void ws_server_bulk_write_callback(uv_write_t *h, int status)
void websocket_server_callback(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
Actually replies to any incoming websocket stuff.
RuntimeErrorRef runtime_error_f(const char *,...)
std::string encode_websocket_handshake_reply(char const *nonce, const char *protocol)
std::string to_string(gsl::span< T, Size > span)
std::vector< char * > * freeList
std::vector< uv_buf_t > buffers
virtual void charIn(char key)=0
virtual void updateMousePos(float x, float y)=0
virtual void keyEvent(char key, bool down)=0
virtual void updateMouseWheel(int direction)=0
virtual void updateMouseButton(bool isClicked)=0
virtual void updateWindowSize(int x, int y)=0
std::string id
The id of the device, including time-pipelining and suffix.
Running state information of a given device.
Context for the client callbacks.
std::vector< StatusWebSocketHandler * > statusHandlers
std::vector< DeviceInfo > * infos
std::vector< DeviceControl > * controls
An handler for a websocket message stream.
DriverServerContext & mContext
void endChunk() override
Invoked whenever we have no more input to process.
void frame(char const *frame, size_t s) override
void beginChunk() override
Invoked before processing the next round of input.
void control(char const *frame, size_t s) override
FIXME: not implemented.
void headers(std::map< std::string, std::string > const &headers) override
Invoked when all the headers are received.
void beginFragmentation() override
FIXME: not implemented.
~GUIWebSocketHandler() override
void endFragmentation() override
FIXME: not implemented.
GUIWebSocketHandler(DriverServerContext &context, GuiRenderer *renderer)
std::set< GuiRenderer * > renderers
static std::string calculateAccept(const char *nonce)
Helper to calculate the reply to a nonce.
std::unique_ptr< WebSocketHandler > mHandler
void endHeaders() override
void replyVersion(std::string_view const &s) override
std::function< void()> mHandshake
std::atomic< bool > mHandshaken
void connect(ServiceRegistryRef ref, uv_stream_t *stream, std::function< void()> handshake, std::unique_ptr< WebSocketHandler > handler)
std::unique_ptr< DriverClientContext > mContext
void body(char *data, size_t s) override
Actual handling of WS frames happens inside here.
void replyCode(std::string_view const &s) override
void dumpHeaders()
Dump headers.
void write(char const *, size_t)
Helper to write a message to the server.
void header(std::string_view const &k, std::string_view const &v) override
std::map< std::string, std::string > mHeaders
void method(std::string_view const &s) override
void body(char *data, size_t s) override
Actual handling of WS frames happens inside here.
void header(std::string_view const &k, std::string_view const &v) override
WSDPLHandler(uv_stream_t *stream, DriverServerContext *context)
void endHeaders() override
DriverServerContext * mServerContext
void target(std::string_view const &s) override
std::unique_ptr< WebSocketHandler > mHandler
void write(char const *, size_t)
Helper to write a message to the associated client.
std::map< std::string, std::string > mHeaders
An handler for a websocket message stream.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"