summaryrefslogtreecommitdiff
path: root/src/syncevo/LocalTransportAgent.h
blob: d909fdd6077d48f3b406bbcdc0ffcbbfce79762e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
 * 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
 */

#ifndef INCL_LOCALTRANSPORTAGENT
#define INCL_LOCALTRANSPORTAGENT

#include "config.h"
#include <syncevo/TransportAgent.h>
#include <syncevo/SyncML.h>
#include <syncevo/SmartPtr.h>
#include <syncevo/GLibSupport.h>
#include <syncevo/SyncConfig.h>
#include <syncevo/ForkExec.h>
// This needs to be defined before including gdbus-cxx-bridge.h!
#define DBUS_CXX_EXCEPTION_HANDLER SyncEvo::SyncEvoHandleException
#include "gdbus-cxx-bridge.h"
#include <string>
#include <stdint.h>

#include <syncevo/declarations.h>
SE_BEGIN_CXX

class SyncContext;

/**
 * The main() function of the local transport helper.
 * Implements the child side of local sync.
 */
int LocalTransportMain(int argc, char **argv);

// internal in LocalTransportAgent.cpp
class LocalTransportChild;

/**
 * message send/receive with a forked process as peer
 *
 * Uses pipes to send a message and then get the response.
 * Limited to server forking the client. Because the client
 * has access to the full server setup after the fork,
 * no SAN message is needed and the first message goes
 * from client to server.
 *
 * Most messages will be SyncML message and response. In addition,
 * password requests also need to be passed through the server via
 * dedicated messages, because it is the one with a UI.
 */
class LocalTransportAgent : public TransportAgent
{
 private:
    LocalTransportAgent(SyncContext *server,
                        const std::string &clientContext,
                        void *loop = NULL);
    boost::weak_ptr<LocalTransportAgent> m_self;

 public:
    /**
     * @param server          the server side of the sync;
     *                        must remain valid while transport exists
     * @param clientContext   name of the context which contains the client's
     *                        sources, must start with @ sign
     * @param loop            optional glib loop to use when waiting for IO;
     *                        transport will *not* increase the reference count
     */
    static boost::shared_ptr<LocalTransportAgent> create(SyncContext *server,
                                                         const std::string &clientContext,
                                                         void *loop = NULL);
    ~LocalTransportAgent();

    /**
     * Set up message passing and fork the client.
     */
    void start();

    /**
     * Copies the client's sync report. If the client terminated
     * unexpectedly or shutdown() hasn't completed yet, the
     * STATUS_DIED_PREMATURELY sync result code will be set.
     */
    void getClientSyncReport(SyncReport &report);

    // TransportAgent implementation
    virtual void setURL(const std::string &url) {}
    virtual void setContentType(const std::string &type);
    virtual void shutdown();
    virtual void send(const char *data, size_t len);
    virtual void cancel();
    virtual Status wait(bool noReply = false);
    virtual void getReply(const char *&data, size_t &len, std::string &contentType);
    virtual void setTimeout(int seconds);

 private:
    SyncContext *m_server;
    std::string m_clientContext;
    Status m_status;
    SyncReport m_clientReport;
    GMainLoopCXX m_loop;
    boost::shared_ptr<ForkExecParent> m_forkexec;
    std::string m_contentType;
    std::string m_replyContentType;
    std::string m_replyMsg;

    /**
     * provides the D-Bus API expected by the forked process:
     * - password requests
     * - store the child's sync report
     */
    boost::shared_ptr<GDBusCXX::DBusObjectHelper> m_parent;

    /**
     * provides access to the forked process' D-Bus API
     * - start sync (returns child's first message)
     * - send server reply (returns child's next message or empty when done)
     * - emits output via signal
     *
     * Only non-NULL when child is running and connected.
     */
    boost::shared_ptr<LocalTransportChild> m_child;

    void logChildOutput(const std::string &level, const std::string &message);
    void onChildConnect(const GDBusCXX::DBusConnectionPtr &conn);
    void onFailure(const std::string &error);
    void onChildQuit(int status);
    void askPassword(const std::string &passwordName,
                     const std::string &descr,
                     const ConfigPasswordKey &key,
                     const boost::shared_ptr< GDBusCXX::Result1<const std::string &> > &reply);
    void storeSyncReport(const std::string &report);
    void storeReplyMsg(const std::string &contentType,
                       const GDBusCXX::DBusArray<uint8_t> &reply,
                       const std::string &error);

    /**
     * utility function: calculate deadline for operation starting now
     *
     * @param seconds      timeout in seconds, 0 for the default
     */
    Timespec deadline(unsigned seconds) { return seconds ? (Timespec::monotonic() + seconds) : Timespec(); }
};

SE_END_CXX

#endif // INCL_LOCALTRANSPORTAGENT