[Spice-devel] [spice-xpi 12/12] Add an abstract controller base class
Christophe Fergeau
cfergeau at redhat.com
Tue Mar 12 04:23:07 PDT 2013
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
More information about the Spice-devel
mailing list