syncevolution/src/syncevo/LocalTransportAgent.cpp

788 lines
29 KiB
C++
Raw Normal View History

support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
/*
* Copyright (C) 2010 Patrick Ohly
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <syncevo/LocalTransportAgent.h>
#include <syncevo/SyncContext.h>
#include <syncevo/SyncML.h>
#include <syncevo/LogRedirect.h>
#include <syncevo/StringDataBlob.h>
#include <syncevo/IniConfigNode.h>
#include <syncevo/GLibSupport.h>
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
#include <stddef.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
#include <algorithm>
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
#include <syncevo/declarations.h>
SE_BEGIN_CXX
class NoopAgentDestructor
{
public:
void operator () (TransportAgent *agent) throw() {}
};
LocalTransportAgent::LocalTransportAgent(SyncContext *server,
const std::string &clientContext,
void *loop) :
m_server(server),
m_clientContext(SyncConfig::normalizeConfigString(clientContext)),
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
m_loop(static_cast<GMainLoop *>(loop)),
m_timeoutSeconds(0),
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
m_status(INACTIVE),
m_messageFD(-1),
m_statusFD(-1),
m_pid(0)
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
{
}
LocalTransportAgent::~LocalTransportAgent()
{
if (m_statusFD >= 0) {
close(m_statusFD);
}
if (m_messageFD >= 0) {
close(m_messageFD);
}
if (m_pid) {
SE_LOG_DEBUG(NULL, NULL, "starting to wait for child process %ld in destructor", (long)m_pid);
int status;
pid_t res = waitpid(m_pid, &status, 0);
SE_LOG_DEBUG(NULL, NULL, "child %ld completed, status %d", (long)res, status);
}
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
}
void LocalTransportAgent::start()
{
int sockets[2][2];
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
// compare normalized context names to detect forbidden sync
// within the same context; they could be set up, but are more
// likely configuration mistakes
string peer, context;
SyncConfig::splitConfigString(m_clientContext, peer, context);
if (!peer.empty()) {
SE_THROW(StringPrintf("invalid local sync URL: '%s' references a peer config, should point to a context like @%s instead",
m_clientContext.c_str(),
context.c_str()));
}
if (m_clientContext == m_server->getContextName()) {
SE_THROW(StringPrintf("invalid local sync inside context '%s', need second context with different databases", context.c_str()));
}
// initialize target client so that we can check passwords in the calling process
boost::shared_ptr<SyncContext> client(new SyncContext(std::string("target-config") + m_clientContext,
m_server->getConfigName(),
m_server->getRootPath() + "/." + m_clientContext,
boost::shared_ptr<TransportAgent>(this, NoopAgentDestructor()),
m_server->getDoLogging()));
// allow proceeding with sync even if no "target-config" was created,
// because information about username/password (for WebDAV) or the
// sources (for file backends) might be enough
client->setConfigNeeded(false);
// Apply temporary config filters, stored for us in m_server by the
// command line.
const FullProps &props = m_server->getConfigProps();
client->setConfigFilter(true, "", props.createSyncFilter(client->getConfigName()));
BOOST_FOREACH(const string &sourceName, m_server->getSyncSources()) {
client->setConfigFilter(false, sourceName, props.createSourceFilter(client->getConfigName(), sourceName));
}
// Copy non-empty credentials from main config, because
// that is where the GUI knows how to store them. A better
// solution would be to require that credentials are in the
// "target-config" config.
string tmp = m_server->getSyncUsername();
if (!tmp.empty()) {
client->setSyncUsername(tmp, true);
}
tmp = m_server->getSyncPassword();
if (!tmp.empty()) {
client->setSyncPassword(tmp, true);
}
// Iterate over all sync and source properties instead of checking
// some specified passwords. Mimics the code in SyncContext::sync(),
// except that we use the SyncContext in the caller to retrieve
// passwords interactively. client->sync() will check passwords
// again later in the forked process, but then it won't have to do
// anything because the check here will save passwords temporarily.
ConfigPropertyRegistry& registry = SyncConfig::getRegistry();
BOOST_FOREACH(const ConfigProperty *prop, registry) {
prop->checkPassword(*m_server, client->getPeer(), *client->getProperties());
}
// TODO: also handle passwords in active sources or, better,
// get interactive password retrieval working in the forked process
// BOOST_FOREACH(SyncSource *source, sourceList) {
// ConfigPropertyRegistry& registry = SyncSourceConfig::getRegistry();
// BOOST_FOREACH(const ConfigProperty *prop, registry) {
// prop->checkPassword(*m_server, m_server, *getProperties(),
// source->getName(), source->getProperties());
// }
// }
memset(sockets, 0, sizeof(sockets));
try {
if (socketpair(AF_LOCAL,
SOCK_STREAM,
0, sockets[0]) ||
socketpair(AF_LOCAL,
SOCK_STREAM,
0, sockets[1])) {
m_server->throwError("socketpair()", errno);
}
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
// Set close-on-exec flag for all file descriptors:
// they are used for tracking the death of either
// parent or child, so additional processes should
// not inherit them.
//
// Also set them to non-blocking, needed for the
// timeout handling.
for (int *fd = &sockets[0][0];
fd <= &sockets[1][1];
++fd) {
long flags = fcntl(*fd, F_GETFD, 0l); // extra argument for valgrind
fcntl(*fd, F_SETFD, flags | FD_CLOEXEC);
flags = fcntl(*fd, F_GETFL, 0l);
fcntl(*fd, F_SETFL, flags | O_NONBLOCK);
}
pid_t pid = fork();
switch (pid) {
case -1:
m_server->throwError("fork()", errno);
break;
case 0:
// child
Logger::setProcessName(m_clientContext);
close(sockets[0][0]);
m_messageFD = sockets[0][1];
close(sockets[1][0]);
m_statusFD = sockets[1][1];
m_client = client;
run();
break;
default:
// parent
close(sockets[0][1]);
m_messageFD = sockets[0][0];
close(sockets[1][1]);
m_statusFD = sockets[1][0];
// first message must come from child
m_status = ACTIVE;
m_pid = pid;
break;
}
} catch (...) {
for (int *fd = &sockets[0][0];
fd < &sockets[2][2];
++fd) {
if (*fd) {
close(*fd);
}
}
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
}
}
void LocalTransportAgent::run()
{
// delay the client for debugging purposes
const char *delay = getenv("SYNCEVOLUTION_LOCAL_CHILD_DELAY");
if (delay) {
sleep(atoi(delay));
}
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
// If we did an exec here, we could start with a clean slate.
// But that forces us to pass all relevant parameters to some
// specific executable, which is more complicated than simply
// reading from the existing in-process variables. So let's
// try without exec, after some clean up.
// The parent may or may not have installed output redirection.
// That instance needs to be remembered and flushed before this
// process may terminate. The parent will also do the same kind of
// flushing (race condition?!), but it might die before being
// able to do so.
//
// This loop used to remove all other loggers above the
// redirection, to get rid of the one which writes into the
// -log.html file of the parent. This was too coarse and also
// removed the LoggerStdout which was installed by
// client-test. Now the logger for -log.html is detected via
// Logger::isProcessSafe().
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
int index = LoggerBase::numLoggers();
LogRedirect *redirect = NULL;
bool removing = true;
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
--index;
while (index >= 0 &&
!(redirect = dynamic_cast<LogRedirect *>(LoggerBase::loggerAt(index)))) {
if (removing) {
if (!LoggerBase::loggerAt(index)->isProcessSafe()) {
LoggerBase::popLogger();
} else {
removing = false;
}
}
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
--index;
}
// do not mix our own output into the output of the parent
if (redirect) {
redirect->redoRedirect();
}
// Ignore parent's timeout and event loop.
m_timeoutSeconds = 0;
m_loop = 0;
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
// Now run. Under no circumstances must we leave this function,
// because our caller is not prepared for running inside a forked
// process.
int res = 0;
try {
SE_LOG_DEBUG(NULL, NULL, "client is running, %s log redirection",
redirect ? "with" : "without");
// debugging mode: write logs inside sub-directory of parent,
// otherwise use normal log settings
if (!m_server->getDoLogging()) {
m_client->setLogDir(std::string(m_server->getLogDir()) + "/child", true);
}
// disable all sources temporarily, will be enabled by next loop
BOOST_FOREACH(const string &targetName, m_client->getSyncSources()) {
SyncSourceNodes targetNodes = m_client->getSyncSourceNodes(targetName);
SyncSourceConfig targetSource(targetName, targetNodes);
targetSource.setSync("disabled", true);
}
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
// activate all sources in client targeted by main config,
// with right uri
BOOST_FOREACH(const string &sourceName, m_server->getSyncSources()) {
SyncSourceNodes nodes = m_server->getSyncSourceNodesNoTracking(sourceName);
SyncSourceConfig source(sourceName, nodes);
std::string sync = source.getSync();
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
if (sync != "disabled") {
string targetName = source.getURINonEmpty();
SyncSourceNodes targetNodes = m_client->getSyncSourceNodes(targetName);
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
SyncSourceConfig targetSource(targetName, targetNodes);
string fullTargetName = m_clientContext + "/" + targetName;
if (!targetNodes.dataConfigExists()) {
if (targetName.empty()) {
m_client->throwError("missing URI for one of the sources");
} else {
m_client->throwError(StringPrintf("%s: source not configured",
fullTargetName.c_str()));
}
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
}
// All of the config setting is done as volatile,
// so none of the regular config nodes have to
// be written. If a sync mode was set, it must have been
// done before in this loop => error in original config.
if (!targetSource.isDisabled()) {
m_client->throwError(StringPrintf("%s: source targetted twice by %s",
fullTargetName.c_str(),
m_clientContext.c_str()));
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
}
// invert data direction
if (sync == "refresh-from-local") {
sync = "refresh-from-remote";
} else if (sync == "refresh-from-remote") {
sync = "refresh-from-local";
} else if (sync == "one-way-from-local") {
sync = "one-way-from-remote";
} else if (sync == "one-way-from-remote") {
sync = "one-way-from-local";
}
targetSource.setSync(sync, true);
targetSource.setURI(sourceName, true);
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
}
}
// now sync
m_client->sync(&m_clientReport);
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
} catch(...) {
SyncMLStatus status = m_clientReport.getStatus();
string explanation;
Exception::handle(&status, redirect, &explanation);
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
m_clientReport.setStatus(status);
if (!explanation.empty() &&
m_clientReport.getError().empty()) {
m_clientReport.setError(explanation);
}
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
}
// send final report
try {
if (m_messageFD >= 0) {
close(m_messageFD);
m_messageFD = -1;
}
// matches parent's code in shutdown()
boost::shared_ptr<std::string> data(new std::string);
boost::shared_ptr<StringDataBlob> dump(new StringDataBlob("buffer", data, false));
IniHashConfigNode node(dump);
node << m_clientReport;
SE_LOG_DEBUG(NULL, NULL, "client: sending report (%s/ERROR '%s'):\n%s",
Status2String(m_clientReport.getStatus()).c_str(),
m_clientReport.getError().c_str(),
data->c_str());
node.flush();
writeMessage(m_statusFD, Message::MSG_SYNC_REPORT, data->c_str(), data->size(), Timespec());
} catch (...) {
SyncMLStatus status = m_clientReport.getStatus();
Exception::handle(&status, redirect);
m_clientReport.setStatus(status);
}
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
if (redirect) {
redirect->flush();
}
_exit(res);
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
}
void LocalTransportAgent::getClientSyncReport(SyncReport &report)
{
report = m_clientReport;
}
void LocalTransportAgent::setContentType(const std::string &type)
{
if (type == m_contentTypeSyncML) {
m_sendType = Message::MSG_SYNCML_XML;
} else if (type == m_contentTypeSyncWBXML) {
m_sendType = Message::MSG_SYNCML_WBXML;
} else {
SE_THROW(string("unsupported content type: ") + type);
}
}
void LocalTransportAgent::shutdown()
{
if (m_messageFD) {
// close message transports, tells peer to shut down
close(m_messageFD);
m_messageFD = -1;
}
if (m_pid) {
// parent: receive SyncReport
receiveChildReport();
// join forked process
int status;
SE_LOG_DEBUG(NULL, NULL, "starting to wait for child process %ld in shutdown()", (long)m_pid);
pid_t res = waitpid(m_pid, &status, 0);
SE_LOG_DEBUG(NULL, NULL, "child %ld completed, status %d", (long)res, status);
m_pid = 0;
// now relay the result from our child, will be added to
// our own sync report if it doesn't have an error already
checkChildReport();
} else {
// child: sends SyncReport at the end of run()
}
}
void LocalTransportAgent::receiveChildReport()
{
// don't try this again
if (m_statusFD >= 0) {
int statusFD = m_statusFD;
m_statusFD = -1;
try {
SE_LOG_DEBUG(NULL, NULL, "parent: receiving report");
m_receiveBuffer.m_used = 0;
if (readMessage(statusFD, m_receiveBuffer, deadline(5 * 60 /* seconds */)) == ACTIVE) {
boost::shared_ptr<std::string> data(new std::string);
data->assign(m_receiveBuffer.m_message->m_data, m_receiveBuffer.m_message->getDataLength());
boost::shared_ptr<StringDataBlob> dump(new StringDataBlob("buffer", data, false));
IniHashConfigNode node(dump);
node >> m_clientReport;
SE_LOG_DEBUG(NULL, NULL, "parent: received report (%s/ERROR '%s'):\n%s",
Status2String(m_clientReport.getStatus()).c_str(),
m_clientReport.getError().c_str(),
data->c_str());
} else {
SE_LOG_DEBUG(NULL, NULL, "parent: timeout receiving report");
}
} catch (...) {
close(statusFD);
throw;
}
close(statusFD);
}
}
void LocalTransportAgent::checkChildReport()
{
std::string childError = "child process failed";
if (!m_clientReport.getError().empty()) {
childError += ": ";
childError += m_clientReport.getError();
SE_LOG_ERROR(NULL, NULL, "%s", childError.c_str());
}
if (m_clientReport.getStatus() != STATUS_HTTP_OK &&
m_clientReport.getStatus() != STATUS_OK) {
SE_THROW_EXCEPTION_STATUS(TransportStatusException,
childError,
m_clientReport.getStatus());
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
}
}
bool LocalTransportAgent::Buffer::haveMessage()
{
bool complete = m_used >= sizeof(Message) &&
m_message->m_length <= m_used;
SE_LOG_DEBUG(NULL, NULL, "message of size %ld/%ld/%ld, %s",
(long)m_used,
m_used < sizeof(Message) ? -1l : (long)m_message->m_length,
(long)m_size,
complete ? "complete" : "incomplete");
return complete;
}
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
void LocalTransportAgent::send(const char *data, size_t len)
{
m_status = ACTIVE;
// first throw away old received message
if (m_receiveBuffer.haveMessage()) {
size_t len = m_receiveBuffer.m_message->m_length;
// memmove() probably never necessary because receiving
// ends directly after complete message, but doesn't hurt
// either...
memmove(m_receiveBuffer.m_message.get(),
(char *)m_receiveBuffer.m_message.get() + len,
m_receiveBuffer.m_used - len);
m_receiveBuffer.m_used -= len;
}
m_status = writeMessage(m_messageFD, m_sendType, data, len, deadline(5 * 60 /* seconds */));
}
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
TransportAgent::Status LocalTransportAgent::writeMessage(int fd, Message::Type type, const char *data, size_t len, Timespec deadline)
{
Message header;
memset(&header, 0, sizeof(header));
header.m_type = type;
header.m_length = sizeof(Message) + len;
struct iovec vec[2];
memset(vec, 0, sizeof(vec));
vec[0].iov_base = &header;
vec[0].iov_len = offsetof(Message, m_data);
vec[1].iov_base = (void *)data;
vec[1].iov_len = len;
SE_LOG_DEBUG(NULL, NULL, "%s: sending %ld bytes via %s",
m_pid ? "parent" : "child",
(long)len,
fd == m_messageFD ? "message channel" : "other channel");
do {
// sleep, possibly with a deadline
int res = 0;
Timespec timeout;
if (deadline) {
Timespec now = Timespec::monotonic();
if (now >= deadline) {
return TIME_OUT;
} else {
timeout = deadline - now;
}
}
SE_LOG_DEBUG(NULL, NULL, "%s: write select on %s %ld.%09lds",
m_pid ? "parent" : "child",
fd == m_messageFD ? "message channel" : "other channel",
(long)timeout.tv_sec,
(long)timeout.tv_nsec);
if (m_loop) {
switch (GLibSelect(m_loop, fd, GLIB_SELECT_WRITE, timeout ? &timeout : NULL)) {
case GLIB_SELECT_TIMEOUT:
res = 0;
break;
case GLIB_SELECT_READY:
res = 1;
break;
case GLIB_SELECT_QUIT:
SE_LOG_DEBUG(NULL, NULL, "quit transport as requested as part of GLib event loop");
return FAILED;
break;
}
} else {
fd_set writefds;
FD_ZERO(&writefds);
FD_SET(fd, &writefds);
timeval tv = timeout;
res = select(fd + 1, NULL, &writefds, NULL,
timeout ? &tv : NULL);
}
switch (res) {
case 0:
SE_LOG_DEBUG(NULL, NULL, "%s: select timeout",
m_pid ? "parent" : "child");
return TIME_OUT;
break;
case 1: {
ssize_t sent = writev(fd, vec, 2);
if (sent == -1) {
// man page doesn't say anything about these, but let's catch
// them anyway and retry
if (errno == EAGAIN ||
errno == EWOULDBLOCK) {
sent = 0;
} else {
int err = errno;
SE_LOG_DEBUG(NULL, NULL, "%s: sending %ld bytes failed: %s",
m_pid ? "parent" : "child",
(long)len,
strerror(err));
SE_THROW_EXCEPTION(TransportException,
StringPrintf("writev(): %s", strerror(err)));
}
}
// potential partial write, reduce byte counters by amount of bytes sent
ssize_t part1 = std::min((ssize_t)vec[0].iov_len, sent);
vec[0].iov_base = (char *)vec[0].iov_base + part1;
vec[0].iov_len -= part1;
sent -= part1;
ssize_t part2 = std::min((ssize_t)vec[1].iov_len, sent);
vec[1].iov_base = (char *)vec[1].iov_base + part2;
vec[1].iov_len -= part2;
break;
}
default: {
int err = errno;
SE_LOG_DEBUG(NULL, NULL, "%s: select errror: %s",
m_pid ? "parent" : "child",
strerror(err));
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
SE_THROW_EXCEPTION(TransportException,
StringPrintf("select(): %s", strerror(err)));
break;
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
}
}
} while (vec[1].iov_len);
SE_LOG_DEBUG(NULL, NULL, "%s: sending %ld bytes done",
m_pid ? "parent" : "child",
(long)len);
return ACTIVE;
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
}
void LocalTransportAgent::cancel()
{
}
TransportAgent::Status LocalTransportAgent::wait(bool noReply)
{
if (m_status == ACTIVE) {
// need next message; for noReply == true we are done
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
if (noReply) {
m_status = INACTIVE;
} else {
if (!m_receiveBuffer.haveMessage()) {
m_status = readMessage(m_messageFD, m_receiveBuffer, deadline(m_timeoutSeconds));
if (m_status == ACTIVE) {
// complete message received, check if it is SyncML
switch (m_receiveBuffer.m_message->m_type) {
case Message::MSG_SYNCML_XML:
case Message::MSG_SYNCML_WBXML:
m_status = GOT_REPLY;
break;
default:
// TODO: handle other types
SE_THROW("unsupported message type");
break;
}
}
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
}
}
}
return m_status;
}
TransportAgent::Status LocalTransportAgent::readMessage(int fd, Buffer &buffer, Timespec deadline)
{
while (!buffer.haveMessage()) {
int res = 0;
Timespec timeout;
if (deadline) {
Timespec now = Timespec::monotonic();
if (now >= deadline) {
// already too late
return TIME_OUT;
} else {
timeout = deadline - now;
}
}
SE_LOG_DEBUG(NULL, NULL, "%s: read select on %s %ld.%09lds",
m_pid ? "parent" : "child",
fd == m_messageFD ? "message channel" : "other channel",
(long)timeout.tv_sec,
(long)timeout.tv_nsec);
if (m_loop) {
switch (GLibSelect(m_loop, fd, GLIB_SELECT_READ, timeout ? &timeout : NULL)) {
case GLIB_SELECT_TIMEOUT:
res = 0;
break;
case GLIB_SELECT_READY:
res = 1;
break;
case GLIB_SELECT_QUIT:
SE_LOG_DEBUG(NULL, NULL, "quit transport as requested as part of GLib event loop");
return FAILED;
break;
}
} else {
// use select to implement timeout
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
timeval tv = timeout;
res = select(fd + 1, &readfds, NULL, NULL,
timeout ? &tv : NULL);
}
switch (res) {
case 0:
SE_LOG_DEBUG(NULL, NULL, "%s: select timeout",
m_pid ? "parent" : "child");
return TIME_OUT;
break;
case 1: {
// data ready, ensure that buffer is available
if (!buffer.m_size) {
buffer.m_size = m_server->getMaxMsgSize();
if (!buffer.m_size) {
buffer.m_size = 1024;
}
buffer.m_message.set(static_cast<Message *>(malloc(buffer.m_size)),
"Message Buffer");
} else if (buffer.m_used >= sizeof(Message) &&
buffer.m_message->m_length > buffer.m_size) {
// copy before (temporarily) freeing memory
size_t newsize = buffer.m_message->m_length;
buffer.m_message.set(static_cast<Message *>(realloc(buffer.m_message.release(), newsize)),
"Message Buffer");
buffer.m_size = newsize;
}
SE_LOG_DEBUG(NULL, NULL, "%s: recv %ld bytes",
m_pid ? "parent" : "child",
(long)(buffer.m_size - buffer.m_used));
ssize_t recvd = recv(fd,
(char *)buffer.m_message.get() + buffer.m_used,
buffer.m_size - buffer.m_used,
MSG_DONTWAIT);
int err = errno;
SE_LOG_DEBUG(NULL, NULL, "%s: received %ld: %s",
m_pid ? "parent" : "child",
(long)recvd,
recvd < 0 ? strerror(err) : "okay");
if (recvd < 0) {
if (err == EAGAIN ||
err == EWOULDBLOCK) {
// try again
recvd = 0;
} else {
SE_THROW_EXCEPTION(TransportException,
StringPrintf("message receive: %s", strerror(err)));
}
} else if (!recvd) {
if (m_pid) {
// Child died. Try to get its sync report to find out why.
receiveChildReport();
checkChildReport();
// if no exception yet, raise a generic one
SE_THROW_EXCEPTION(TransportException,
"child has died unexpectedly");
} else {
SE_THROW_EXCEPTION(TransportException,
"parent has died unexpectedly");
}
}
buffer.m_used += recvd;
break;
}
default: {
int err = errno;
SE_LOG_DEBUG(NULL, NULL, "%s: select errror: %s",
m_pid ? "parent" : "child",
strerror(err));
SE_THROW_EXCEPTION(TransportException,
StringPrintf("select(): %s", strerror(err)));
break;
}
}
}
return ACTIVE;
}
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
void LocalTransportAgent::getReply(const char *&data, size_t &len, std::string &contentType)
{
if (m_status != GOT_REPLY) {
SE_THROW("internal error, no reply available");
}
switch (m_receiveBuffer.m_message->m_type) {
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
case Message::MSG_SYNCML_XML:
contentType = m_contentTypeSyncML;
break;
case Message::MSG_SYNCML_WBXML:
contentType = m_contentTypeSyncWBXML;
break;
default:
contentType = "";
SE_THROW("internal error, no the right message");
break;
}
if (!contentType.empty()) {
len = m_receiveBuffer.m_message->getDataLength();
data = m_receiveBuffer.m_message->m_data;
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
}
}
void LocalTransportAgent::setTimeout(int seconds)
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
{
// setTimeout() was meant for unreliable transports like HTTP
// which cannot determine whether the peer is still alive. The
// LocalTransportAgent uses sockets and will notice when a peer
// dies unexpectedly, so timeouts should never be necessary.
//
// Quite the opposite, because the "client" in a local sync
// with WebDAV on the client side can be quite slow, incorrect
// timeouts were seen where the client side took longer than
// the default timeout of 5 minutes to process a message and
// send a reply.
//
// Therefore we ignore the request to set a timeout here and thus
// local send/receive operations are allowed to continue for as
// long as they like.
//
// m_timeoutSeconds = seconds;
support local sync (BMC #712) Local sync is configured with a new syncURL = local://<context> where <context> identifies the set of databases to synchronize with. The URI of each source in the config identifies the source in that context to synchronize with. The databases in that context run a SyncML session as client. The config itself is for a server. Reversing these roles is possible by putting the config into the other context. A sync is started by the server side, via the new LocalTransportAgent. That agent forks, sets up the client side, then passes messages back and forth via stream sockets. Stream sockets are useful because unexpected peer shutdown can be detected. Running the server side requires a few changes: - do not send a SAN message, the client will start the message exchange based on the config - wait for that message before doing anything The client side is more difficult: - Per-peer config nodes do not exist in the target context. They are stored in a hidden .<context> directory inside the server config tree. This depends on the new "registering nodes in the tree" feature. All nodes are hidden, because users are not meant to edit any of them. Their name is intentionally chosen like traditional nodes so that removing the config also removes the new files. - All relevant per-peer properties must be copied from the server config (log level, printing changes, ...); they cannot be set differently. Because two separate SyncML sessions are used, we end up with two normal session directories and log files. The implementation is not complete yet: - no glib support, so cannot be used in syncevo-dbus-server - no support for CTRL-C and abort - no interactive password entry for target sources - unexpected slow syncs are detected on the client side, but not reported properly on the server side
2010-07-31 18:28:53 +02:00
}
SE_END_CXX