/* -*- 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 "coroutine.h"
#include "gio-coroutine.h"
/* common/ */
#include "marshallers.h"
#include "demarshallers.h"
#include "ssl_verify.h"
G_BEGIN_DECLS
struct spice_msg_out {
int refcount;
SpiceChannel *channel;
SpiceMessageMarshallers *marshallers;
SpiceMarshaller *marshaller;
SpiceDataHeader *header;
};
struct spice_msg_in {
int refcount;
SpiceChannel *channel;
SpiceDataHeader header;
uint8_t *data;
int hpos,dpos;
uint8_t *parsed;
size_t psize;
message_destructor_t pfree;
spice_msg_in *parent;
};
enum spice_channel_state {
SPICE_CHANNEL_STATE_UNCONNECTED = 0,
SPICE_CHANNEL_STATE_CONNECTING,
SPICE_CHANNEL_STATE_LINK_HDR,
SPICE_CHANNEL_STATE_LINK_MSG,
SPICE_CHANNEL_STATE_AUTH,
SPICE_CHANNEL_STATE_READY,
SPICE_CHANNEL_STATE_SWITCHING,
SPICE_CHANNEL_STATE_MIGRATING,
};
struct spice_channel {
/* 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
/* not swapped */
SpiceSession *session;
struct coroutine coroutine;
int fd;
gboolean has_error;
guint connect_delayed_id;
int wait_interruptible;
struct wait_queue wait;
guint8 *xmit_buffer;
int xmit_buffer_capacity;
int xmit_buffer_size;
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;
int serial;
SpiceLinkHeader link_hdr;
SpiceLinkMess link_msg;
SpiceLinkHeader peer_hdr;
SpiceLinkReply* peer_msg;
int peer_pos;
spice_msg_in *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;
};
spice_msg_in *spice_msg_in_new(SpiceChannel *channel);
spice_msg_in *spice_msg_in_sub_new(SpiceChannel *channel, spice_msg_in *parent,
SpiceSubMessage *sub);
void spice_msg_in_ref(spice_msg_in *in);
void spice_msg_in_unref(spice_msg_in *in);
int spice_msg_in_type(spice_msg_in *in);
void *spice_msg_in_parsed(spice_msg_in *in);
void *spice_msg_in_raw(spice_msg_in *in, int *len);
void spice_msg_in_hexdump(spice_msg_in *in);
spice_msg_out *spice_msg_out_new(SpiceChannel *channel, int type);
void spice_msg_out_ref(spice_msg_out *out);
void spice_msg_out_unref(spice_msg_out *out);
void spice_msg_out_send(spice_msg_out *out);
void spice_msg_out_send_internal(spice_msg_out *out);
void spice_msg_out_hexdump(spice_msg_out *out, unsigned char *data, int len);
void spice_channel_up(SpiceChannel *channel);
void spice_channel_wakeup(SpiceChannel *channel);
SpiceSession* spice_channel_get_session(SpiceChannel *channel);
/* coroutine context */
typedef void (*handler_msg_in)(SpiceChannel *channel, spice_msg_in *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, spice_msg_in *in);
void spice_channel_handle_ping(SpiceChannel *channel, spice_msg_in *in);
void spice_channel_handle_notify(SpiceChannel *channel, spice_msg_in *in);
void spice_channel_handle_disconnect(SpiceChannel *channel, spice_msg_in *in);
void spice_channel_handle_wait_for_channels(SpiceChannel *channel, spice_msg_in *in);
void spice_channel_handle_migrate(SpiceChannel *channel, spice_msg_in *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);
void spice_channel_set_common_capability(SpiceChannel *channel, guint32 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__ */