[Spice-devel] [spice-xpi 12/12] Add an abstract controller base class

Marc-André Lureau marcandre.lureau at gmail.com
Tue Mar 12 05:37:06 PDT 2013


after this patch:

"LoadPlugin: failed to initialize"..., 212LoadPlugin: failed to
initialize shared library
/home/elmarco/.mozilla/plugins/libnsISpicec.so
[/home/elmarco/.mozilla/plugins/libnsISpicec.so: undefined symbol:
_ZN19SpiceControllerUnix14GetClientPathsEPPPcS2_


On Tue, Mar 12, 2013 at 12:23 PM, Christophe Fergeau
<cfergeau at redhat.com> wrote:
> It contains all the generic code, then platform-specific controller
> implementations will inherit from it and overload the non-generic parts
> abstract methods.
> ---
>  SpiceXPI/src/plugin/Makefile.am         |   2 +
>  SpiceXPI/src/plugin/controller-unix.cpp | 209 +++-----------------------
>  SpiceXPI/src/plugin/controller-unix.h   |  96 ++++++++++++
>  SpiceXPI/src/plugin/controller.cpp      | 252 ++++++++++++++++++++++++++++++++
>  SpiceXPI/src/plugin/controller.h        |  27 ++--
>  SpiceXPI/src/plugin/plugin.cpp          |  22 +--
>  SpiceXPI/src/plugin/plugin.h            |   2 +-
>  7 files changed, 398 insertions(+), 212 deletions(-)
>  create mode 100644 SpiceXPI/src/plugin/controller-unix.h
>  create mode 100644 SpiceXPI/src/plugin/controller.cpp
>
> diff --git a/SpiceXPI/src/plugin/Makefile.am b/SpiceXPI/src/plugin/Makefile.am
> index 2f12e70..2db218e 100644
> --- a/SpiceXPI/src/plugin/Makefile.am
> +++ b/SpiceXPI/src/plugin/Makefile.am
> @@ -26,8 +26,10 @@ libnsISpicec_la_SOURCES =                    \
>         $(top_srcdir)/common/rederrorcodes.h    \
>         glib-compat.c                           \
>         glib-compat.h                           \
> +       controller.cpp                          \
>         controller.h                            \
>         controller-unix.cpp                     \
> +       controller-unix.h                       \
>         npapi/npapi.h                           \
>         npapi/npfunctions.h                     \
>         npapi/npruntime.h                       \
> diff --git a/SpiceXPI/src/plugin/controller-unix.cpp b/SpiceXPI/src/plugin/controller-unix.cpp
> index ddbd8c0..b3bd832 100644
> --- a/SpiceXPI/src/plugin/controller-unix.cpp
> +++ b/SpiceXPI/src/plugin/controller-unix.cpp
> @@ -41,6 +41,7 @@
>   *   the terms of any one of the MPL, the GPL or the LGPL.
>   *
>   * ***** END LICENSE BLOCK ***** */
> +#include "config.h"
>
>  #include <cstdio>
>  #include <cstdlib>
> @@ -58,11 +59,11 @@ extern "C" {
>  }
>
>  #include "rederrorcodes.h"
> -#include "controller.h"
> +#include "controller-unix.h"
>  #include "plugin.h"
>
> -SpiceController::SpiceController(nsPluginInstance *aPlugin):
> -    m_plugin(aPlugin),
> +SpiceControllerUnix::SpiceControllerUnix(nsPluginInstance *aPlugin):
> +    SpiceController(aPlugin),
>      m_client_socket(-1)
>  {
>      // create temporary directory in /tmp
> @@ -70,7 +71,7 @@ SpiceController::SpiceController(nsPluginInstance *aPlugin):
>      m_tmp_dir = mkdtemp(tmp_dir);
>  }
>
> -SpiceController::~SpiceController()
> +SpiceControllerUnix::~SpiceControllerUnix()
>  {
>      g_debug(G_STRFUNC);
>      Disconnect();
> @@ -79,17 +80,7 @@ SpiceController::~SpiceController()
>      rmdir(m_tmp_dir.c_str());
>  }
>
> -void SpiceController::SetFilename(const std::string &name)
> -{
> -    m_name = name;
> -}
> -
> -void SpiceController::SetProxy(const std::string &proxy)
> -{
> -    m_proxy = proxy;
> -}
> -
> -int SpiceController::Connect()
> +int SpiceControllerUnix::Connect()
>  {
>      // check, if we have a filename for socket to create
>      if (m_name.empty())
> @@ -123,23 +114,11 @@ int SpiceController::Connect()
>      return rc;
>  }
>
> -int SpiceController::Connect(const int nRetries)
> +bool SpiceControllerUnix::CheckPipe()
>  {
> -    int rc = -1;
> -    int sleep_time = 0;
> -
> -    // try to connect for specified count
> -    for (int i = 0; rc != 0 && i < nRetries; ++i)
> -    {
> -        rc = Connect();
> -        g_usleep(sleep_time * G_USEC_PER_SEC);
> -        ++sleep_time;
> -    }
> -
> -    return rc;
>  }
>
> -void SpiceController::GetClientPaths(GStrv *client_argv, GStrv *fallback_argv)
> +void SpiceControllerUnixGetClientPaths(GStrv *client_argv, GStrv *fallback_argv)
>  {
>      if (client_argv != NULL) {
>          *client_argv = g_new0(char *, 2);
> @@ -153,7 +132,7 @@ void SpiceController::GetClientPaths(GStrv *client_argv, GStrv *fallback_argv)
>      }
>  }
>
> -void SpiceController::SetupControllerPipe(GStrv &env)
> +void SpiceControllerUnix::SetupControllerPipe(GStrv &env)
>  {
>      std::string socket_file(this->m_tmp_dir);
>      socket_file += "/spice-xpi";
> @@ -163,18 +142,13 @@ void SpiceController::SetupControllerPipe(GStrv &env)
>      env = g_environ_setenv(env, "SPICE_XPI_SOCKET", socket_file.c_str(), TRUE);
>  }
>
> -void SpiceController::Disconnect()
> +void SpiceControllerUnix::StopClient()
>  {
> -    // close the socket
> -    close(m_client_socket);
> -    m_client_socket = -1;
> -
> -    // delete the temporary file, which is used for the socket
> -    unlink(m_name.c_str());
> -    m_name.clear();
> +    if (m_pid_controller > 0)
> +        kill(-m_pid_controller, SIGTERM);
>  }
>
> -uint32_t SpiceController::Write(const void *lpBuffer, uint32_t nBytesToWrite)
> +uint32_t SpiceControllerUnix::Write(const void *lpBuffer, uint32_t nBytesToWrite)
>  {
>      ssize_t len = send(m_client_socket, lpBuffer, nBytesToWrite, 0);
>
> @@ -187,156 +161,13 @@ uint32_t SpiceController::Write(const void *lpBuffer, uint32_t nBytesToWrite)
>      return len;
>  }
>
> -void SpiceController::ChildExited(GPid pid, gint status, gpointer user_data)
> +void SpiceControllerUnix::Disconnect()
>  {
> -    SpiceController *fake_this = (SpiceController *)user_data;
> -
> -    g_message("Client with pid %p exited", pid);
> -
> -    g_main_loop_quit(fake_this->m_child_watch_mainloop);
> -    /* FIXME: we are not in the main thread!! */
> -    fake_this->m_plugin->OnSpiceClientExit(status);
> -}
> -
> -void SpiceController::WaitForPid(GPid pid)
> -{
> -    GMainContext *context;
> -    GSource *source;
> -
> -    context = g_main_context_new();
> -
> -    m_child_watch_mainloop = g_main_loop_new(context, FALSE);
> -    source = g_child_watch_source_new(pid);
> -    g_source_set_callback(source, (GSourceFunc)ChildExited, this, NULL);
> -    g_source_attach(source, context);
> -
> -    g_main_loop_run(m_child_watch_mainloop);
> -
> -    g_main_loop_unref(m_child_watch_mainloop);
> -    g_main_context_unref(context);
> -
> -    g_spawn_close_pid(pid);
> -    if (pid == m_pid_controller)
> -        m_pid_controller = 0;
> -}
> -
> -
> -gpointer SpiceController::ClientThread(gpointer data)
> -{
> -    SpiceController *fake_this = (SpiceController *)data;
> -    gchar **env = g_get_environ();
> -    GPid pid;
> -    gboolean spawned = FALSE;
> -    GError *error = NULL;
> -    GStrv client_argv;
> -    GStrv fallback_argv;
> -    fake_this->GetClientPaths(&client_argv, &fallback_argv);
> -
> -    {
> -        char *argv_str = g_strjoinv(" ", client_argv);
> -        g_warning("main client cmdline: %s", argv_str);
> -        g_free(argv_str);
> -        argv_str = g_strjoinv(" ", fallback_argv);
> -        g_warning("fallback client cmdline: %s", argv_str);
> -        g_free(argv_str);
> -    }
> -
> -    fake_this->SetupControllerPipe(env);
> -
> -    if (!fake_this->m_proxy.empty())
> -        env = g_environ_setenv(env, "SPICE_PROXY", fake_this->m_proxy.c_str(), TRUE);
> -
> -    if (client_argv != NULL) {
> -        spawned = g_spawn_async(NULL,
> -                                client_argv, env,
> -                                G_SPAWN_DO_NOT_REAP_CHILD,
> -                                NULL, NULL, /* child_func, child_arg */
> -                                &pid, &error);
> -        if (error != NULL) {
> -            g_warning("failed to start %s: %s", client_argv[0], error->message);
> -            g_warn_if_fail(spawned == FALSE);
> -            g_clear_error(&error);
> -        }
> -    }
> -    if (!spawned && (fallback_argv != NULL)) {
> -        // TODO: temporary fallback for backward compatibility
> -        g_message("failed to run preferred client, running fallback client instead");
> -        spawned = g_spawn_async(NULL, fallback_argv, env,
> -                                G_SPAWN_DO_NOT_REAP_CHILD,
> -                                NULL, NULL, /* child_func, child_arg */
> -                                &pid, &error);
> -        if (error != NULL) {
> -            g_warning("failed to start %s: %s", fallback_argv[0], error->message);
> -            g_warn_if_fail(spawned == FALSE);
> -            g_clear_error(&error);
> -        }
> -    }
> -    g_strfreev(env);
> -    g_strfreev(client_argv);
> -    g_strfreev(fallback_argv);
> -
> -    if (!spawned) {
> -        g_critical("ERROR failed to run spicec fallback");
> -        return NULL;
> -    }
> -
> -#ifdef XP_UNIX
> -    fake_this->m_pid_controller = pid;
> -#endif
> -    fake_this->WaitForPid(pid);
> -
> -    return NULL;
> -}
> -
> -bool SpiceController::StartClient()
> -{
> -    GThread *thread;
> -
> -    thread = g_thread_create(ClientThread, this, FALSE, NULL);
> -
> -    return (thread != NULL);
> -}
> -
> -void SpiceController::StopClient()
> -{
> -    if (m_pid_controller > 0)
> -        kill(-m_pid_controller, SIGTERM);
> -}
> -
> -int SpiceController::TranslateRC(int nRC)
> -{
> -    switch (nRC)
> -    {
> -    case SPICEC_ERROR_CODE_SUCCESS:
> -        return 0;
> -
> -    case SPICEC_ERROR_CODE_GETHOSTBYNAME_FAILED:
> -        return RDP_ERROR_CODE_HOST_NOT_FOUND;
> -
> -    case SPICEC_ERROR_CODE_CONNECT_FAILED:
> -        return RDP_ERROR_CODE_WINSOCK_CONNECT_FAILED;
> -
> -    case SPICEC_ERROR_CODE_ERROR:
> -    case SPICEC_ERROR_CODE_SOCKET_FAILED:
> -        return RDP_ERROR_CODE_INTERNAL_ERROR;
> -
> -    case SPICEC_ERROR_CODE_RECV_FAILED:
> -        return RDP_ERROR_RECV_WINSOCK_FAILED;
> -
> -    case SPICEC_ERROR_CODE_SEND_FAILED:
> -        return RDP_ERROR_SEND_WINSOCK_FAILED;
> -
> -    case SPICEC_ERROR_CODE_NOT_ENOUGH_MEMORY:
> -        return RDP_ERROR_CODE_OUT_OF_MEMORY;
> -
> -    case SPICEC_ERROR_CODE_AGENT_TIMEOUT:
> -        return RDP_ERROR_CODE_TIMEOUT;
> -
> -    case SPICEC_ERROR_CODE_AGENT_ERROR:
> -        return RDP_ERROR_CODE_INTERNAL_ERROR;
> +    // close the socket
> +    close(m_client_socket);
> +    m_client_socket = -1;
>
> -    default:
> -        return RDP_ERROR_CODE_INTERNAL_ERROR;
> -    }
> +    // delete the temporary file, which is used for the socket
> +    unlink(m_name.c_str());
> +    m_name.clear();
>  }
> -
> diff --git a/SpiceXPI/src/plugin/controller-unix.h b/SpiceXPI/src/plugin/controller-unix.h
> new file mode 100644
> index 0000000..e72663b
> --- /dev/null
> +++ b/SpiceXPI/src/plugin/controller-unix.h
> @@ -0,0 +1,96 @@
> +/* ***** BEGIN LICENSE BLOCK *****
> + *   Version: MPL 1.1/GPL 2.0/LGPL 2.1
> + *
> + *   The contents of this file are subject to the Mozilla Public License Version
> + *   1.1 (the "License"); you may not use this file except in compliance with
> + *   the License. You may obtain a copy of the License at
> + *   http://www.mozilla.org/MPL/
> + *
> + *   Software distributed under the License is distributed on an "AS IS" basis,
> + *   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
> + *   for the specific language governing rights and limitations under the
> + *   License.
> + *
> + *   Copyright 2009-2011, Red Hat Inc.
> + *   Copyright 2013, Red Hat Inc.
> + *   Based on mozilla.org's scriptable plugin example
> + *
> + *   The Original Code is mozilla.org code.
> + *
> + *   The Initial Developer of the Original Code is
> + *   Netscape Communications Corporation.
> + *   Portions created by the Initial Developer are Copyright (C) 1998
> + *   the Initial Developer. All Rights Reserved.
> + *
> + *   Contributor(s):
> + *   Uri Lublin
> + *   Martin Stransky
> + *   Peter Hatina
> + *   Christophe Fergeau
> + *
> + *   Alternatively, the contents of this file may be used under the terms of
> + *   either the GNU General Public License Version 2 or later (the "GPL"), or
> + *   the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
> + *   in which case the provisions of the GPL or the LGPL are applicable instead
> + *   of those above. If you wish to allow use of your version of this file only
> + *   under the terms of either the GPL or the LGPL, and not to allow others to
> + *   use your version of this file under the terms of the MPL, indicate your
> + *   decision by deleting the provisions above and replace them with the notice
> + *   and other provisions required by the GPL or the LGPL. If you do not delete
> + *   the provisions above, a recipient may use your version of this file under
> + *   the terms of any one of the MPL, the GPL or the LGPL.
> + *
> + * ***** END LICENSE BLOCK ***** */
> +
> +#ifndef SPICE_CONTROLLER_UNIX_H
> +#define SPICE_CONTROLLER_UNIX_H
> +
> +/*
> +    Basic assumption:
> +    ------------------
> +    Cross platform compatible.
> +    Easy to transform into remote process communication
> +    Secured
> +
> +    chosen:
> +        Unix - Unix Domain Sockets (easy to change into regular sockets for remote communication)
> +        Windows - Named pipe (which allows remote access and is duplex
> +            (rather than anonymous pipe which is local only and one way)
> +*/
> +
> +#include <glib.h>
> +#include <glib-object.h> /* for GStrv */
> +#include <gio/gio.h>
> +#include <string>
> +extern "C" {
> +#  include <stdint.h>
> +#  include <limits.h>
> +}
> +
> +#include <spice/controller_prot.h>
> +#include "controller.h"
> +
> +class nsPluginInstance;
> +
> +class SpiceControllerUnix: public SpiceController
> +{
> +public:
> +    SpiceControllerUnix(nsPluginInstance *aPlugin);
> +    virtual ~SpiceControllerUnix();
> +
> +    virtual void StopClient();
> +    virtual uint32_t Write(const void *lpBuffer, uint32_t nBytesToWrite);
> +    int Connect(int nRetries) { return SpiceController::Connect(nRetries); };
> +
> +private:
> +    virtual int Connect();
> +    virtual void Disconnect();
> +    virtual void SetupControllerPipe(GStrv &env);
> +    virtual bool CheckPipe();
> +    virtual void GetClientPaths(GStrv *client_argv, GStrv *fallback_argv);
> +
> +    int m_client_socket;
> +    std::string m_tmp_dir;
> +};
> +
> +#endif // SPICE_CONTROLLER_UNIX_H
> diff --git a/SpiceXPI/src/plugin/controller.cpp b/SpiceXPI/src/plugin/controller.cpp
> new file mode 100644
> index 0000000..6011f5d
> --- /dev/null
> +++ b/SpiceXPI/src/plugin/controller.cpp
> @@ -0,0 +1,252 @@
> +/* ***** BEGIN LICENSE BLOCK *****
> + *   Version: MPL 1.1/GPL 2.0/LGPL 2.1
> + *
> + *   The contents of this file are subject to the Mozilla Public License Version
> + *   1.1 (the "License"); you may not use this file except in compliance with
> + *   the License. You may obtain a copy of the License at
> + *   http://www.mozilla.org/MPL/
> + *
> + *   Software distributed under the License is distributed on an "AS IS" basis,
> + *   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
> + *   for the specific language governing rights and limitations under the
> + *   License.
> + *
> + *   Copyright 2009-2011, Red Hat Inc.
> + *   Copyright 2013, Red Hat Inc.
> + *   Based on mozilla.org's scriptable plugin example
> + *
> + *   The Original Code is mozilla.org code.
> + *
> + *   The Initial Developer of the Original Code is
> + *   Netscape Communications Corporation.
> + *   Portions created by the Initial Developer are Copyright (C) 1998
> + *   the Initial Developer. All Rights Reserved.
> + *
> + *   Contributor(s):
> + *   Uri Lublin
> + *   Martin Stransky
> + *   Peter Hatina
> + *   Christophe Fergeau
> + *
> + *   Alternatively, the contents of this file may be used under the terms of
> + *   either the GNU General Public License Version 2 or later (the "GPL"), or
> + *   the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
> + *   in which case the provisions of the GPL or the LGPL are applicable instead
> + *   of those above. If you wish to allow use of your version of this file only
> + *   under the terms of either the GPL or the LGPL, and not to allow others to
> + *   use your version of this file under the terms of the MPL, indicate your
> + *   decision by deleting the provisions above and replace them with the notice
> + *   and other provisions required by the GPL or the LGPL. If you do not delete
> + *   the provisions above, a recipient may use your version of this file under
> + *   the terms of any one of the MPL, the GPL or the LGPL.
> + *
> + * ***** END LICENSE BLOCK ***** */
> +
> +#include "config.h"
> +
> +#include <cstdio>
> +#include <cstdlib>
> +#include <cstring>
> +#include <cerrno>
> +#include <glib.h>
> +
> +#include "rederrorcodes.h"
> +#include "controller.h"
> +#include "plugin.h"
> +
> +SpiceController::SpiceController(nsPluginInstance *aPlugin):
> +    m_pid_controller(0),
> +    m_pipe(NULL),
> +    m_plugin(aPlugin),
> +    m_child_watch_mainloop(NULL)
> +{
> +}
> +
> +SpiceController::~SpiceController()
> +{
> +    g_debug(G_STRFUNC);
> +    Disconnect();
> +}
> +
> +void SpiceController::SetFilename(const std::string &name)
> +{
> +    m_name = name;
> +}
> +
> +void SpiceController::SetProxy(const std::string &proxy)
> +{
> +    m_proxy = proxy;
> +}
> +
> +#define FACILITY_SPICEX             50
> +#define FACILITY_CREATE_RED_PROCESS 51
> +#define FACILITY_STRING_OPERATION   52
> +#define FACILITY_CREATE_RED_EVENT   53
> +#define FACILITY_CREATE_RED_PIPE    54
> +#define FACILITY_PIPE_OPERATION     55
> +
> +int SpiceController::Connect(const int nRetries)
> +{
> +    int rc = -1;
> +    int sleep_time = 0;
> +
> +    // try to connect for specified count
> +    for (int i = 0; rc != 0 && i < nRetries; ++i)
> +    {
> +        rc = Connect();
> +        g_usleep(sleep_time * G_USEC_PER_SEC);
> +        ++sleep_time;
> +    }
> +
> +    return rc;
> +}
> +
> +void SpiceController::Disconnect()
> +{
> +}
> +
> +void SpiceController::ChildExited(GPid pid, gint status, gpointer user_data)
> +{
> +    SpiceController *fake_this = (SpiceController *)user_data;
> +
> +    g_message("Client with pid %p exited", pid);
> +
> +    g_main_loop_quit(fake_this->m_child_watch_mainloop);
> +    /* FIXME: we are not in the main thread!! */
> +    fake_this->m_plugin->OnSpiceClientExit(status);
> +}
> +
> +void SpiceController::WaitForPid(GPid pid)
> +{
> +    GMainContext *context;
> +    GSource *source;
> +
> +    context = g_main_context_new();
> +
> +    m_child_watch_mainloop = g_main_loop_new(context, FALSE);
> +    source = g_child_watch_source_new(pid);
> +    g_source_set_callback(source, (GSourceFunc)ChildExited, this, NULL);
> +    g_source_attach(source, context);
> +
> +    g_main_loop_run(m_child_watch_mainloop);
> +
> +    g_main_loop_unref(m_child_watch_mainloop);
> +    g_main_context_unref(context);
> +
> +    g_spawn_close_pid(pid);
> +    if (pid == m_pid_controller)
> +        m_pid_controller = 0;
> +}
> +
> +gpointer SpiceController::ClientThread(gpointer data)
> +{
> +    SpiceController *fake_this = (SpiceController *)data;
> +    gchar **env = g_get_environ();
> +    GPid pid;
> +    gboolean spawned = FALSE;
> +    GError *error = NULL;
> +    GStrv client_argv;
> +    GStrv fallback_argv;
> +    fake_this->GetClientPaths(&client_argv, &fallback_argv);
> +
> +    {
> +        char *argv_str = g_strjoinv(" ", client_argv);
> +        g_warning("main client cmdline: %s", argv_str);
> +        g_free(argv_str);
> +        argv_str = g_strjoinv(" ", fallback_argv);
> +        g_warning("fallback client cmdline: %s", argv_str);
> +        g_free(argv_str);
> +    }
> +
> +    fake_this->SetupControllerPipe(env);
> +
> +    if (!fake_this->m_proxy.empty())
> +        env = g_environ_setenv(env, "SPICE_PROXY", fake_this->m_proxy.c_str(), TRUE);
> +
> +    if (client_argv != NULL) {
> +        spawned = g_spawn_async(NULL,
> +                                client_argv, env,
> +                                G_SPAWN_DO_NOT_REAP_CHILD,
> +                                NULL, NULL, /* child_func, child_arg */
> +                                &pid, &error);
> +        if (error != NULL) {
> +            g_warning("failed to start %s: %s", client_argv[0], error->message);
> +            g_warn_if_fail(spawned == FALSE);
> +            g_clear_error(&error);
> +        }
> +    }
> +    if (!spawned && (fallback_argv != NULL)) {
> +        // TODO: temporary fallback for backward compatibility
> +        g_message("failed to run preferred client, running fallback client instead");
> +        spawned = g_spawn_async(NULL, fallback_argv, env,
> +                                G_SPAWN_DO_NOT_REAP_CHILD,
> +                                NULL, NULL, /* child_func, child_arg */
> +                                &pid, &error);
> +        if (error != NULL) {
> +            g_warning("failed to start %s: %s", fallback_argv[0], error->message);
> +            g_warn_if_fail(spawned == FALSE);
> +            g_clear_error(&error);
> +        }
> +    }
> +    g_strfreev(env);
> +    g_strfreev(client_argv);
> +    g_strfreev(fallback_argv);
> +
> +    if (!spawned) {
> +        g_critical("ERROR failed to run spicec fallback");
> +        return NULL;
> +    }
> +
> +#ifdef XP_UNIX
> +    fake_this->m_pid_controller = pid;
> +#endif
> +    fake_this->WaitForPid(pid);
> +
> +    return NULL;
> +}
> +
> +bool SpiceController::StartClient()
> +{
> +    GThread *thread;
> +
> +    thread = g_thread_create(ClientThread, this, FALSE, NULL);
> +
> +    return (thread != NULL);
> +}
> +
> +int SpiceController::TranslateRC(int nRC)
> +{
> +    switch (nRC)
> +    {
> +    case SPICEC_ERROR_CODE_SUCCESS:
> +        return 0;
> +
> +    case SPICEC_ERROR_CODE_GETHOSTBYNAME_FAILED:
> +        return RDP_ERROR_CODE_HOST_NOT_FOUND;
> +
> +    case SPICEC_ERROR_CODE_CONNECT_FAILED:
> +        return RDP_ERROR_CODE_WINSOCK_CONNECT_FAILED;
> +
> +    case SPICEC_ERROR_CODE_ERROR:
> +    case SPICEC_ERROR_CODE_SOCKET_FAILED:
> +        return RDP_ERROR_CODE_INTERNAL_ERROR;
> +
> +    case SPICEC_ERROR_CODE_RECV_FAILED:
> +        return RDP_ERROR_RECV_WINSOCK_FAILED;
> +
> +    case SPICEC_ERROR_CODE_SEND_FAILED:
> +        return RDP_ERROR_SEND_WINSOCK_FAILED;
> +
> +    case SPICEC_ERROR_CODE_NOT_ENOUGH_MEMORY:
> +        return RDP_ERROR_CODE_OUT_OF_MEMORY;
> +
> +    case SPICEC_ERROR_CODE_AGENT_TIMEOUT:
> +        return RDP_ERROR_CODE_TIMEOUT;
> +
> +    case SPICEC_ERROR_CODE_AGENT_ERROR:
> +        return RDP_ERROR_CODE_INTERNAL_ERROR;
> +
> +    default:
> +        return RDP_ERROR_CODE_INTERNAL_ERROR;
> +    }
> +}
> diff --git a/SpiceXPI/src/plugin/controller.h b/SpiceXPI/src/plugin/controller.h
> index de4516c..4473dd4 100644
> --- a/SpiceXPI/src/plugin/controller.h
> +++ b/SpiceXPI/src/plugin/controller.h
> @@ -60,6 +60,7 @@
>
>  #include <glib.h>
>  #include <glib-object.h> /* for GStrv */
> +#include <gio/gio.h>
>  #include <string>
>  extern "C" {
>  #  include <stdint.h>
> @@ -74,32 +75,34 @@ class SpiceController
>  {
>  public:
>      SpiceController(nsPluginInstance *aPlugin);
> -    ~SpiceController();
> +    virtual ~SpiceController();
>
>      bool StartClient();
> -    void StopClient();
> +    virtual void StopClient() = 0;
>      void SetFilename(const std::string &name);
>      void SetProxy(const std::string &proxy);
>      int Connect(int nRetries);
> -    void Disconnect();
> -    uint32_t Write(const void *lpBuffer, uint32_t nBytesToWrite);
> +    virtual void Disconnect();
> +    virtual uint32_t Write(const void *lpBuffer, uint32_t nBytesToWrite) = 0;
>
>      static int TranslateRC(int nRC);
>
> +protected:
> +    std::string m_name;
> +    std::string m_proxy;
> +    GPid m_pid_controller;
> +    GOutputStream *m_pipe;
> +
>  private:
> -    int Connect();
> +    virtual int Connect() = 0;
>      void WaitForPid(GPid pid);
> -    void SetupControllerPipe(GStrv &env);
> -    void GetClientPaths(GStrv *client_argv, GStrv *fallback_argv);
> +    virtual void SetupControllerPipe(GStrv &env) = 0;
> +    virtual bool CheckPipe() = 0;
> +    virtual void GetClientPaths(GStrv *client_argv, GStrv *fallback_argv) = 0;
>      static void ChildExited(GPid pid, gint status, gpointer user_data);
>      static gpointer ClientThread(gpointer data);
>
>      nsPluginInstance *m_plugin;
> -    int m_client_socket;
> -    std::string m_name;
> -    std::string m_tmp_dir;
> -    pid_t m_pid_controller;
> -    std::string m_proxy;
>
>      GMainLoop *m_child_watch_mainloop;
>  };
> diff --git a/SpiceXPI/src/plugin/plugin.cpp b/SpiceXPI/src/plugin/plugin.cpp
> index e8c916e..5ecc793 100644
> --- a/SpiceXPI/src/plugin/plugin.cpp
> +++ b/SpiceXPI/src/plugin/plugin.cpp
> @@ -67,7 +67,7 @@ extern "C" {
>  #include <fstream>
>  #include <set>
>
> -#include "controller.h"
> +#include "controller-unix.h"
>  #include "plugin.h"
>  #include "nsScriptablePeer.h"
>
> @@ -173,7 +173,6 @@ void NS_DestroyPluginInstance(nsPluginInstanceBase *aPlugin)
>  nsPluginInstance::nsPluginInstance(NPP aInstance):
>      nsPluginInstanceBase(),
>      m_connected_status(-2),
> -    m_external_controller(this),
>      m_instance(aInstance),
>      m_initialized(true),
>      m_window(NULL),
> @@ -186,6 +185,8 @@ nsPluginInstance::nsPluginInstance(NPP aInstance):
>      m_scriptable_peer(NULL)
>  {
>      g_type_init();
> +
> +    m_external_controller = new SpiceControllerUnix(this);
>  }
>
>  nsPluginInstance::~nsPluginInstance()
> @@ -196,6 +197,7 @@ nsPluginInstance::~nsPluginInstance()
>      // and zero its m_plugin member
>      if (m_scriptable_peer)
>          NPN_ReleaseObject(m_scriptable_peer);
> +    delete(m_external_controller);
>  }
>
>  NPBool nsPluginInstance::init(NPWindow *aWindow)
> @@ -221,7 +223,7 @@ NPBool nsPluginInstance::init(NPWindow *aWindow)
>      m_color_depth.clear();
>      m_disable_effects.clear();
>      m_proxy.clear();
> -    m_external_controller.SetProxy(std::string());
> +    m_external_controller->SetProxy(std::string());
>
>      m_fullscreen = false;
>      m_smartcard = false;
> @@ -526,12 +528,12 @@ char *nsPluginInstance::GetProxy() const
>  void nsPluginInstance::SetProxy(const char *aProxy)
>  {
>      m_proxy = aProxy;
> -    m_external_controller.SetProxy(m_proxy);
> +    m_external_controller->SetProxy(m_proxy);
>  }
>
>  void nsPluginInstance::WriteToPipe(const void *data, uint32_t size)
>  {
> -    m_external_controller.Write(data, size);
> +    m_external_controller->Write(data, size);
>  }
>
>  void nsPluginInstance::SendInit()
> @@ -628,12 +630,12 @@ void nsPluginInstance::Connect()
>          return;
>      }
>
> -    if (!m_external_controller.StartClient()) {
> +    if (!m_external_controller->StartClient()) {
>          g_critical("failed to start SPICE client");
>          return;
>      }
>
> -    if (m_external_controller.Connect(10) != 0)
> +    if (m_external_controller->Connect(10) != 0)
>      {
>          g_critical("could not connect to spice client controller");
>          return;
> @@ -681,7 +683,7 @@ void nsPluginInstance::Show()
>
>  void nsPluginInstance::Disconnect()
>  {
> -    m_external_controller.StopClient();
> +    m_external_controller->StopClient();
>  }
>
>  void nsPluginInstance::ConnectedStatus(int32_t *retval)
> @@ -755,11 +757,11 @@ void nsPluginInstance::CallOnDisconnected(int code)
>
>  void nsPluginInstance::OnSpiceClientExit(int exit_code)
>  {
> -    m_connected_status = m_external_controller.TranslateRC(exit_code);
> +    m_connected_status = m_external_controller->TranslateRC(exit_code);
>      if (!getenv("SPICE_XPI_DEBUG"))
>      {
>          CallOnDisconnected(exit_code);
> -        m_external_controller.Disconnect();
> +        m_external_controller->Disconnect();
>      }
>
>      RemoveTrustStoreFile();
> diff --git a/SpiceXPI/src/plugin/plugin.h b/SpiceXPI/src/plugin/plugin.h
> index 5e7f079..7884dc7 100644
> --- a/SpiceXPI/src/plugin/plugin.h
> +++ b/SpiceXPI/src/plugin/plugin.h
> @@ -190,7 +190,7 @@ private:
>      bool RemoveTrustStoreFile();
>
>      int32_t m_connected_status;
> -    SpiceController m_external_controller;
> +    SpiceController *m_external_controller;
>
>      NPP m_instance;
>      NPBool m_initialized;
> --
> 1.8.1.4
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel



-- 
Marc-André Lureau


More information about the Spice-devel mailing list