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>
|
2010-11-03 12:10:15 +01:00
|
|
|
#include <syncevo/StringDataBlob.h>
|
|
|
|
#include <syncevo/IniConfigNode.h>
|
2011-02-15 16:50:39 +01:00
|
|
|
#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>
|
2010-10-20 14:14:28 +02:00
|
|
|
#include <sys/socket.h>
|
2010-10-29 11:20:11 +02:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/wait.h>
|
2011-02-09 15:33:20 +01:00
|
|
|
#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
|
|
|
|
2010-11-03 10:01:27 +01: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),
|
2010-08-02 13:22:01 +02:00
|
|
|
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)),
|
2011-02-09 15:33:20 +01:00
|
|
|
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),
|
2010-11-03 12:10:15 +01:00
|
|
|
m_messageFD(-1),
|
|
|
|
m_statusFD(-1),
|
2010-10-29 11:20:11 +02:00
|
|
|
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()
|
|
|
|
{
|
2010-11-03 12:10:15 +01:00
|
|
|
if (m_statusFD >= 0) {
|
|
|
|
close(m_statusFD);
|
|
|
|
}
|
|
|
|
if (m_messageFD >= 0) {
|
|
|
|
close(m_messageFD);
|
|
|
|
}
|
2010-10-29 11:20:11 +02:00
|
|
|
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()
|
|
|
|
{
|
2010-11-03 12:10:15 +01:00
|
|
|
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
|
|
|
|
2010-08-02 13:22:01 +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()));
|
|
|
|
}
|
2010-10-25 10:41:17 +02:00
|
|
|
if (m_clientContext == m_server->getContextName()) {
|
2010-08-02 13:22:01 +02:00
|
|
|
SE_THROW(StringPrintf("invalid local sync inside context '%s', need second context with different databases", context.c_str()));
|
|
|
|
}
|
|
|
|
|
2011-06-16 15:32:22 +02:00
|
|
|
// initialize target client so that we can check passwords in the calling process
|
2011-06-29 03:42:43 +02:00
|
|
|
boost::shared_ptr<SyncContext> client(new SyncContext(std::string("target-config") + m_clientContext,
|
2011-06-16 15:32:22 +02:00
|
|
|
m_server->getConfigName(),
|
|
|
|
m_server->getRootPath() + "/." + m_clientContext,
|
|
|
|
boost::shared_ptr<TransportAgent>(this, NoopAgentDestructor()),
|
|
|
|
m_server->getDoLogging()));
|
|
|
|
|
2011-06-29 03:42:43 +02:00
|
|
|
// allow proceeding with sync even if no "target-config" was created,
|
2011-06-16 15:32:22 +02:00
|
|
|
// 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
|
2011-06-29 03:42:43 +02:00
|
|
|
// "target-config" config.
|
2011-06-16 15:32:22 +02:00
|
|
|
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());
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
2010-11-03 12:10:15 +01:00
|
|
|
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
|
|
|
|
2011-02-09 15:33:20 +01: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];
|
2011-04-20 10:26:33 +02:00
|
|
|
fd <= &sockets[1][1];
|
2011-02-09 15:33:20 +01:00
|
|
|
++fd) {
|
2011-04-20 10:26:33 +02:00
|
|
|
long flags = fcntl(*fd, F_GETFD, 0l); // extra argument for valgrind
|
2011-02-09 15:33:20 +01:00
|
|
|
fcntl(*fd, F_SETFD, flags | FD_CLOEXEC);
|
2011-04-20 10:26:33 +02:00
|
|
|
flags = fcntl(*fd, F_GETFL, 0l);
|
2011-02-09 15:33:20 +01:00
|
|
|
fcntl(*fd, F_SETFL, flags | O_NONBLOCK);
|
|
|
|
}
|
|
|
|
|
2010-11-03 12:10:15 +01:00
|
|
|
pid_t pid = fork();
|
|
|
|
switch (pid) {
|
|
|
|
case -1:
|
|
|
|
m_server->throwError("fork()", errno);
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
// child
|
2010-12-09 18:12:41 +01:00
|
|
|
Logger::setProcessName(m_clientContext);
|
2010-11-03 12:10:15 +01:00
|
|
|
close(sockets[0][0]);
|
|
|
|
m_messageFD = sockets[0][1];
|
|
|
|
close(sockets[1][0]);
|
|
|
|
m_statusFD = sockets[1][1];
|
2011-06-16 15:32:22 +02:00
|
|
|
m_client = client;
|
2010-11-03 12:10:15 +01:00
|
|
|
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()
|
|
|
|
{
|
2011-02-15 16:50:39 +01:00
|
|
|
// 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.
|
|
|
|
|
2010-12-09 11:52:45 +01:00
|
|
|
// 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;
|
2010-12-09 11:52:45 +01:00
|
|
|
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)))) {
|
2010-12-09 11:52:45 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-02-11 11:35:05 +01:00
|
|
|
// do not mix our own output into the output of the parent
|
|
|
|
if (redirect) {
|
|
|
|
redirect->redoRedirect();
|
|
|
|
}
|
|
|
|
|
2011-02-15 16:50:39 +01:00
|
|
|
// Ignore parent's timeout and event loop.
|
2011-02-09 15:33:20 +01:00
|
|
|
m_timeoutSeconds = 0;
|
2011-02-15 16:50:39 +01:00
|
|
|
m_loop = 0;
|
2011-02-09 15:33:20 +01:00
|
|
|
|
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 {
|
2010-12-09 12:04:34 +01:00
|
|
|
SE_LOG_DEBUG(NULL, NULL, "client is running, %s log redirection",
|
|
|
|
redirect ? "with" : "without");
|
2010-10-29 11:17:34 +02:00
|
|
|
|
2010-12-09 12:04:34 +01:00
|
|
|
// debugging mode: write logs inside sub-directory of parent,
|
|
|
|
// otherwise use normal log settings
|
2011-06-16 15:32:22 +02:00
|
|
|
if (!m_server->getDoLogging()) {
|
|
|
|
m_client->setLogDir(std::string(m_server->getLogDir()) + "/child", true);
|
2010-12-09 12:04:34 +01:00
|
|
|
}
|
|
|
|
|
2010-10-22 11:41:50 +02:00
|
|
|
// disable all sources temporarily, will be enabled by next loop
|
2011-06-16 15:32:22 +02:00
|
|
|
BOOST_FOREACH(const string &targetName, m_client->getSyncSources()) {
|
|
|
|
SyncSourceNodes targetNodes = m_client->getSyncSourceNodes(targetName);
|
2010-10-22 11:41:50 +02:00
|
|
|
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);
|
2011-10-24 19:52:01 +02:00
|
|
|
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") {
|
2011-04-21 12:20:00 +02:00
|
|
|
string targetName = source.getURINonEmpty();
|
2011-06-16 15:32:22 +02:00
|
|
|
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()) {
|
2011-04-19 13:48:51 +02:00
|
|
|
if (targetName.empty()) {
|
2011-06-16 15:32:22 +02:00
|
|
|
m_client->throwError("missing URI for one of the sources");
|
2011-04-19 13:48:51 +02:00
|
|
|
} else {
|
2011-06-16 15:32:22 +02:00
|
|
|
m_client->throwError(StringPrintf("%s: source not configured",
|
|
|
|
fullTargetName.c_str()));
|
2011-04-19 13:48:51 +02:00
|
|
|
}
|
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.
|
2011-10-24 19:52:01 +02:00
|
|
|
if (!targetSource.isDisabled()) {
|
2011-06-16 15:32:22 +02:00
|
|
|
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
|
|
|
}
|
2011-10-24 19:52:01 +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
|
2011-06-16 15:32:22 +02:00
|
|
|
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();
|
2011-04-19 13:54:09 +02:00
|
|
|
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);
|
2011-04-19 13:54:09 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2010-11-03 12:10:15 +01: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();
|
2011-02-16 12:07:20 +01:00
|
|
|
writeMessage(m_statusFD, Message::MSG_SYNC_REPORT, data->c_str(), data->size(), Timespec());
|
2010-11-03 12:10:15 +01:00
|
|
|
} 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();
|
|
|
|
}
|
2010-10-29 11:20:11 +02:00
|
|
|
_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()
|
|
|
|
{
|
2010-11-03 12:10:15 +01:00
|
|
|
if (m_messageFD) {
|
|
|
|
// close message transports, tells peer to shut down
|
2010-10-29 11:20:11 +02:00
|
|
|
close(m_messageFD);
|
2010-11-03 12:10:15 +01:00
|
|
|
m_messageFD = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_pid) {
|
|
|
|
// parent: receive SyncReport
|
|
|
|
receiveChildReport();
|
|
|
|
|
|
|
|
// join forked process
|
2010-10-29 11:20:11 +02:00
|
|
|
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;
|
2010-11-03 12:10:15 +01:00
|
|
|
|
|
|
|
// now relay the result from our child, will be added to
|
|
|
|
// our own sync report if it doesn't have an error already
|
|
|
|
checkChildReport();
|
2010-10-29 11:20:11 +02:00
|
|
|
} else {
|
2010-11-03 12:10:15 +01:00
|
|
|
// child: sends SyncReport at the end of run()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LocalTransportAgent::receiveChildReport()
|
|
|
|
{
|
2010-11-10 15:25:01 +01:00
|
|
|
// 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;
|
2011-06-16 22:48:53 +02:00
|
|
|
if (readMessage(statusFD, m_receiveBuffer, deadline(5 * 60 /* seconds */)) == ACTIVE) {
|
2011-02-09 15:33:20 +01:00
|
|
|
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");
|
|
|
|
}
|
2010-11-10 15:25:01 +01:00
|
|
|
} catch (...) {
|
|
|
|
close(statusFD);
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
close(statusFD);
|
|
|
|
}
|
2010-11-03 12:10:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-07 18:21:40 +01: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)
|
|
|
|
{
|
2011-02-09 15:33:20 +01:00
|
|
|
m_status = ACTIVE;
|
2011-02-15 16:50:39 +01:00
|
|
|
// 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;
|
2010-11-03 10:01:27 +01:00
|
|
|
}
|
2011-06-16 22:48:53 +02:00
|
|
|
m_status = writeMessage(m_messageFD, m_sendType, data, len, deadline(5 * 60 /* seconds */));
|
2010-11-03 10:01:27 +01:00
|
|
|
}
|
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
|
|
|
|
2011-02-16 12:07:20 +01:00
|
|
|
TransportAgent::Status LocalTransportAgent::writeMessage(int fd, Message::Type type, const char *data, size_t len, Timespec deadline)
|
2010-11-03 10:01:27 +01:00
|
|
|
{
|
|
|
|
Message header;
|
2011-04-20 10:26:33 +02:00
|
|
|
memset(&header, 0, sizeof(header));
|
2010-11-03 10:01:27 +01:00
|
|
|
header.m_type = type;
|
|
|
|
header.m_length = sizeof(Message) + len;
|
|
|
|
struct iovec vec[2];
|
2011-04-20 10:26:33 +02:00
|
|
|
memset(vec, 0, sizeof(vec));
|
2010-11-03 10:01:27 +01:00
|
|
|
vec[0].iov_base = &header;
|
|
|
|
vec[0].iov_len = offsetof(Message, m_data);
|
|
|
|
vec[1].iov_base = (void *)data;
|
|
|
|
vec[1].iov_len = len;
|
2011-04-20 10:26:33 +02:00
|
|
|
|
2010-11-03 10:01:27 +01:00
|
|
|
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 {
|
2011-02-09 15:33:20 +01:00
|
|
|
// sleep, possibly with a deadline
|
2011-02-15 16:50:39 +01:00
|
|
|
int res = 0;
|
2011-02-16 12:07:20 +01:00
|
|
|
Timespec timeout;
|
2011-02-09 15:33:20 +01:00
|
|
|
if (deadline) {
|
2011-02-16 12:07:20 +01:00
|
|
|
Timespec now = Timespec::monotonic();
|
2011-02-09 15:33:20 +01:00
|
|
|
if (now >= deadline) {
|
2011-02-16 09:50:43 +01:00
|
|
|
return TIME_OUT;
|
2011-02-09 15:33:20 +01:00
|
|
|
} else {
|
2011-02-16 12:07:20 +01:00
|
|
|
timeout = deadline - now;
|
2011-02-09 15:33:20 +01:00
|
|
|
}
|
|
|
|
}
|
2011-02-16 12:07:20 +01:00
|
|
|
SE_LOG_DEBUG(NULL, NULL, "%s: write select on %s %ld.%09lds",
|
2011-02-09 15:33:20 +01:00
|
|
|
m_pid ? "parent" : "child",
|
|
|
|
fd == m_messageFD ? "message channel" : "other channel",
|
|
|
|
(long)timeout.tv_sec,
|
2011-02-16 12:07:20 +01:00
|
|
|
(long)timeout.tv_nsec);
|
2011-02-15 16:50:39 +01:00
|
|
|
if (m_loop) {
|
2011-02-16 12:07:20 +01:00
|
|
|
switch (GLibSelect(m_loop, fd, GLIB_SELECT_WRITE, timeout ? &timeout : NULL)) {
|
2011-02-15 16:50:39 +01:00
|
|
|
case GLIB_SELECT_TIMEOUT:
|
|
|
|
res = 0;
|
|
|
|
break;
|
|
|
|
case GLIB_SELECT_READY:
|
|
|
|
res = 1;
|
|
|
|
break;
|
|
|
|
case GLIB_SELECT_QUIT:
|
2011-02-16 09:50:43 +01:00
|
|
|
SE_LOG_DEBUG(NULL, NULL, "quit transport as requested as part of GLib event loop");
|
|
|
|
return FAILED;
|
2011-02-15 16:50:39 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
fd_set writefds;
|
|
|
|
FD_ZERO(&writefds);
|
|
|
|
FD_SET(fd, &writefds);
|
2011-02-16 12:07:20 +01:00
|
|
|
timeval tv = timeout;
|
2011-02-15 16:50:39 +01:00
|
|
|
res = select(fd + 1, NULL, &writefds, NULL,
|
2011-02-16 12:07:20 +01:00
|
|
|
timeout ? &tv : NULL);
|
2011-02-15 16:50:39 +01:00
|
|
|
}
|
2011-02-09 15:33:20 +01:00
|
|
|
switch (res) {
|
|
|
|
case 0:
|
|
|
|
SE_LOG_DEBUG(NULL, NULL, "%s: select timeout",
|
|
|
|
m_pid ? "parent" : "child");
|
2011-02-16 09:50:43 +01:00
|
|
|
return TIME_OUT;
|
2011-02-09 15:33:20 +01:00
|
|
|
break;
|
|
|
|
case 1: {
|
|
|
|
ssize_t sent = writev(fd, vec, 2);
|
|
|
|
if (sent == -1) {
|
2011-04-20 14:23:59 +02:00
|
|
|
// man page doesn't say anything about these, but let's catch
|
|
|
|
// them anyway and retry
|
|
|
|
if (errno == EAGAIN ||
|
|
|
|
errno == EWOULDBLOCK) {
|
|
|
|
sent = 0;
|
|
|
|
} else {
|
2011-04-20 16:45:24 +02:00
|
|
|
int err = errno;
|
2011-04-20 14:23:59 +02:00
|
|
|
SE_LOG_DEBUG(NULL, NULL, "%s: sending %ld bytes failed: %s",
|
|
|
|
m_pid ? "parent" : "child",
|
|
|
|
(long)len,
|
2011-04-20 16:45:24 +02:00
|
|
|
strerror(err));
|
2011-04-20 14:23:59 +02:00
|
|
|
SE_THROW_EXCEPTION(TransportException,
|
2011-04-20 16:45:24 +02:00
|
|
|
StringPrintf("writev(): %s", strerror(err)));
|
2011-04-20 14:23:59 +02:00
|
|
|
}
|
2011-02-09 15:33:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// potential partial write, reduce byte counters by amount of bytes sent
|
|
|
|
ssize_t part1 = std::min((ssize_t)vec[0].iov_len, sent);
|
2011-04-20 10:26:33 +02:00
|
|
|
vec[0].iov_base = (char *)vec[0].iov_base + part1;
|
2011-02-09 15:33:20 +01:00
|
|
|
vec[0].iov_len -= part1;
|
|
|
|
sent -= part1;
|
|
|
|
ssize_t part2 = std::min((ssize_t)vec[1].iov_len, sent);
|
2011-04-20 10:26:33 +02:00
|
|
|
vec[1].iov_base = (char *)vec[1].iov_base + part2;
|
2011-02-09 15:33:20 +01:00
|
|
|
vec[1].iov_len -= part2;
|
|
|
|
break;
|
|
|
|
}
|
2011-04-20 16:45:24 +02:00
|
|
|
default: {
|
|
|
|
int err = errno;
|
2011-02-09 15:33:20 +01:00
|
|
|
SE_LOG_DEBUG(NULL, NULL, "%s: select errror: %s",
|
2010-10-29 11:20:11 +02:00
|
|
|
m_pid ? "parent" : "child",
|
2011-04-20 16:45:24 +02:00
|
|
|
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,
|
2011-04-20 16:45:24 +02:00
|
|
|
StringPrintf("select(): %s", strerror(err)));
|
2011-02-09 15:33:20 +01:00
|
|
|
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
|
|
|
}
|
2011-04-20 16:45:24 +02:00
|
|
|
}
|
2010-11-03 10:01:27 +01:00
|
|
|
} while (vec[1].iov_len);
|
|
|
|
|
|
|
|
SE_LOG_DEBUG(NULL, NULL, "%s: sending %ld bytes done",
|
|
|
|
m_pid ? "parent" : "child",
|
|
|
|
(long)len);
|
2011-02-16 09:50:43 +01:00
|
|
|
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)
|
|
|
|
{
|
2011-02-09 15:33:20 +01:00
|
|
|
if (m_status == ACTIVE) {
|
2010-11-03 12:10:15 +01:00
|
|
|
// 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 {
|
2010-11-03 10:01:27 +01:00
|
|
|
if (!m_receiveBuffer.haveMessage()) {
|
2011-06-16 22:48:53 +02:00
|
|
|
m_status = readMessage(m_messageFD, m_receiveBuffer, deadline(m_timeoutSeconds));
|
2011-02-16 09:50:43 +01:00
|
|
|
if (m_status == ACTIVE) {
|
2011-02-09 15:33:20 +01:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2011-02-16 12:07:20 +01:00
|
|
|
TransportAgent::Status LocalTransportAgent::readMessage(int fd, Buffer &buffer, Timespec deadline)
|
2010-11-03 10:01:27 +01:00
|
|
|
{
|
|
|
|
while (!buffer.haveMessage()) {
|
2011-02-15 16:50:39 +01:00
|
|
|
int res = 0;
|
2011-02-16 12:07:20 +01:00
|
|
|
Timespec timeout;
|
2011-02-09 15:33:20 +01:00
|
|
|
if (deadline) {
|
2011-02-16 12:07:20 +01:00
|
|
|
Timespec now = Timespec::monotonic();
|
2011-02-09 15:33:20 +01:00
|
|
|
if (now >= deadline) {
|
|
|
|
// already too late
|
2011-02-16 09:50:43 +01:00
|
|
|
return TIME_OUT;
|
2011-02-09 15:33:20 +01:00
|
|
|
} else {
|
2011-02-16 12:07:20 +01:00
|
|
|
timeout = deadline - now;
|
2011-02-09 15:33:20 +01:00
|
|
|
}
|
|
|
|
}
|
2011-02-16 12:07:20 +01:00
|
|
|
SE_LOG_DEBUG(NULL, NULL, "%s: read select on %s %ld.%09lds",
|
2010-11-03 10:01:27 +01:00
|
|
|
m_pid ? "parent" : "child",
|
2011-02-09 15:33:20 +01:00
|
|
|
fd == m_messageFD ? "message channel" : "other channel",
|
|
|
|
(long)timeout.tv_sec,
|
2011-02-16 12:07:20 +01:00
|
|
|
(long)timeout.tv_nsec);
|
2011-02-15 16:50:39 +01:00
|
|
|
if (m_loop) {
|
2011-02-16 12:07:20 +01:00
|
|
|
switch (GLibSelect(m_loop, fd, GLIB_SELECT_READ, timeout ? &timeout : NULL)) {
|
2011-02-15 16:50:39 +01:00
|
|
|
case GLIB_SELECT_TIMEOUT:
|
|
|
|
res = 0;
|
|
|
|
break;
|
|
|
|
case GLIB_SELECT_READY:
|
|
|
|
res = 1;
|
|
|
|
break;
|
|
|
|
case GLIB_SELECT_QUIT:
|
2011-02-16 09:50:43 +01:00
|
|
|
SE_LOG_DEBUG(NULL, NULL, "quit transport as requested as part of GLib event loop");
|
|
|
|
return FAILED;
|
2011-02-15 16:50:39 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// use select to implement timeout
|
|
|
|
fd_set readfds;
|
|
|
|
FD_ZERO(&readfds);
|
|
|
|
FD_SET(fd, &readfds);
|
2011-02-16 12:07:20 +01:00
|
|
|
timeval tv = timeout;
|
2011-02-15 16:50:39 +01:00
|
|
|
res = select(fd + 1, &readfds, NULL, NULL,
|
2011-02-16 12:07:20 +01:00
|
|
|
timeout ? &tv : NULL);
|
2011-02-15 16:50:39 +01:00
|
|
|
}
|
2010-11-03 10:01:27 +01:00
|
|
|
switch (res) {
|
|
|
|
case 0:
|
|
|
|
SE_LOG_DEBUG(NULL, NULL, "%s: select timeout",
|
|
|
|
m_pid ? "parent" : "child");
|
2011-02-16 09:50:43 +01:00
|
|
|
return TIME_OUT;
|
2010-11-03 10:01:27 +01:00
|
|
|
break;
|
|
|
|
case 1: {
|
|
|
|
// data ready, ensure that buffer is available
|
|
|
|
if (!buffer.m_size) {
|
|
|
|
buffer.m_size = m_server->getMaxMsgSize();
|
2010-12-10 12:07:08 +01:00
|
|
|
if (!buffer.m_size) {
|
|
|
|
buffer.m_size = 1024;
|
|
|
|
}
|
2010-11-03 10:01:27 +01:00
|
|
|
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) {
|
2011-04-20 14:20:46 +02:00
|
|
|
// 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)),
|
2010-11-03 10:01:27 +01:00
|
|
|
"Message Buffer");
|
2011-04-20 14:20:46 +02:00
|
|
|
buffer.m_size = newsize;
|
2010-11-03 10:01:27 +01:00
|
|
|
}
|
|
|
|
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);
|
2011-04-20 16:45:24 +02:00
|
|
|
int err = errno;
|
2010-11-03 10:01:27 +01:00
|
|
|
SE_LOG_DEBUG(NULL, NULL, "%s: received %ld: %s",
|
|
|
|
m_pid ? "parent" : "child",
|
|
|
|
(long)recvd,
|
2011-04-20 16:45:24 +02:00
|
|
|
recvd < 0 ? strerror(err) : "okay");
|
2010-11-03 10:01:27 +01:00
|
|
|
if (recvd < 0) {
|
2011-04-20 16:45:24 +02:00
|
|
|
if (err == EAGAIN ||
|
|
|
|
err == EWOULDBLOCK) {
|
2011-04-20 14:23:59 +02:00
|
|
|
// try again
|
|
|
|
recvd = 0;
|
|
|
|
} else {
|
|
|
|
SE_THROW_EXCEPTION(TransportException,
|
2011-04-20 16:45:24 +02:00
|
|
|
StringPrintf("message receive: %s", strerror(err)));
|
2011-04-20 14:23:59 +02:00
|
|
|
}
|
2010-11-03 10:01:27 +01:00
|
|
|
} else if (!recvd) {
|
2010-11-03 12:10:15 +01:00
|
|
|
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");
|
|
|
|
}
|
2010-11-03 10:01:27 +01:00
|
|
|
}
|
|
|
|
buffer.m_used += recvd;
|
|
|
|
break;
|
|
|
|
}
|
2011-04-20 16:45:24 +02:00
|
|
|
default: {
|
|
|
|
int err = errno;
|
2010-11-03 10:01:27 +01:00
|
|
|
SE_LOG_DEBUG(NULL, NULL, "%s: select errror: %s",
|
|
|
|
m_pid ? "parent" : "child",
|
2011-04-20 16:45:24 +02:00
|
|
|
strerror(err));
|
2010-11-03 10:01:27 +01:00
|
|
|
SE_THROW_EXCEPTION(TransportException,
|
2011-04-20 16:45:24 +02:00
|
|
|
StringPrintf("select(): %s", strerror(err)));
|
2010-11-03 10:01:27 +01:00
|
|
|
break;
|
|
|
|
}
|
2011-04-20 16:45:24 +02:00
|
|
|
}
|
2010-11-03 10:01:27 +01:00
|
|
|
}
|
2011-02-09 15:33:20 +01:00
|
|
|
|
2011-02-16 09:50:43 +01:00
|
|
|
return ACTIVE;
|
2010-11-03 10:01:27 +01:00
|
|
|
}
|
|
|
|
|
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");
|
|
|
|
}
|
2010-11-03 10:01:27 +01:00
|
|
|
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()) {
|
2010-11-03 10:01:27 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-09 15:02:13 +01: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
|
|
|
{
|
2011-06-16 22:48: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
|