This is platform specific, and is related to starting the receiver of controller messages, so let's move it with the rest of the platform-specific code. --- SpiceXPI/src/plugin/controller-unix.cpp | 106 +++++++++++++++++++++++++++++- SpiceXPI/src/plugin/controller.h | 13 +++- SpiceXPI/src/plugin/plugin.cpp | 110 ++++---------------------------- SpiceXPI/src/plugin/plugin.h | 7 +- 4 files changed, 130 insertions(+), 106 deletions(-) diff --git a/SpiceXPI/src/plugin/controller-unix.cpp b/SpiceXPI/src/plugin/controller-unix.cpp index e2a513c..0435c24 100644 --- a/SpiceXPI/src/plugin/controller-unix.cpp +++ b/SpiceXPI/src/plugin/controller-unix.cpp @@ -54,20 +54,29 @@ extern "C" { # include <fcntl.h> # include <sys/socket.h> # include <sys/un.h> +# include <sys/wait.h> } #include "rederrorcodes.h" #include "controller.h" +#include "plugin.h" -SpiceController::SpiceController(): +SpiceController::SpiceController(nsPluginInstance *aPlugin): + m_plugin(aPlugin), m_client_socket(-1) { + // create temporary directory in /tmp + char tmp_dir[] = "/tmp/spicec-XXXXXX"; + m_tmp_dir = mkdtemp(tmp_dir); } SpiceController::~SpiceController() { g_debug(G_STRFUNC); Disconnect(); + + // delete the temporary directory used for a client socket + rmdir(m_tmp_dir.c_str()); } void SpiceController::SetFilename(const std::string &name) @@ -75,6 +84,11 @@ void SpiceController::SetFilename(const std::string &name) m_name = name; } +void SpiceController::SetProxy(const std::string &proxy) +{ + m_proxy = proxy; +} + int SpiceController::Connect() { // check, if we have a filename for socket to create @@ -149,6 +163,96 @@ uint32_t SpiceController::Write(const void *lpBuffer, uint32_t nBytesToWrite) return len; } +bool SpiceController::StartClient() +{ + std::string socket_file(m_tmp_dir); + socket_file += "/spice-xpi"; + + /* use a pipe for the children to wait until it gets tracked */ + int pipe_fds[2] = { -1, -1 }; + if (pipe(pipe_fds) < 0) { + perror("spice-xpi system error"); + return false; + } + + m_pid_controller = fork(); + if (m_pid_controller == 0) + { + setpgrp(); + + close(pipe_fds[1]); + pipe_fds[1] = -1; + + char c; + if (read(pipe_fds[0], &c, 1) != 0) + g_critical("Error while reading on pipe: %s", g_strerror(errno)); + + close(pipe_fds[0]); + pipe_fds[0] = -1; + + gchar **env = g_get_environ(); + env = g_environ_setenv(env, "SPICE_XPI_SOCKET", socket_file.c_str(), TRUE); + if (!m_proxy.empty()) + env = g_environ_setenv(env, "SPICE_PROXY", m_proxy.c_str(), TRUE); + + execle("/usr/libexec/spice-xpi-client", + "/usr/libexec/spice-xpi-client", NULL, + env); + g_message("failed to run spice-xpi-client, running spicec instead"); + + // TODO: temporary fallback for backward compatibility + execle("/usr/bin/spicec", + "/usr/bin/spicec", "--controller", NULL, + env); + + g_critical("ERROR failed to run spicec fallback"); + g_strfreev(env); + exit(EXIT_FAILURE); + } + else + { + g_debug("child pid: %"G_GUINT64_FORMAT, (guint64)m_pid_controller); + + close(pipe_fds[0]); + pipe_fds[0] = -1; + + pthread_t controller_thread_id; + pthread_create(&controller_thread_id, NULL, ControllerWaitHelper, + reinterpret_cast<void*>(this)); + + close(pipe_fds[1]); + pipe_fds[1] = -1; + + this->SetFilename(socket_file); + + return true; + } + + g_return_val_if_reached(false); +} + +void SpiceController::StopClient() +{ + if (m_pid_controller > 0) + kill(-m_pid_controller, SIGTERM); +} + +void *SpiceController::ControllerWaitHelper(void *opaque) +{ + SpiceController *fake_this = reinterpret_cast<SpiceController *>(opaque); + if (!fake_this) + return NULL; + + int exit_code; + waitpid(fake_this->m_pid_controller, &exit_code, 0); + g_debug("child finished, pid: %"G_GUINT64_FORMAT, (guint64)exit_code); + + fake_this->m_plugin->OnSpiceClientExit(exit_code); + fake_this->m_pid_controller = -1; + + return NULL; +} + int SpiceController::TranslateRC(int nRC) { switch (nRC) diff --git a/SpiceXPI/src/plugin/controller.h b/SpiceXPI/src/plugin/controller.h index 5bbf291..54d1d46 100644 --- a/SpiceXPI/src/plugin/controller.h +++ b/SpiceXPI/src/plugin/controller.h @@ -66,13 +66,18 @@ extern "C" { #include <spice/controller_prot.h> +class nsPluginInstance; + class SpiceController { public: - SpiceController(); + SpiceController(nsPluginInstance *aPlugin); ~SpiceController(); + bool StartClient(); + void StopClient(); 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); @@ -81,8 +86,14 @@ public: private: int Connect(); + static void *ControllerWaitHelper(void *opaque); + + 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; }; #endif // SPICE_CONTROLLER_H diff --git a/SpiceXPI/src/plugin/plugin.cpp b/SpiceXPI/src/plugin/plugin.cpp index 9d47924..e8c916e 100644 --- a/SpiceXPI/src/plugin/plugin.cpp +++ b/SpiceXPI/src/plugin/plugin.cpp @@ -48,10 +48,6 @@ #include "config.h" -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/stat.h> - #include <stdlib.h> #include <errno.h> #include <unistd.h> @@ -176,8 +172,8 @@ void NS_DestroyPluginInstance(nsPluginInstanceBase *aPlugin) nsPluginInstance::nsPluginInstance(NPP aInstance): nsPluginInstanceBase(), - m_pid_controller(-1), m_connected_status(-2), + m_external_controller(this), m_instance(aInstance), m_initialized(true), m_window(NULL), @@ -189,10 +185,6 @@ nsPluginInstance::nsPluginInstance(NPP aInstance): m_usb_auto_share(true), m_scriptable_peer(NULL) { - // create temporary directory in /tmp - char tmp_dir[] = "/tmp/spicec-XXXXXX"; - m_tmp_dir = mkdtemp(tmp_dir); - g_type_init(); } @@ -204,9 +196,6 @@ nsPluginInstance::~nsPluginInstance() // and zero its m_plugin member if (m_scriptable_peer) NPN_ReleaseObject(m_scriptable_peer); - - // delete the temporary directory used for a client socket - rmdir(m_tmp_dir.c_str()); } NPBool nsPluginInstance::init(NPWindow *aWindow) @@ -232,6 +221,7 @@ NPBool nsPluginInstance::init(NPWindow *aWindow) m_color_depth.clear(); m_disable_effects.clear(); m_proxy.clear(); + m_external_controller.SetProxy(std::string()); m_fullscreen = false; m_smartcard = false; @@ -536,6 +526,7 @@ char *nsPluginInstance::GetProxy() const void nsPluginInstance::SetProxy(const char *aProxy) { m_proxy = aProxy; + m_external_controller.SetProxy(m_proxy); } void nsPluginInstance::WriteToPipe(const void *data, uint32_t size) @@ -585,74 +576,6 @@ void nsPluginInstance::SendStr(uint32_t id, std::string str) free(msg); } -bool nsPluginInstance::StartClient() -{ - std::string socket_file(m_tmp_dir); - socket_file += "/spice-xpi"; - - /* use a pipe for the children to wait until it gets tracked */ - int pipe_fds[2] = { -1, -1 }; - if (pipe(pipe_fds) < 0) { - perror("spice-xpi system error"); - return false; - } - - m_pid_controller = fork(); - if (m_pid_controller == 0) - { - setpgrp(); - - close(pipe_fds[1]); - pipe_fds[1] = -1; - - char c; - if (read(pipe_fds[0], &c, 1) != 0) - g_critical("Error while reading on pipe: %s", g_strerror(errno)); - - close(pipe_fds[0]); - pipe_fds[0] = -1; - - gchar **env = g_get_environ(); - env = g_environ_setenv(env, "SPICE_XPI_SOCKET", socket_file.c_str(), TRUE); - if (!m_proxy.empty()) - env = g_environ_setenv(env, "SPICE_PROXY", m_proxy.c_str(), TRUE); - - execle("/usr/libexec/spice-xpi-client", - "/usr/libexec/spice-xpi-client", NULL, - env); - g_message("failed to run spice-xpi-client, running spicec instead"); - - // TODO: temporary fallback for backward compatibility - execle("/usr/bin/spicec", - "/usr/bin/spicec", "--controller", NULL, - env); - - g_critical("ERROR failed to run spicec fallback"); - g_strfreev(env); - exit(EXIT_FAILURE); - } - else - { - g_debug("child pid: %"G_GUINT64_FORMAT, (guint64)m_pid_controller); - - close(pipe_fds[0]); - pipe_fds[0] = -1; - - pthread_t controller_thread_id; - pthread_create(&controller_thread_id, NULL, ControllerWaitHelper, - reinterpret_cast<void*>(this)); - - close(pipe_fds[1]); - pipe_fds[1] = -1; - - m_external_controller.SetFilename(socket_file); - - return true; - } - - g_return_val_if_reached(false); -} - bool nsPluginInstance::CreateTrustStoreFile(const std::string &trust_store) { GFile *tmp_file; @@ -705,7 +628,7 @@ void nsPluginInstance::Connect() return; } - if (!this->StartClient()) { + if (!m_external_controller.StartClient()) { g_critical("failed to start SPICE client"); return; } @@ -758,8 +681,7 @@ void nsPluginInstance::Show() void nsPluginInstance::Disconnect() { - if (m_pid_controller > 0) - kill(-m_pid_controller, SIGTERM); + m_external_controller.StopClient(); } void nsPluginInstance::ConnectedStatus(int32_t *retval) @@ -831,26 +753,16 @@ void nsPluginInstance::CallOnDisconnected(int code) NPN_ReleaseVariantValue(&var_on_disconnected); } -void *nsPluginInstance::ControllerWaitHelper(void *opaque) +void nsPluginInstance::OnSpiceClientExit(int exit_code) { - nsPluginInstance *fake_this = reinterpret_cast<nsPluginInstance *>(opaque); - if (!fake_this) - return NULL; - - int exit_code; - waitpid(fake_this->m_pid_controller, &exit_code, 0); - g_debug("child finished, pid: %"G_GUINT64_FORMAT, (guint64)exit_code); - - fake_this->m_connected_status = fake_this->m_external_controller.TranslateRC(exit_code); + m_connected_status = m_external_controller.TranslateRC(exit_code); if (!getenv("SPICE_XPI_DEBUG")) { - fake_this->CallOnDisconnected(exit_code); - fake_this->m_external_controller.Disconnect(); + CallOnDisconnected(exit_code); + m_external_controller.Disconnect(); } - - fake_this->RemoveTrustStoreFile(); - fake_this->m_pid_controller = -1; - return NULL; + + RemoveTrustStoreFile(); } // ============================== diff --git a/SpiceXPI/src/plugin/plugin.h b/SpiceXPI/src/plugin/plugin.h index ea50ca5..5e7f079 100644 --- a/SpiceXPI/src/plugin/plugin.h +++ b/SpiceXPI/src/plugin/plugin.h @@ -174,8 +174,9 @@ public: NPObject *GetScriptablePeer(); + void OnSpiceClientExit(int exit_code); + private: - static void *ControllerWaitHelper(void *opaque); void WriteToPipe(const void *data, uint32_t size); void SendInit(); void SendMsg(uint32_t id); @@ -185,12 +186,9 @@ private: void CallOnDisconnected(int code); private: - bool StartClient(); - bool CreateTrustStore(); bool CreateTrustStoreFile(const std::string &trust_store); bool RemoveTrustStoreFile(); - pid_t m_pid_controller; int32_t m_connected_status; SpiceController m_external_controller; @@ -224,7 +222,6 @@ private: std::string m_proxy; NPObject *m_scriptable_peer; - std::string m_tmp_dir; std::string m_trust_store_file; }; -- 1.8.1.4 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel