/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* Copyright (C) 2010 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 . */ #ifndef __SPICE_CLIENT_CHANNEL_PRIV_H__ #define __SPICE_CLIENT_CHANNEL_PRIV_H__ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #if HAVE_SASL #include #endif #include "spice-util-priv.h" #include "coroutine.h" #include "gio-coroutine.h" #include "common/client_marshallers.h" #include "common/client_demarshallers.h" #include "common/ssl_verify.h" G_BEGIN_DECLS #define MAX_SPICE_DATA_HEADER_SIZE sizeof(SpiceDataHeader) #define CHANNEL_DEBUG(channel, fmt, ...) \ SPICE_DEBUG("%s: " fmt, SPICE_CHANNEL(channel)->priv->name, ## __VA_ARGS__) struct _SpiceMsgOut { int refcount; SpiceChannel *channel; SpiceMessageMarshallers *marshallers; SpiceMarshaller *marshaller; uint8_t *header; gboolean ro_check; }; struct _SpiceMsgIn { int refcount; SpiceChannel *channel; uint8_t header[MAX_SPICE_DATA_HEADER_SIZE]; uint8_t *data; int hpos,dpos; uint8_t *parsed; size_t psize; message_destructor_t pfree; SpiceMsgIn *parent; }; enum spice_channel_state { SPICE_CHANNEL_STATE_UNCONNECTED = 0, SPICE_CHANNEL_STATE_CONNECTING, SPICE_CHANNEL_STATE_READY, SPICE_CHANNEL_STATE_SWITCHING, SPICE_CHANNEL_STATE_MIGRATING, SPICE_CHANNEL_STATE_MIGRATION_HANDSHAKE, }; struct _SpiceChannelPrivate { /* swapped on migration */ SSL_CTX *ctx; SSL *ssl; SpiceOpenSSLVerify *sslverify; GSocket *sock; #if HAVE_SASL sasl_conn_t *sasl_conn; const char *sasl_decoded; unsigned int sasl_decoded_length; unsigned int sasl_decoded_offset; #endif gboolean use_mini_header; uint64_t out_serial; uint64_t in_serial; /* not swapped */ SpiceSession *session; GCoroutine coroutine; int fd; gboolean has_error; guint connect_delayed_id; GQueue xmit_queue; gboolean xmit_queue_blocked; STATIC_MUTEX xmit_queue_lock; guint xmit_queue_wakeup_id; char name[16]; enum spice_channel_state state; spice_parse_channel_func_t parser; SpiceMessageMarshallers *marshallers; guint channel_watch; int tls; int connection_id; int channel_id; int channel_type; SpiceLinkHeader link_hdr; SpiceLinkMess link_msg; SpiceLinkHeader peer_hdr; SpiceLinkReply* peer_msg; int peer_pos; SpiceMsgIn *msg_in; int message_ack_window; int message_ack_count; GArray *caps; GArray *common_caps; GArray *remote_caps; GArray *remote_common_caps; gsize total_read_bytes; uint64_t last_message_serial; GSList *flushing; }; SpiceMsgIn *spice_msg_in_new(SpiceChannel *channel); SpiceMsgIn *spice_msg_in_sub_new(SpiceChannel *channel, SpiceMsgIn *parent, SpiceSubMessage *sub); void spice_msg_in_ref(SpiceMsgIn *in); void spice_msg_in_unref(SpiceMsgIn *in); int spice_msg_in_type(SpiceMsgIn *in); void *spice_msg_in_parsed(SpiceMsgIn *in); void *spice_msg_in_raw(SpiceMsgIn *in, int *len); void spice_msg_in_hexdump(SpiceMsgIn *in); SpiceMsgOut *spice_msg_out_new(SpiceChannel *channel, int type); void spice_msg_out_ref(SpiceMsgOut *out); void spice_msg_out_unref(SpiceMsgOut *out); void spice_msg_out_send(SpiceMsgOut *out); void spice_msg_out_send_internal(SpiceMsgOut *out); void spice_msg_out_hexdump(SpiceMsgOut *out, unsigned char *data, int len); uint16_t spice_header_get_msg_type(uint8_t *header, gboolean is_mini_header); uint32_t spice_header_get_msg_size(uint8_t *header, gboolean is_mini_header); void spice_channel_up(SpiceChannel *channel); void spice_channel_wakeup(SpiceChannel *channel, gboolean cancel); SpiceSession* spice_channel_get_session(SpiceChannel *channel); enum spice_channel_state spice_channel_get_state(SpiceChannel *channel); /* coroutine context */ typedef void (*handler_msg_in)(SpiceChannel *channel, SpiceMsgIn *msg, gpointer data); void spice_channel_recv_msg(SpiceChannel *channel, handler_msg_in handler, gpointer data); /* channel-base.c */ /* coroutine context */ void spice_channel_handle_set_ack(SpiceChannel *channel, SpiceMsgIn *in); void spice_channel_handle_ping(SpiceChannel *channel, SpiceMsgIn *in); void spice_channel_handle_notify(SpiceChannel *channel, SpiceMsgIn *in); void spice_channel_handle_disconnect(SpiceChannel *channel, SpiceMsgIn *in); void spice_channel_handle_wait_for_channels(SpiceChannel *channel, SpiceMsgIn *in); void spice_channel_handle_migrate(SpiceChannel *channel, SpiceMsgIn *in); gint spice_channel_get_channel_id(SpiceChannel *channel); gint spice_channel_get_channel_type(SpiceChannel *channel); void spice_channel_swap(SpiceChannel *channel, SpiceChannel *swap, gboolean swap_msgs); gboolean spice_channel_get_read_only(SpiceChannel *channel); void spice_channel_reset(SpiceChannel *channel, gboolean migrating); void spice_caps_set(GArray *caps, guint32 cap, const gchar *desc); #define spice_channel_set_common_capability(channel, cap) \ spice_caps_set(SPICE_CHANNEL(channel)->priv->common_caps, cap, #cap) #define spice_channel_set_capability(channel, cap) \ spice_caps_set(SPICE_CHANNEL(channel)->priv->caps, cap, #cap) /* coroutine context */ #define emit_main_context(object, event, args...) \ G_STMT_START { \ g_signal_emit_main_context(G_OBJECT(object), do_emit_main_context, \ event, &((struct event) { args }), G_STRLOC); \ } G_STMT_END G_END_DECLS #endif /* __SPICE_CLIENT_CHANNEL_PRIV_H__ */