summaryrefslogtreecommitdiff
path: root/client/red_client.h
blob: 037896ac2ed976689d4395a07f685dc779e8dfeb (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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
/*
   Copyright (C) 2009 Red Hat, Inc.

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of
   the License, or (at your option) any later version.

   This program 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _H_REDCLIENT
#define _H_REDCLIENT

#include <list>

#include "common.h"
#include "red_peer.h"
#include "red_channel.h"
#include "display_channel.h"
#include "inputs_channel.h"
#include "cursor_channel.h"
#include "audio_channels.h"
#include "red.h"
#include "vd_agent.h"
#include "process_loop.h"

class Application;

class MigChannel: public RedChannelBase {
public:
    MigChannel(uint32_t type, uint32_t id, const ChannelCaps& common_caps, const ChannelCaps& caps)
        : RedChannelBase(type, id, common_caps, caps)
        , _valid(false) {}
    bool is_valid() { return _valid;}
    void set_valid(bool val) { _valid = val;}

private:
    bool _valid;
};

class Migrate {
public:
    Migrate(RedClient& client);
    ~Migrate();

    void start(const SpiceMsgMainMigrationBegin* migrate);
    bool abort();
    void add_channel(MigChannel* channel);
    void clear_channels();
    void swap_peer(RedChannelBase& other);

private:
    void connect_one(MigChannel& channel, const RedPeer::ConnectionOptions& options,
                     uint32_t connection_id);
    void disconnect_channels();
    void close_channels();
    void delete_channels();
    void run();
    static void* worker_main(void *data);

private:
    RedClient& _client;
    typedef std::list<MigChannel*> MigChannels;
    MigChannels _channels;
    bool _running;
    bool _aborting;
    bool _connected;
    std::string _password;
    std::string _host;
    int _port;
    int _sport;
    RedPeer::HostAuthOptions _auth_options;
    Thread* _thread;
    Mutex _lock;
    Condition _cond;
    int _pending_con;
};

class ChannelFactory {
public:
    ChannelFactory(uint32_t type) : _type (type) {}
    virtual ~ChannelFactory() {}

    uint32_t type() { return _type;}
    virtual RedChannel* construct(RedClient& client, uint32_t id) = 0;

private:
    uint32_t _type;
};

class GlzDecoderWindowDebug: public GlzDecoderDebug {
public:
    virtual void error(const std::string& str)
    {
        throw Exception(str);
    }

    virtual void warn(const std::string& str)
    {
        LOG_WARN("%s", str.c_str());
    }

    virtual void info(const std::string& str)
    {
        LOG_INFO("%s", str.c_str());
    }
};

class AgentTimer: public Timer {
    virtual void response(AbstractProcessLoop& events_loop);
};

typedef std::map< int, RedPeer::ConnectionOptions::Type> PeerConnectionOptMap;

class ForEachChannelFunc {
public:
    virtual bool operator() (RedChannel& channel) = 0;
};

class RedClient: public RedChannel {
public:
    friend class RedChannel;
    friend class Migrate;

    RedClient(Application& application);
    ~RedClient();

    void register_channel_factory(ChannelFactory& factory);

    virtual void connect();
    virtual void disconnect();
    virtual bool abort();

    void push_event(Event* event);
    void activate_interval_timer(Timer* timer, unsigned int millisec);
    void deactivate_interval_timer(Timer* timer);

    void set_target(const std::string&, int port, int sport);
    void set_password(const std::string& password) { _password = password;}
    void set_auto_display_res(bool auto_display_res) { _auto_display_res = auto_display_res;}
    const std::string& get_password() { return _password;}
    const std::string& get_host() { return _host;}
    int get_port() { return _port;}
    int get_sport() { return _sport;}
    virtual uint32_t get_connection_id() { return _connection_id;}
    uint32_t get_mouse_mode() { return _mouse_mode;}
    Application& get_application() { return _application;}
    bool is_auto_display_res() { return _auto_display_res;}
    RedPeer::ConnectionOptions::Type get_connection_options(uint32_t channel_type);
    RedPeer::HostAuthOptions& get_host_auth_options() { return _host_auth_opt;}
    void get_sync_info(uint8_t channel_type, uint8_t channel_id, SyncInfo& info);
    void wait_for_channels(int wait_list_size, SpiceWaitForChannel* wait_list);
    PixmapCache& get_pixmap_cache() {return _pixmap_cache;}
    uint64_t get_pixmap_cache_size() { return _pixmap_cache_size;}
    void on_display_mode_change();
    void for_each_channel(ForEachChannelFunc& func);
    void on_mouse_capture_trigger(RedScreen& screen);

    GlzDecoderWindow& get_glz_window() {return _glz_window;}
    int get_glz_window_size() { return _glz_window_size;}

    void set_mm_time(uint32_t time);
    uint32_t get_mm_time();

protected:
    virtual void on_connecting();
    virtual void on_connect();
    virtual void on_disconnect();

private:
    void on_channel_disconnected(RedChannel& channel);
    void migrate_channel(RedChannel& channel);
    void send_agent_monitors_config();
    void calc_pixmap_cach_and_glz_window_size(uint32_t display_channels_hint,
                                              uint32_t pci_mem_hint);
    void set_mouse_mode(uint32_t supported_modes, uint32_t current_mode);

    void handle_migrate_begin(RedPeer::InMessage* message);
    void handle_migrate_cancel(RedPeer::InMessage* message);
    void handle_init(RedPeer::InMessage* message);
    void handle_channels(RedPeer::InMessage* message);
    void handle_mouse_mode(RedPeer::InMessage* message);
    void handle_mm_time(RedPeer::InMessage* message);
    void handle_agent_connected(RedPeer::InMessage* message);
    void handle_agent_disconnected(RedPeer::InMessage* message);
    void handle_agent_data(RedPeer::InMessage* message);
    void handle_agent_tokens(RedPeer::InMessage* message);

    void on_agent_reply(VDAgentReply* reply);

    ChannelFactory* find_factory(uint32_t type);
    void create_channel(uint32_t type, uint32_t id);
    void disconnect_channels();
    void delete_channels();
    bool abort_channels();

private:
    Application& _application;

    std::string _host;
    int _port;
    int _sport;
    std::string _password;
    uint32_t _connection_id;
    uint32_t _mouse_mode;
    Mutex _notify_lock;
    bool _notify_disconnect;
    bool _auto_display_res;
    bool _aborting;

    bool _agent_connected;
    bool _agent_mon_config_sent;
    VDAgentMessage* _agent_msg;
    uint8_t* _agent_msg_data;
    uint32_t _agent_msg_pos;
    uint32_t _agent_tokens;
    AutoRef<AgentTimer> _agent_timer;

    PeerConnectionOptMap _con_opt_map;
    RedPeer::HostAuthOptions _host_auth_opt;
    Migrate _migrate;
    Mutex _channels_lock;
    typedef std::list<ChannelFactory*> Factorys;
    Factorys _factorys;
    typedef std::list<RedChannel*> Channels;
    Channels _channels;
    PixmapCache _pixmap_cache;
    uint64_t _pixmap_cache_size;
    Mutex _sync_lock;
    Condition _sync_condition;
    uint64_t _sync_info[SPICE_END_CHANNEL][256];

    GlzDecoderWindowDebug _glz_debug;
    GlzDecoderWindow _glz_window;
    int _glz_window_size; // in pixels

    Mutex _mm_clock_lock;
    uint64_t _mm_clock_last_update;
    uint32_t _mm_time;
};

#endif