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>
|
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>
|
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)),
|
|
|
|
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()));
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
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];
|
|
|
|
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()
|
|
|
|
{
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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");
|
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
|
|
|
// TODO: password and abort handling in a derived class
|
2010-12-09 12:04:34 +01:00
|
|
|
bool doLogging = m_server->getDoLogging();
|
2010-10-22 11:41:50 +02:00
|
|
|
SyncContext client(std::string("source-config") + m_clientContext,
|
local sync: avoid confusion about what data is changed
In local sync the terms "local" and "remote" (in SyncReport, "Data
modified locally") do not always apply and can be confusing. Replaced
with explicitly mentioning the context.
The source name also no longer is unique. Extended in the local sync
case (and only in that case) by adding a <context>/ prefix to the
source name.
Here is an example of the modified output:
$ syncevolution google
[INFO] @default/itodo20: inactive
[INFO] @default/addressbook: inactive
[INFO] @default/calendar+todo: inactive
[INFO] @default/memo: inactive
[INFO] @default/ical20: inactive
[INFO] @default/todo: inactive
[INFO] @default/file_calendar+todo: inactive
[INFO] @default/file_vcard21: inactive
[INFO] @default/vcard30: inactive
[INFO] @default/text: inactive
[INFO] @default/file_itodo20: inactive
[INFO] @default/vcard21: inactive
[INFO] @default/file_ical20: inactive
[INFO] @default/file_vcard30: inactive
[INFO] @google/addressbook: inactive
[INFO] @google/memo: inactive
[INFO] @google/todo: inactive
[INFO] @google/calendar: starting normal sync, two-way
Local data changes to be applied remotely during synchronization:
*** @google/calendar ***
after last sync | current data
removed since last sync <
> added since last sync
-------------------------------------------------------------------------------
BEGIN:VCALENDAR BEGIN:VCALENDAR
...
END:VCALENDAR END:VCALENDAR
-------------------------------------------------------------------------------
[INFO] @google/calendar: sent 1/2
[INFO] @google/calendar: sent 2/2
Local data changes to be applied remotely during synchronization:
*** @default/calendar ***
no changes
[INFO] @default/calendar: started
[INFO] @default/calendar: updating "created in Google, online"
[INFO] @default/calendar: updating "created in Google - mod2, online"
[INFO] @google/calendar: started
[INFO] @default/calendar: inactive
[INFO] @google/calendar: normal sync done successfully
Synchronization successful.
Changes applied during synchronization:
+---------------|-----------------------|-----------------------|-CON-+
| | @default | @google | FLI |
| Source | NEW | MOD | DEL | ERR | NEW | MOD | DEL | ERR | CTS |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| calendar | 0 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| disabled, 0 KB sent by client, 2 KB received |
| item(s) in database backup: 3 before sync, 3 after it |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| start Mon Oct 25 10:03:24 2010, duration 0:13min |
| synchronization completed successfully |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
Data modified @default during synchronization:
*** @default/calendar ***
before sync | after sync
removed during sync <
> added during sync
-------------------------------------------------------------------------------
BEGIN:VCALENDAR BEGIN:VCALENDAR
VERSION:2.0 VERSION:2.0
...
END:VCALENDAR END:VCALENDAR
-------------------------------------------------------------------------------
pohly@pohly-mobl1:/tmp/syncevolution/src$
Synchronization successful.
Changes applied during synchronization:
+---------------|-----------------------|-----------------------|-CON-+
| | @google | @default | FLI |
| Source | NEW | MOD | DEL | ERR | NEW | MOD | DEL | ERR | CTS |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| calendar | 0 | 0 | 0 | 0 | 0 | 2 | 0 | 0 | 0 |
| two-way, 2 KB sent by client, 0 KB received |
| item(s) in database backup: 2 before sync, 2 after it |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| start Mon Oct 25 10:03:24 2010, duration 0:13min |
| synchronization completed successfully |
+---------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
Data modified @google during synchronization:
*** @google/calendar ***
no changes
2010-10-25 10:34:23 +02:00
|
|
|
m_server->getConfigName(),
|
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_server->getRootPath() + "/." + m_clientContext,
|
|
|
|
boost::shared_ptr<TransportAgent>(this, NoopAgentDestructor()),
|
2010-12-09 12:04:34 +01:00
|
|
|
doLogging);
|
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-01-25 11:38:49 +01:00
|
|
|
// 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
|
|
|
|
// "source-config" config.
|
|
|
|
string tmp = m_server->getUsername();
|
|
|
|
if (!tmp.empty()) {
|
|
|
|
client.setUsername(tmp, true);
|
|
|
|
}
|
|
|
|
tmp = m_server->getPassword();
|
|
|
|
if (!tmp.empty()) {
|
|
|
|
client.setPassword(tmp, true);
|
|
|
|
}
|
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
|
|
|
|
if (!doLogging) {
|
|
|
|
client.setLogDir(std::string(m_server->getLogDir()) + "/child", true);
|
|
|
|
}
|
|
|
|
|
2010-10-22 11:41:50 +02:00
|
|
|
// disable all sources temporarily, will be enabled by next loop
|
|
|
|
BOOST_FOREACH(const string &targetName, client.getSyncSources()) {
|
|
|
|
SyncSourceNodes targetNodes = client.getSyncSourceNodes(targetName);
|
|
|
|
SyncSourceConfig targetSource(targetName, targetNodes);
|
|
|
|
targetSource.setSync("disabled", true);
|
|
|
|
}
|
|
|
|
|
support local sync (BMC #712)
Local sync is configured with a new syncURL = local://<context> where
<context> identifies the set of databases to synchronize with. The
URI of each source in the config identifies the source in that context
to synchronize with.
The databases in that context run a SyncML session as client. The
config itself is for a server. Reversing these roles is possible by
putting the config into the other context.
A sync is started by the server side, via the new LocalTransportAgent.
That agent forks, sets up the client side, then passes messages
back and forth via stream sockets. Stream sockets are useful because
unexpected peer shutdown can be detected.
Running the server side requires a few changes:
- do not send a SAN message, the client will start the
message exchange based on the config
- wait for that message before doing anything
The client side is more difficult:
- Per-peer config nodes do not exist in the target context.
They are stored in a hidden .<context> directory inside
the server config tree. This depends on the new "registering nodes
in the tree" feature. All nodes are hidden, because users
are not meant to edit any of them. Their name is intentionally
chosen like traditional nodes so that removing the config
also removes the new files.
- All relevant per-peer properties must be copied from the server
config (log level, printing changes, ...); they cannot be set
differently.
Because two separate SyncML sessions are used, we end up with
two normal session directories and log files.
The implementation is not complete yet:
- no glib support, so cannot be used in syncevo-dbus-server
- no support for CTRL-C and abort
- no interactive password entry for target sources
- unexpected slow syncs are detected on the client side, but
not reported properly on the server side
2010-07-31 18:28:53 +02:00
|
|
|
// activate all sources in client targeted by main config,
|
|
|
|
// with right uri
|
|
|
|
BOOST_FOREACH(const string &sourceName, m_server->getSyncSources()) {
|
|
|
|
SyncSourceNodes nodes = m_server->getSyncSourceNodesNoTracking(sourceName);
|
|
|
|
SyncSourceConfig source(sourceName, nodes);
|
|
|
|
string sync = source.getSync();
|
|
|
|
if (sync != "disabled") {
|
|
|
|
string targetName = source.getURI();
|
|
|
|
SyncSourceNodes targetNodes = client.getSyncSourceNodes(targetName);
|
|
|
|
SyncSourceConfig targetSource(targetName, targetNodes);
|
|
|
|
string fullTargetName = m_clientContext + "/" + targetName;
|
|
|
|
|
|
|
|
if (!targetNodes.dataConfigExists()) {
|
|
|
|
client.throwError(StringPrintf("%s: source not configured",
|
|
|
|
fullTargetName.c_str()));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// All of the config setting is done as volatile,
|
|
|
|
// so none of the regular config nodes have to
|
|
|
|
// be written. If a sync mode was set, it must have been
|
|
|
|
// done before in this loop => error in original config.
|
|
|
|
if (string(targetSource.getSync()) != "disabled") {
|
|
|
|
client.throwError(StringPrintf("%s: source targetted twice by %s",
|
|
|
|
fullTargetName.c_str(),
|
|
|
|
m_clientContext.c_str()));
|
|
|
|
}
|
|
|
|
targetSource.setSync(sync.c_str(), true);
|
|
|
|
targetSource.setURI(sourceName.c_str(), true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// now sync
|
|
|
|
client.sync(&m_clientReport);
|
|
|
|
} catch(...) {
|
|
|
|
SyncMLStatus status = m_clientReport.getStatus();
|
|
|
|
Exception::handle(&status, redirect);
|
|
|
|
m_clientReport.setStatus(status);
|
|
|
|
}
|
|
|
|
|
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();
|
|
|
|
writeMessage(m_statusFD, Message::MSG_SYNC_REPORT, data->c_str(), data->size());
|
|
|
|
} 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;
|
|
|
|
readMessage(statusFD, m_receiveBuffer);
|
|
|
|
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());
|
|
|
|
} 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)
|
|
|
|
{
|
|
|
|
if (m_loop) {
|
|
|
|
SE_THROW("glib support not implemented");
|
|
|
|
} else {
|
|
|
|
// first throw away old received message
|
2010-11-03 10:01:27 +01:00
|
|
|
if (m_receiveBuffer.haveMessage()) {
|
|
|
|
size_t len = m_receiveBuffer.m_message->m_length;
|
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
|
|
|
// memmove() probably never necessary because receiving
|
|
|
|
// ends directly after complete message, but doesn't hurt
|
|
|
|
// either...
|
2010-11-03 10:01:27 +01:00
|
|
|
memmove(m_receiveBuffer.m_message.get(),
|
|
|
|
(char *)m_receiveBuffer.m_message.get() + len,
|
|
|
|
m_receiveBuffer.m_used - len);
|
|
|
|
m_receiveBuffer.m_used -= len;
|
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
|
|
|
writeMessage(m_messageFD, m_sendType, data, len);
|
|
|
|
}
|
|
|
|
m_status = 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
|
|
|
|
2010-11-03 10:01:27 +01:00
|
|
|
void LocalTransportAgent::writeMessage(int fd, Message::Type type, const char *data, size_t len)
|
|
|
|
{
|
|
|
|
Message header;
|
|
|
|
header.m_type = type;
|
|
|
|
header.m_length = sizeof(Message) + len;
|
|
|
|
struct iovec vec[2];
|
|
|
|
vec[0].iov_base = &header;
|
|
|
|
vec[0].iov_len = offsetof(Message, m_data);
|
|
|
|
vec[1].iov_base = (void *)data;
|
|
|
|
vec[1].iov_len = len;
|
|
|
|
// TODO: handle timeouts and aborts while writing
|
|
|
|
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 {
|
|
|
|
ssize_t sent = writev(fd, vec, 2);
|
|
|
|
if (sent == -1) {
|
|
|
|
SE_LOG_DEBUG(NULL, NULL, "%s: sending %ld bytes failed: %s",
|
2010-10-29 11:20:11 +02:00
|
|
|
m_pid ? "parent" : "child",
|
2010-11-03 10:01:27 +01:00
|
|
|
(long)len,
|
|
|
|
strerror(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
|
|
|
SE_THROW_EXCEPTION(TransportException,
|
|
|
|
StringPrintf("writev(): %s", strerror(errno)));
|
|
|
|
}
|
2010-11-03 10:01:27 +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);
|
|
|
|
vec[0].iov_len -= part1;
|
|
|
|
sent -= part1;
|
|
|
|
ssize_t part2 = std::min((ssize_t)vec[1].iov_len, sent);
|
|
|
|
vec[1].iov_len -= part2;
|
|
|
|
sent -= part2;
|
|
|
|
// might be completely sent now, check
|
|
|
|
} while (vec[1].iov_len);
|
|
|
|
|
|
|
|
SE_LOG_DEBUG(NULL, NULL, "%s: sending %ld bytes done",
|
|
|
|
m_pid ? "parent" : "child",
|
|
|
|
(long)len);
|
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)
|
|
|
|
{
|
|
|
|
switch (m_status) {
|
|
|
|
case 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;
|
|
|
|
return m_status;
|
|
|
|
}
|
|
|
|
if (m_loop) {
|
|
|
|
SE_THROW("glib support not implemented");
|
|
|
|
} else {
|
2010-11-03 10:01:27 +01:00
|
|
|
if (!m_receiveBuffer.haveMessage()) {
|
|
|
|
readMessage(m_messageFD, m_receiveBuffer);
|
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
|
|
|
|
|
|
|
// 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
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return m_status;
|
|
|
|
}
|
|
|
|
return m_status;
|
|
|
|
}
|
|
|
|
|
2010-11-03 10:01:27 +01:00
|
|
|
void LocalTransportAgent::readMessage(int fd, Buffer &buffer)
|
|
|
|
{
|
|
|
|
while (!buffer.haveMessage()) {
|
|
|
|
// use select to implement timeout (TODO)
|
|
|
|
fd_set readfds;
|
|
|
|
FD_ZERO(&readfds);
|
|
|
|
FD_SET(fd, &readfds);
|
|
|
|
SE_LOG_DEBUG(NULL, NULL, "%s: waiting on %s",
|
|
|
|
m_pid ? "parent" : "child",
|
|
|
|
fd == m_messageFD ? "message channel" : "other channel");
|
|
|
|
int res = select(fd + 1, &readfds, NULL, NULL, NULL);
|
|
|
|
switch (res) {
|
|
|
|
case 0:
|
|
|
|
SE_LOG_DEBUG(NULL, NULL, "%s: select timeout",
|
|
|
|
m_pid ? "parent" : "child");
|
|
|
|
// TODO: timeout
|
|
|
|
SE_THROW("internal error, unexpected timeout");
|
|
|
|
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) {
|
|
|
|
buffer.m_message.set(static_cast<Message *>(realloc(buffer.m_message.release(), buffer.m_message->m_length)),
|
|
|
|
"Message Buffer");
|
2010-12-07 18:21:40 +01:00
|
|
|
buffer.m_size = buffer.m_message->m_length;
|
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);
|
|
|
|
SE_LOG_DEBUG(NULL, NULL, "%s: received %ld: %s",
|
|
|
|
m_pid ? "parent" : "child",
|
|
|
|
(long)recvd,
|
|
|
|
recvd < 0 ? strerror(errno) : "okay");
|
|
|
|
if (recvd < 0) {
|
|
|
|
SE_THROW_EXCEPTION(TransportException,
|
|
|
|
StringPrintf("message receive: %s", strerror(errno)));
|
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
SE_LOG_DEBUG(NULL, NULL, "%s: select errror: %s",
|
|
|
|
m_pid ? "parent" : "child",
|
|
|
|
strerror(errno));
|
|
|
|
SE_THROW_EXCEPTION(TransportException,
|
|
|
|
StringPrintf("select(): %s", strerror(errno)));
|
|
|
|
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
|
|
|
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
|
|
|
{
|
|
|
|
// TODO: implement timeout mechanism
|
|
|
|
}
|
|
|
|
|
|
|
|
SE_END_CXX
|