spice-gtk之spice-channel数据包的解析

spice-gtk,是红帽的一个远程连接的一个项目,这是一个c语言实现的面相对象的项目,采用的是gobject面相对象的方法,所以读懂spice-gtk的代码首先得了解一下gobject的语法。

spice-channel网络层接收所有服务端的包

spice_channel_init(SpiceChannel *channel)首先初始化初始化的时候将priv结构体中的一些变量初始化,公有变量SpiceChannel结构体,typedef转换的变量,其实是_SpiceChannel, 在spice-types.h中转换,存在于spice-channel.h中。SpiceChannelPrivate类似其实是_SpiceChannelPrivate存在于spice-channel-priv.h中类似于c++中的private变量这边是gobject编程的一种安全机制。

struct _SpiceChannel
{
    GObject parent;
    SpiceChannelPrivate *priv;
    /* Do not add fields to this struct */
};
struct _SpiceChannelPrivate {

    /* swapped on migration */
    SSL_CTX                     *ctx;
    SSL                         *ssl;
    SpiceOpenSSLVerify          *sslverify;
    GSocket                     *sock;
    GSocketConnection           *conn;
    GInputStream                *in;
    GOutputStream               *out;
    。
    。
    。
    下面变量未显示
};

其实spice-channel类初始化的时候还会调用一个spice_channel_class_init(SpiceChannelClass *kclass)

SpiceChannelClass这个类和上面的类似其实是_SpiceChannelClass这是在spice-type.h中转换的

实际上结构体是这样的都是一些函数指针,在class_init中会将这些函数指针真正的指向具体的函数,在spicechannelclass结构体中也会有一个spicechannelclassprivate变量,也是存在于spice-channel-priv.h中如下所示:

struct _SpiceChannelClass
{
    GObjectClass parent_class;
    /*< public >*/
    /* signals, main context */
    void (*channel_event)(SpiceChannel *channel, SpiceChannelEvent event);
    void (*open_fd)(SpiceChannel *channel, int with_tls);
    /*< private >*/
    /* virtual methods, coroutine context */
    void (*handle_msg)(SpiceChannel *channel, SpiceMsgIn *msg);
    void (*channel_up)(SpiceChannel *channel);
    void (*iterate_write)(SpiceChannel *channel);
    void (*iterate_read)(SpiceChannel *channel);
    /*< private >*/
    /* virtual method, any context */
    gpointer deprecated;
    void (*channel_reset)(SpiceChannel *channel, gboolean migrating);
    void (*channel_reset_capabilities)(SpiceChannel *channel);
    /*< private >*/
    /* virtual methods, coroutine context */
    void (*channel_send_migration_handshake)(SpiceChannel *channel);
    SpiceChannelClassPrivate *priv;
    /*
     * If adding fields to this struct, remove corresponding
     * amount of padding to avoid changing overall struct size
     */
    gchar _spice_reserved[SPICE_RESERVED_PADDING - 2 * sizeof(void *)];
};

struct _SpiceChannelClassPrivate
{
    GArray *handlers;
};

    这里面的有一个数组handlers接下来我们分析这个handlers的作用:

    首先分析一下客户端接收包的时候数据包走的流程,刚开始接收是在spice_channel_iterate_read这个函数中有一个调用很重要:

spice_channel_recv_msg(channel, (handler_msg_in)SPICE_CHANNEL_GET_CLASS(channel)->handle_msg, NULL);

第二个参数其实传递的是spicechannelclass中的一个函数指针,而这个函数指针很明确在class_init中指向的函数就是spice_chanel_handle_msg,因此我们要分析这个函数:

static void spice_channel_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg)
{
    SpiceChannelClass *klass = SPICE_CHANNEL_GET_CLASS(channel);
    int type = spice_msg_in_type(msg);
    spice_msg_handler handler; //这边只是一个函数指针,具体的指向哪里还不知道
    g_return_if_fail(type < klass->priv->handlers->len);
    if (type > SPICE_MSG_BASE_LAST && channel->priv->disable_channel_msg)
        return;

    /*这个函数的第一个参数其实就是上面大黑字定义的一个garray,g_array_index函数的作用就是在这个数组中寻找到匹配这个type的函数,这样上面的函数指针就有明确指向的定义了*/
    handler = g_array_index(klass->priv->handlers, spice_msg_handler, type);//通过channel-display最底下的channel_set_handlers函数中去匹配
    g_return_if_fail(handler != NULL);
    handler(channel, msg);//这个handle其实已经是channel-display中的处理视频包的相关函数了
}

g_array_index会去查找garray这个包type和处理函数的对应表,而这个表存在每个模块的最后,因为包有视频的包,音频的包,鼠标操作的包键盘操作的包各种各样,这边给出一个视频包处理的文件,channel-display.c  处理网络层收到的包中关于视频的包,匹配表如下所示:

//本函数存在channel-display.c最后
static void channel_set_handlers(SpiceChannelClass *klass)
{
    static const spice_msg_handler handlers[] = {
        [ SPICE_MSG_DISPLAY_MODE ]               = display_handle_mode,
        [ SPICE_MSG_DISPLAY_MARK ]               = display_handle_mark,
        [ SPICE_MSG_DISPLAY_RESET ]              = display_handle_reset,
        [ SPICE_MSG_DISPLAY_COPY_BITS ]          = display_handle_copy_bits,
        [ SPICE_MSG_DISPLAY_INVAL_LIST ]         = display_handle_inv_list,
        [ SPICE_MSG_DISPLAY_INVAL_ALL_PIXMAPS ]  = display_handle_inv_pixmap_all,
        [ SPICE_MSG_DISPLAY_INVAL_PALETTE ]      = display_handle_inv_palette,
        [ SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES ] = display_handle_inv_palette_all,

        [ SPICE_MSG_DISPLAY_STREAM_CREATE ]      = display_handle_stream_create,
        [ SPICE_MSG_DISPLAY_STREAM_DATA ]        = display_handle_stream_data,
        [ SPICE_MSG_DISPLAY_STREAM_CLIP ]        = display_handle_stream_clip,
        [ SPICE_MSG_DISPLAY_STREAM_DESTROY ]     = display_handle_stream_destroy,
        [ SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL ] = display_handle_stream_destroy_all,
        [ SPICE_MSG_DISPLAY_STREAM_DATA_SIZED ]  = display_handle_stream_data,
        [ SPICE_MSG_DISPLAY_STREAM_ACTIVATE_REPORT ] = display_handle_stream_activate_report,

        [ SPICE_MSG_DISPLAY_DRAW_FILL ]          = display_handle_draw_fill,
        [ SPICE_MSG_DISPLAY_DRAW_OPAQUE ]        = display_handle_draw_opaque,
        [ SPICE_MSG_DISPLAY_DRAW_COPY ]          = display_handle_draw_copy,
        [ SPICE_MSG_DISPLAY_DRAW_BLEND ]         = display_handle_draw_blend,
        [ SPICE_MSG_DISPLAY_DRAW_BLACKNESS ]     = display_handle_draw_blackness,
        [ SPICE_MSG_DISPLAY_DRAW_WHITENESS ]     = display_handle_draw_whiteness,
        [ SPICE_MSG_DISPLAY_DRAW_INVERS ]        = display_handle_draw_invers,
        [ SPICE_MSG_DISPLAY_DRAW_ROP3 ]          = display_handle_draw_rop3,
        [ SPICE_MSG_DISPLAY_DRAW_STROKE ]        = display_handle_draw_stroke,
        [ SPICE_MSG_DISPLAY_DRAW_TEXT ]          = display_handle_draw_text,
        [ SPICE_MSG_DISPLAY_DRAW_TRANSPARENT ]   = display_handle_draw_transparent,
        [ SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND ]   = display_handle_draw_alpha_blend,
        [ SPICE_MSG_DISPLAY_DRAW_COMPOSITE ]     = display_handle_draw_composite,
        [ SPICE_MSG_DISPLAY_SURFACE_CREATE ]     = display_handle_surface_create,
        [ SPICE_MSG_DISPLAY_SURFACE_DESTROY ]    = display_handle_surface_destroy,
        [ SPICE_MSG_DISPLAY_MONITORS_CONFIG ]    = display_handle_monitors_config,
#ifdef G_OS_UNIX
        [ SPICE_MSG_DISPLAY_GL_SCANOUT_UNIX ]    = display_handle_gl_scanout_unix,
#endif
        [ SPICE_MSG_DISPLAY_GL_DRAW ]            = display_handle_gl_draw,
    };
    spice_channel_set_handlers(klass, handlers, G_N_ELEMENTS(handlers));
}

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: Spice-gtk 是一个开源的用于远程访问和显示虚拟化环境的客户端库,它允许用户通过网络连接到远程虚拟机,并在本地进行交互操作和图形渲染。下面是对其源码的简要分析。 首先,spice-gtk 的源码采用 C 语言编写,为构建虚拟化环境提供了一个简洁而高效的框架。它使用了许多不同的库和工具,如 GTK+,Glib 和 Cairo,用于实现图形用户界面以及输入和输出设备的处理。 源码中的主要组件包括 SPICE Client,用于建立与远程虚拟机的通信连接,并处理输入和输出数据流。它封装了 SPICE 协议,以实现远程图形渲染和输入事件传递。另一个重要的组件是 SPICE Display,用于渲染和显示远程虚拟机的图像内容。 在源码中,还可以找到一些辅助模块,如音频处理模块、USB 设备管理模块等。这些模块负责管理与虚拟机相关的附加功能,并提供了相应的接口。 在分析源码时,我们可以看到源码中使用了许多设计模式和技术,如单例模式、事件驱动模型和异步处理。这些设计模式和技术的使用使得源码具有扩展性和可维护性,为开发人员提供了自定义和扩展的便利。 总之,spice-gtk 的源码分析涉及到底层通信协议的实现、图形渲染和输入输出处理等方面。通过深入研究和分析,可以更好地理解 spic-gtk 的工作原理,并为其开发和维护提供指导和支持。 ### 回答2: spice-gtk是一个开源的包含SPICE客户端的GTK+工具包,用于与SPICE协议兼容的远程计算机进行交互和图形渲染。它的源代码可以帮助我们了解SPICE协议的实现细节以及与远程计算机通信的方式。 spice-gtk的源码是使用C语言编写的,主要由几个模块和文件组成。其中最重要的模块是spice-client,它实现了SPICE协议的客户端功能。此外,还有其他辅助模块,如spice-widget和spice-common,它们提供了用于创建GUI界面和共享资源的工具。 在源码中,我们可以找到与SPICE协议相关的数据结构和函数。这些数据结构用于存储协议消息的信息,例如输入事件、帧缓冲和图像数据等。函数则用于处理这些消息,完成数据的编解码、传输和渲染等操作。 通过分析源码,我们可以深入了解SPICE协议的各个阶段和步骤。例如,源码中可能包含与连接建立和认证相关的代码,用于验证客户端与远程计算机之间的身份和权限。同时,我们还可以找到与图形渲染和输入事件处理相关的代码,用于将远程计算机的图像和用户的输入交互传递。此外,源码中可能还包含了与音频、剪贴板共享和本地文件传输等功能相关的代码。 总之,通过对spice-gtk源码的分析,我们可以了解SPICE协议的实现原理以及与远程计算机通信的细节。这有助于我们深入理解SPICE技术,并能够根据需求进行自定义修改和扩展。同时,也可以从中学习到一些关于C语言编程和GTK+工具包的技巧和经验。 ### 回答3: spice-gtk是一款用于远程桌面应用程序的开源工具包。它提供了一组用于在本地计算机上创建与远程服务器连接的库和工具。 对于spice-gtk源代码的分析,我们可以从以下几个方面着手: 1. 连接管理:spice-gtk提供了连接管理的功能,用于建立与远程服务器的连接。可以分析其网络编程相关的代码,包括套接字通信、连接建立和认证等过程。 2. 图形渲染:spice-gtk可以将远程服务器的图像数据渲染到本地计算机上。源代码中可能包含与图像编解码、颜色管理和图像渲染相关的实现细节。 3. 输入设备:spice-gtk允许用户在本地计算机上控制远程服务器。源代码中可能包含处理本地输入设备(例如鼠标和键盘)事件的代码,以及将这些事件传递到远程服务器的实现部分。 4. 窗口管理:spice-gtk还提供了窗口管理的功能,用于在本地计算机上显示远程服务器的应用程序窗口。源代码可能包含与窗口管理相关的实现,例如窗口布局、窗口管理器通信等。 5. 性能优化:在源代码中可能会涉及性能优化的实现细节,例如数据压缩算法、带宽管理、缓存策略等。分析这些部分可以了解spice-gtk如何提高远程桌面应用程序的性能和响应速度。 总体而言,对于spice-gtk源代码的分析需要关注网络通信、图形渲染、输入设备、窗口管理和性能优化等方面的实现细节。深入理解这些细节有助于我们更好地使用和定制spice-gtk,并为远程桌面应用程序的开发和优化提供指导。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值