spice/server/red-channel.h
Frediano Ziglio 435ea33540 Reduce C++ symbols visibility
This allows the compiler to do some more optimisations on the
produced binary.
To allows possible future portability include header/footer in
some helper header files.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
2020-05-01 06:58:09 +01:00

212 lines
7.1 KiB
C

/*
Copyright (C) 2009 Red Hat, Inc.
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) any later version.
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, see <http://www.gnu.org/licenses/>.
Author:
yhalperi@redhat.com
*/
#ifndef RED_CHANNEL_H_
#define RED_CHANNEL_H_
#include <pthread.h>
#include <limits.h>
#include <glib-object.h>
#include <common/marshaller.h>
#include <common/demarshallers.h>
#include "spice.h"
#include "red-common.h"
#include "red-stream.h"
#include "stat.h"
#include "red-pipe-item.h"
#include "red-channel-capabilities.h"
G_BEGIN_DECLS
SPICE_DECLARE_TYPE(RedChannel, red_channel, CHANNEL);
#define RED_TYPE_CHANNEL red_channel_get_type()
#include "push-visibility.h"
struct RedChannelClient;
struct RedClient;
struct MainChannelClient;
#include "pop-visibility.h"
typedef void (*channel_client_connect_proc)(RedChannel *channel, RedClient *client, RedStream *stream,
int migration, RedChannelCapabilities *caps);
static inline gboolean test_capability(const uint32_t *caps, int num_caps, uint32_t cap)
{
return VD_AGENT_HAS_CAPABILITY(caps, num_caps, cap);
}
struct RedChannelClass
{
GObjectClass parent_class;
/* subclasses must implement handle_message() and optionally parser().
* If parser() is implemented, then handle_message() will get passed the
* parsed message as its 'msg' argument, otherwise it will be passed
* the raw data. In both cases, the 'size' argument is the length of 'msg'
* in bytes
*/
spice_parse_channel_func_t parser;
/*
* callbacks that are triggered from client events.
* They should be called from the thread that handles the RedClient
*/
channel_client_connect_proc connect;
};
#define FOREACH_CLIENT(_channel, _data) \
GLIST_FOREACH(_channel->get_clients(), RedChannelClient, _data)
/* Red Channel interface */
struct RedChannel: public GObject
{
const char *get_name() const;
void add_client(RedChannelClient *rcc);
void remove_client(RedChannelClient *rcc);
void init_stat_node(const RedStatNode *parent, const char *name);
// caps are freed when the channel is destroyed
void set_common_cap(uint32_t cap);
void set_cap(uint32_t cap);
int is_connected();
/* seamless migration is supported for only one client. This routine
* checks if the only channel client associated with channel is
* waiting for migration data */
bool is_waiting_for_migrate_data();
/*
* the disconnect callback is called from the channel's thread,
* i.e., for display channels - red worker thread, for all the other - from the main thread.
* RedChannel::destroy can be called only from channel thread.
*/
void destroy();
/* return true if all the channel clients support the cap */
bool test_remote_cap(uint32_t cap);
// helper to push a new item to all channels
typedef RedPipeItem *(*new_pipe_item_t)(RedChannelClient *rcc, void *data, int num);
int pipes_new_add(new_pipe_item_t creator, void *data);
void pipes_add_type(int pipe_item_type);
void pipes_add_empty_msg(int msg_type);
/* Add an item to all the clients connected.
* The same item is shared between all clients.
* Function will take ownership of the item.
*/
void pipes_add(RedPipeItem *item);
/* return TRUE if all of the connected clients to this channel are blocked */
bool all_blocked();
// TODO: unstaticed for display/cursor channels. they do some specific pushes not through
// adding elements or on events. but not sure if this is actually required (only result
// should be that they ""try"" a little harder, but if the event system is correct it
// should not make any difference.
void push();
// Again, used in various places outside of event handler context (or in other event handler
// contexts):
// flush_display_commands/flush_cursor_commands
// display_channel_wait_for_init
// red_wait_outgoing_item
// red_wait_pipe_item_sent
// handle_channel_events - this is the only one that was used before, and was in red-channel.c
void receive();
// For red_worker
void send();
// For red_worker
void disconnect();
void connect(RedClient *client, RedStream *stream, int migration,
RedChannelCapabilities *caps);
/* return the sum of all the rcc pipe size */
uint32_t max_pipe_size();
/* return the max size of all the rcc pipe */
uint32_t sum_pipes_size();
GList *get_clients();
guint get_n_clients();
struct RedsState* get_server();
SpiceCoreInterfaceInternal* get_core_interface();
/* channel callback function */
void reset_thread_id();
const RedStatNode *get_stat_node();
const RedChannelCapabilities* get_local_capabilities();
/*
* blocking functions.
*
* timeout is in nano sec. -1 for no timeout.
*
* This method tries for up to @timeout nanoseconds to send all the
* items which are currently queued. If the timeout elapses,
* the RedChannelClient which are too slow (those which still have pending
* items) will be disconnected.
*
* Return: TRUE if waiting succeeded. FALSE if timeout expired.
*/
bool wait_all_sent(int64_t timeout);
/* wrappers for client callbacks */
void migrate_client(RedChannelClient *rcc);
void disconnect_client(RedChannelClient *rcc);
RedChannelPrivate *priv;
};
#define CHANNEL_BLOCKED_SLEEP_DURATION 10000 //micro
#define red_channel_log_generic(log_cb, channel, format, ...) \
do { \
uint32_t id_; \
RedChannel *channel_ = (channel); \
g_object_get(channel_, "id", &id_, NULL); \
log_cb("%s:%u (%p): " format, channel_->get_name(), \
id_, channel_, ## __VA_ARGS__); \
} while (0)
#define red_channel_warning(channel, format, ...) \
red_channel_log_generic(g_warning, channel, format, ## __VA_ARGS__);
#define red_channel_message(channel, format, ...) \
red_channel_log_generic(g_message, channel, format, ## __VA_ARGS__);
#define red_channel_debug(channel, format, ...) \
red_channel_log_generic(g_debug, channel, format, ## __VA_ARGS__);
G_END_DECLS
#endif /* RED_CHANNEL_H_ */