void
attachUiImpl_destroy(void)
{
    if (_attachUiImpl.core_connection != NULL) {
        core_connection_close(_attachUiImpl.core_connection);
        core_connection_free(_attachUiImpl.core_connection);
        _attachUiImpl.core_connection = NULL;
    }
}
void
clientfb_destroy(ClientFramebuffer* client_fb)
{
    if (client_fb != NULL && client_fb->core_connection != NULL) {
        // Disable the reader callback.
        qemu_set_fd_handler(client_fb->sock, NULL, NULL, NULL);

        // Close framebuffer connection.
        core_connection_close(client_fb->core_connection);
        core_connection_free(client_fb->core_connection);
        client_fb->core_connection = NULL;
    }
}
void
userEventsProxy_destroy(void)
{
    if (_userEventsProxy.sync_writer != NULL) {
        syncsocket_close(_userEventsProxy.sync_writer);
        syncsocket_free(_userEventsProxy.sync_writer);
        _userEventsProxy.sync_writer = NULL;
    }
    if (_userEventsProxy.core_connection != NULL) {
        core_connection_close(_userEventsProxy.core_connection);
        core_connection_free(_userEventsProxy.core_connection);
        _userEventsProxy.core_connection = NULL;
    }
}
/* Destroys CoreCmdProxy instance. */
void
coreCmdProxy_destroy(void)
{
    if (_coreCmdProxy.sync_writer != NULL) {
        syncsocket_close(_coreCmdProxy.sync_writer);
        syncsocket_free(_coreCmdProxy.sync_writer);
        _coreCmdProxy.sync_writer = NULL;
    }
    if (_coreCmdProxy.sync_reader != NULL) {
        syncsocket_close(_coreCmdProxy.sync_reader);
        syncsocket_free(_coreCmdProxy.sync_reader);
        _coreCmdProxy.sync_reader = NULL;
    }
    if (_coreCmdProxy.core_connection != NULL) {
        core_connection_close(_coreCmdProxy.core_connection);
        core_connection_free(_coreCmdProxy.core_connection);
        _coreCmdProxy.core_connection = NULL;
    }
}
ClientFramebuffer*
clientfb_create(SockAddress* console_socket,
                const char* protocol,
                QFrameBuffer* fb)
{
    char* connect_message = NULL;
    char switch_cmd[256];

    // Connect to the framebuffer service.
    _client_fb.core_connection = core_connection_create(console_socket);
    if (_client_fb.core_connection == NULL) {
        derror("Framebuffer client is unable to connect to the console: %s\n",
               errno_str);
        return NULL;
    }
    if (core_connection_open(_client_fb.core_connection)) {
        core_connection_free(_client_fb.core_connection);
        _client_fb.core_connection = NULL;
        derror("Framebuffer client is unable to open the console: %s\n",
               errno_str);
        return NULL;
    }
    snprintf(switch_cmd, sizeof(switch_cmd), "framebuffer %s", protocol);
    if (core_connection_switch_stream(_client_fb.core_connection, switch_cmd,
                                      &connect_message)) {
        derror("Unable to attach to the framebuffer %s: %s\n",
               switch_cmd, connect_message ? connect_message : "");
        if (connect_message != NULL) {
            free(connect_message);
        }
        core_connection_close(_client_fb.core_connection);
        core_connection_free(_client_fb.core_connection);
        _client_fb.core_connection = NULL;
        return NULL;
    }

    // We expect core framebuffer to return us bits per pixel property in
    // the handshake message.
    _client_fb.bits_per_pixel = 0;
    if (connect_message != NULL) {
        char* bpp = strstr(connect_message, "bitsperpixel=");
        if (bpp != NULL) {
            char* end;
            bpp += strlen("bitsperpixel=");
            end = strchr(bpp, ' ');
            if (end == NULL) {
                end = bpp + strlen(bpp);
            }
            _client_fb.bits_per_pixel = strtol(bpp, &end, 0);
        }
    }

    if (!_client_fb.bits_per_pixel) {
        derror("Unexpected core framebuffer reply: %s\n"
               "Bits per pixel property is not there, or is invalid\n", connect_message);
        core_connection_close(_client_fb.core_connection);
        core_connection_free(_client_fb.core_connection);
        _client_fb.core_connection = NULL;
        return NULL;
    }

    // Now that we're connected lets initialize the descriptor.
    _client_fb.fb = fb;
    _client_fb.sock = core_connection_get_socket(_client_fb.core_connection);
    _client_fb.fb_state = WAIT_HEADER;
    _client_fb.reader_buffer = (uint8_t*)&_client_fb.update_header;
    _client_fb.reader_offset = 0;
    _client_fb.reader_bytes = sizeof(FBUpdateMessage);

    if (connect_message != NULL) {
        free(connect_message);
    }

    // At last setup read callback, and start receiving the updates.
    if (qemu_set_fd_handler(_client_fb.sock, _clientfb_read_cb, NULL, &_client_fb)) {
        derror("Unable to set up framebuffer read callback\n");
        core_connection_close(_client_fb.core_connection);
        core_connection_free(_client_fb.core_connection);
        _client_fb.core_connection = NULL;
        return NULL;
    }
    {
        // Force the core to send us entire framebuffer now, when we're prepared
        // to receive it.
        FBRequestHeader hd;
        SyncSocket* sk = syncsocket_init(_client_fb.sock);

        hd.request_type = AFB_REQUEST_REFRESH;
        syncsocket_start_write(sk);
        syncsocket_write(sk, &hd, sizeof(hd), 500);
        syncsocket_stop_write(sk);
        syncsocket_free(sk);
    }
    fprintf(stdout, "Framebuffer %s is now attached to the core %s\n",
            protocol, sock_address_to_string(console_socket));

    return &_client_fb;
}