softwarecontainer  0.18.0-739e8d7 2017-05-04
softwarecontainer::DBusGatewayInstance Class Reference

DBus Gateway takes care of spawning and killing the DBus proxies. More...

#include <dbusgatewayinstance.h>

Inheritance diagram for softwarecontainer::DBusGatewayInstance:
[legend]
Collaboration diagram for softwarecontainer::DBusGatewayInstance:
[legend]

Public Types

enum  ProxyType { SessionProxy, SystemProxy }
 
enum  GatewayState : unsigned int { CREATED, CONFIGURED, ACTIVATED }
 

Public Member Functions

 DBusGatewayInstance (ProxyType type, const std::string &gatewayDir, std::shared_ptr< ContainerAbstractInterface > container)
 Spawn the proxy and use the supplied path for the socket. More...
 
virtual bool readConfigElement (const json_t *element) override
 Gateway specific parsing of config elements. More...
 
virtual bool activateGateway ()
 Implements Gateway::activateGateway. More...
 
virtual bool teardownGateway () override
 Implements Gateway::teardownGateway. More...
 
virtual std::string id () const
 Returns the ID of the gateway. More...
 
virtual bool setConfig (const json_t *config)
 Configure this gateway according to the supplied JSON configuration string. More...
 
virtual bool activate ()
 Applies any configuration set by setConfig() More...
 
virtual bool teardown ()
 Restore system to the state prior to launching of gateway. More...
 
virtual bool isConfigured ()
 Is the gateway configured or not? More...
 
virtual bool isActivated ()
 Is the gateway activated or not? More...
 

Static Public Attributes

static constexpr const char * ID
 
static constexpr const char * SESSION_CONFIG
 
static constexpr const char * SYSTEM_CONFIG
 

Protected Member Functions

std::shared_ptr< ContainerAbstractInterfacegetContainer ()
 Get a handle to the associated container. More...
 
bool setEnvironmentVariable (const std::string &variable, const std::string &value)
 Set an environment variable in the associated container. More...
 

Protected Attributes

bool m_activatedOnce
 

Detailed Description

DBus Gateway takes care of spawning and killing the DBus proxies.

This module requires the 'dbus-proxy' binary to be available in the $PATH of the user executing softwarecontainer.

Definition at line 32 of file dbusgatewayinstance.h.

Constructor & Destructor Documentation

softwarecontainer::DBusGatewayInstance::DBusGatewayInstance ( ProxyType  type,
const std::string &  gatewayDir,
std::shared_ptr< ContainerAbstractInterface container 
)

Spawn the proxy and use the supplied path for the socket.

Parameters
typeSessionProxy or SystemProxy

Definition at line 36 of file dbusgatewayinstance.cpp.

References softwarecontainer::Gateway::id(), softwarecontainer::Gateway::isActivated(), and softwarecontainer::Gateway::teardown().

38  :
39  Gateway(ID, container, true /*this GW is dynamic*/),
40  m_socket(""),
41  m_type(type),
42  m_pid(INVALID_PID),
43  m_proxyStdin(INVALID_FD)
44 {
45  std::string name = container->id();
46  std::string socketName = (m_type == SessionProxy ? "sess_" : "sys_") + name + ".sock";
47  m_socket = buildPath(gatewayDir, socketName);
48 
49  // Write configuration
50  m_entireConfig = json_object();
51  m_busConfig = json_array();
52 
53  const char* unusedTypeStr;
54  if (m_type == SessionProxy) {
55  typeStr = SESSION_CONFIG;
56  unusedTypeStr = SYSTEM_CONFIG;
57 
58  } else {
59  typeStr = SYSTEM_CONFIG;
60  unusedTypeStr = SESSION_CONFIG;
61  }
62  json_object_set(m_entireConfig, typeStr, m_busConfig);
63 
64  // Send an empty array as config for the irrelevant proxy type
65  json_t* emptyArray = json_array();
66  json_object_set(m_entireConfig, unusedTypeStr, emptyArray);
67 }
Gateway(const std::string &id, std::shared_ptr< ContainerAbstractInterface > container, bool isDynamic=false)
Constructor for inheriting classes to initilize.
Definition: gateway.cpp:25

Here is the call graph for this function:

Member Function Documentation

bool softwarecontainer::DBusGatewayInstance::readConfigElement ( const json_t *  element)
overridevirtual

Gateway specific parsing of config elements.

All gateways implement this method in order to provide gateway specific parsing of the configuration content.

Parameters
elementA JSON configuration item.
Returns
false if an error was encountered while parsing, true otherwise.

Implements softwarecontainer::Gateway.

Definition at line 81 of file dbusgatewayinstance.cpp.

82 {
83  DBusGatewayParser parser;
84 
85  // TODO: This should really be done with exceptions instead and json_t* as return type.
86  if (!parser.parseDBusConfig(element, typeStr, m_busConfig)) {
87  // This might also mean that only one of session or system bus config parsing failed
88  // so this is not a fatal error
89  log_warning() << "Failed to parse DBus configuration element";
90  return false;
91  }
92 
93  return true;
94 }
bool softwarecontainer::DBusGatewayInstance::activateGateway ( )
virtual

Implements Gateway::activateGateway.

Starts the dbus-proxy binary and feeds it the configuration set in setConfig(). This function will also set up the correct environment variables (DBUS_SESSION_BUS_ADDRESS when proxying the session bus, or DBUS_SYSTEM_BUS_ADDRESS when proxying the system bus).

This function requires a config to have been set using setConfig().

This function requires the 'dbus-proxy' binary to be available in $PATH

Returns
true when dbus-proxy was correctly execute and environment variable was correctly set false if dbus-proxy failed to execute or accept input on STDIN, or when environment variable could not be set.

Implements softwarecontainer::Gateway.

Definition at line 96 of file dbusgatewayinstance.cpp.

References softwarecontainer::Gateway::getContainer().

97 {
98  // Setting up the environment and starting dbus-proxy should only be done the first time
99  // around. Any subsequent calls after the first should only result in the config being
100  // updated.
101  if (!m_activatedOnce) {
102  // set DBUS_{SESSION,SYSTEM}_BUS_ADDRESS env variable
103  std::string variable = std::string("DBUS_")
104  + (m_type == SessionProxy ? "SESSION" : "SYSTEM")
105  + std::string("_BUS_ADDRESS");
106  std::string value = "unix:path=" + buildPath("/gateways", socketName());
107  getContainer()->setEnvironmentVariable(variable, value);
108 
109  std::vector<std::string> commandVec = {"dbus-proxy",
110  m_socket,
111  m_type == SessionProxy ? "session" : "system"};
112 
113  // Give the dbus-proxy access to the real dbus bus address.
114  std::vector<std::string> envVec;
115 
116  bool hasEnvVar = false;
117  std::string envValue = Glib::getenv(variable, hasEnvVar);
118 
119  if (!hasEnvVar) {
120  if (SessionProxy == m_type) {
121  log_error() << "Using DBus gateway in session mode"
122  << " and no " + variable + " set in host environment, dbus-proxy won't work";
123  return false;
124  } else {
125  log_warn() << "Using DBus gateway in system mode"
126  << " and no " + variable + " set in host environment, this could be a problem";
127  }
128  } else {
129  envVec.push_back(variable + "=" + envValue);
130  }
131 
132  if (!startDBusProxy(commandVec, envVec)) {
133  return false;
134  }
135  }
136 
137  // Dump to string. Compact format is currently needed as dbus-proxy relies on
138  // the config string to be without newlines anywhere in the middle of it all
139  char *config_c = json_dumps(m_entireConfig, JSON_COMPACT);
140  std::string config = std::string(config_c);
141 
142  free(config_c);
143 
144  return testDBusConnection(config);
145 }
std::shared_ptr< ContainerAbstractInterface > getContainer()
Get a handle to the associated container.
Definition: gateway.cpp:128

Here is the call graph for this function:

bool softwarecontainer::DBusGatewayInstance::teardownGateway ( )
overridevirtual

Implements Gateway::teardownGateway.

This function will clean up processes launched and file descriptors opened during the lifetime of the gatway. Specifically it will close the connection to the dbus-proxy, and close the stdin and stdout pipes opened to dbus-proxy.

Returns
false if dbus-proxy could not be terminated, if stdin or stdout could not be closed, or if the socket created by the dbus-proxy could not be removed.

Implements softwarecontainer::Gateway.

Definition at line 221 of file dbusgatewayinstance.cpp.

222 {
223  bool success = true;
224 
225  if (nullptr != m_entireConfig) {
226  json_decref(m_entireConfig);
227  m_entireConfig = nullptr;
228  }
229 
230  if (m_pid != INVALID_PID) {
231  log_debug() << "Killing dbus-proxy with pid " << m_pid;
232 
233  // TODO: Figure out how to shut down nicely?
234  kill(m_pid, SIGKILL); // In some configurations, hangs if using SIGTERM instead
235  waitpid(m_pid, nullptr, 0); // Wait until it exits
236  Glib::spawn_close_pid(m_pid);
237  } else {
238  log_debug() << "dbus-proxy pid not set or already dead: " << m_pid;
239  }
240 
241  if (access(m_socket.c_str(), F_OK) != -1) {
242  if (unlink(m_socket.c_str()) == -1) {
243  log_error() << "Could not remove " << m_socket << ": " << strerror(errno);
244  success = false;
245  }
246  } else {
247  // TODO: Seems weird that this would ever happen. Seems like a severe error.
248  log_debug() << "Socket not accessible, has it been removed already?";
249  }
250 
251  // Close stdin to proxy as we will no longer send configs to it
252  if (close(m_proxyStdin) == -1) {
253  log_warning() << "Could not close stdin of dbus-proxy";
254  }
255 
256  return success;
257 }
std::string softwarecontainer::Gateway::id ( ) const
virtualinherited

Returns the ID of the gateway.

Returns
Returns the ID of the gateway as a string

Definition at line 36 of file gateway.cpp.

Referenced by softwarecontainer::Gateway::activate(), DBusGatewayInstance(), softwarecontainer::Gateway::setConfig(), and softwarecontainer::Gateway::teardown().

37 {
38  return m_id;
39 }

Here is the caller graph for this function:

bool softwarecontainer::Gateway::setConfig ( const json_t *  config)
virtualinherited

Configure this gateway according to the supplied JSON configuration string.

Parameters
configJSON string containing gateway-specific JSON configuration
Returns
true if config was successfully parsed, false otherwise
Exceptions
GatewayErrorIf called on an already activated gateway.

Reimplemented in softwarecontainer::DBusGateway.

Definition at line 41 of file gateway.cpp.

References softwarecontainer::Gateway::id(), and softwarecontainer::Gateway::readConfigElement().

42 {
43  if (GatewayState::ACTIVATED == m_state && !m_isDynamic) {
44  std::string message = "Can not configure a gateway that is already activated "
45  "if the gateway does not support dynamic behavior. "
46  "Gateway ID: " + id();
47  log_error() << message;
48  throw GatewayError(message);
49  }
50 
51  if (!json_is_array(config)) {
52  log_error() << "Root JSON element is not an array";
53  return false;
54  }
55 
56  if (json_array_size(config) == 0) {
57  log_error() << "Root JSON array is empty";
58  return false;
59  }
60 
61  for(size_t i = 0; i < json_array_size(config); i++) {
62  json_t *element = json_array_get(config, i);
63  if (!json_is_object(element)) {
64  log_error() << "json configuration is not an object";
65  return false;
66  }
67 
68  if (!readConfigElement(element)) {
69  log_warning() << "Could not read config element";
70  return false;
71  }
72  }
73 
74  m_state = GatewayState::CONFIGURED;
75  return true;
76 }
virtual std::string id() const
Returns the ID of the gateway.
Definition: gateway.cpp:36
virtual bool readConfigElement(const json_t *element)=0
Gateway specific parsing of config elements.

Here is the call graph for this function:

bool softwarecontainer::Gateway::activate ( )
virtualinherited

Applies any configuration set by setConfig()

Returns
true upon successful application of configuration, false otherwise
Exceptions
GatewayErrorIf called on an already activated gateway, or if the gateway has not been previously configured, or if there is not container instance set.

Reimplemented in softwarecontainer::DBusGateway.

Definition at line 78 of file gateway.cpp.

References softwarecontainer::Gateway::id().

78  {
79  if (GatewayState::ACTIVATED == m_state && !m_isDynamic) {
80  std::string message = "Can not activate a gateway that is already activated "
81  "if the gateway does not support dynamic behavior. "
82  "Gateway ID: " + id();
83  log_error() << message;
84  throw GatewayError(message);
85  }
86 
87  if (GatewayState::CONFIGURED != m_state) {
88  std::string message = "Activate was called on a gateway which is not in configured state. "
89  "Gateway ID: " + id();
90  log_error() << message;
91  throw GatewayError(message);
92  }
93 
94  if (!activateGateway()) {
95  log_error() << "Couldn't activate gateway: " << id();
96  return false;
97  }
98 
99  m_state = GatewayState::ACTIVATED;
100  return true;
101 }
virtual std::string id() const
Returns the ID of the gateway.
Definition: gateway.cpp:36

Here is the call graph for this function:

bool softwarecontainer::Gateway::teardown ( )
virtualinherited

Restore system to the state prior to launching of gateway.

Any cleanup code (removal of files, virtual interfaces, etc) should be placed here.

Returns
true upon successful clean-up, false otherwise
Exceptions
GatewayErrorIf called on a non activated gateway.

Reimplemented in softwarecontainer::DBusGateway.

Definition at line 103 of file gateway.cpp.

References softwarecontainer::Gateway::id().

Referenced by DBusGatewayInstance().

103  {
104  /* At this point, a gateway should either be in state ACTIVATED if it is non-dynamic, or
105  if it is dynamic it should have been activated at least once before.
106  */
107  if (GatewayState::ACTIVATED != m_state && !m_activatedOnce) {
108  std::string message = "Teardown called on non-activated gateway. Gateway ID: " + id();
109  log_error() << message;
110  throw GatewayError(message);
111  }
112 
113  if (!teardownGateway()) {
114  log_error() << "Could not tear down gateway: " << id();
115  return false;
116  }
117 
118  // Return to a state of nothingness
119  m_state = GatewayState::CREATED;
120 
121  /* Since we have been torn down, we should not be considered to have been
122  activated any more. */
123  m_activatedOnce = false;
124 
125  return true;
126 }
virtual std::string id() const
Returns the ID of the gateway.
Definition: gateway.cpp:36

Here is the call graph for this function:

Here is the caller graph for this function:

bool softwarecontainer::Gateway::isConfigured ( )
virtualinherited

Is the gateway configured or not?

Reimplemented in softwarecontainer::DBusGateway.

Definition at line 134 of file gateway.cpp.

135 {
136  return m_state >= GatewayState::CONFIGURED;
137 }
bool softwarecontainer::Gateway::isActivated ( )
virtualinherited

Is the gateway activated or not?

Dynamic gateways will return true if they have been activated at least once. Non-dynamic gateways will return true if they are in state ACTIVATED

Reimplemented in softwarecontainer::DBusGateway.

Definition at line 139 of file gateway.cpp.

Referenced by DBusGatewayInstance().

140 {
141  // For dynamic gateways it's only relevant to know if it has been activated
142  // at least once, the current state is not important
143  if (m_isDynamic) {
144  return m_activatedOnce;
145  }
146 
147  // For non-dynamic gateways, the current state is the only relevant info
148  return m_state >= GatewayState::ACTIVATED;
149 }

Here is the caller graph for this function:

std::shared_ptr< ContainerAbstractInterface > softwarecontainer::Gateway::getContainer ( )
protectedinherited

Get a handle to the associated container.

Exceptions
GatewayErrorIf called before setContainer() has been called.

Definition at line 128 of file gateway.cpp.

Referenced by softwarecontainer::NetworkGateway::activateGateway(), activateGateway(), softwarecontainer::WaylandGateway::readConfigElement(), and softwarecontainer::NetworkGateway::teardownGateway().

129 {
130  std::shared_ptr<ContainerAbstractInterface> ptrCopy = m_container;
131  return ptrCopy;
132 }

Here is the caller graph for this function:

bool softwarecontainer::Gateway::setEnvironmentVariable ( const std::string &  variable,
const std::string &  value 
)
protectedinherited

Set an environment variable in the associated container.


The documentation for this class was generated from the following files: