+ // This is the AFBClient interface impl
+ int init(int port, char const *token);
+ int dispatch();
+
+ // WM API
+ int requestSurface(const char *label);
+ int activateSurface(const char *label);
+ int deactivateSurface(const char *label);
+ int endDraw(const char *label);
+
+ void set_event_handler(enum EventType et,
+ std::function<void(char const *label)> f);
+
+ Impl();
+ ~Impl();
+
+ struct afb_wsj1 *wsj1;
+ struct sd_event *loop;
+};
+
+AFBClient::Impl::Impl() : wsj1{}, loop{} { TRACE(); }
+
+AFBClient::Impl::~Impl() {
+ TRACE();
+ afb_wsj1_unref(wsj1);
+ sd_event_unref(loop);
+ loop = nullptr;
+}
+
+int AFBClient::Impl::init(int port, char const *token) {
+ TRACE();
+ char *uribuf = nullptr;
+ int rc = -1;
+
+ if (!token || strlen(token) > token_maxlen) {
+ fprintf(stderr, "Token is invalid\n");
+ rc = -EINVAL;
+ goto fail;
+ }
+
+ for (char const *p = token; *p; p++) {
+ if (!isalnum(*p)) {
+ fprintf(stderr, "Token is invalid\n");
+ rc = -EINVAL;
+ goto fail;
+ }
+ }
+
+ if (port < 1 && port > 0xffff) {
+ fprintf(stderr, "Port is invalid\n");
+ rc = -EINVAL;
+ goto fail;
+ }
+
+ /* get the default event loop */
+ rc = sd_event_default(&loop);
+ if (rc < 0) {
+ fprintf(stderr, "Connection to default event loop failed: %s\n",
+ strerror(-rc));
+ goto fail;
+ }
+
+ asprintf(&uribuf, "ws://localhost:%d/api?token=%s", port, token);
+
+ /* connect the websocket wsj1 to the uri given by the first argument */
+ wsj1 = afb_ws_client_connect_wsj1(loop, uribuf, &itf, nullptr);
+ if (wsj1 == nullptr) {
+ sd_event_unref(loop);
+ fprintf(stderr, "Connection to %s failed: %m\n", uribuf);
+ rc = -errno;
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ return rc;
+}
+
+int AFBClient::Impl::dispatch() {
+ std::lock_guard<std::recursive_mutex> guard(dispatch_mutex);
+ return sd_event_run(loop, 1);
+}
+
+int AFBClient::Impl::requestSurface(const char *label) {
+ TRACE();
+ json_object *jp = json_object_new_object();
+ json_object_object_add(jp, "drawing_name", json_object_new_string(label));
+ int rc = -1;