• spice Link过程分析


    一、客户端发起link message消息
    Client link message
    协议分析:
    1、Link Header 
    抓包协议:服务器和客户端共用  4x4=16Byte
    {
        SPICE MAGIC: REDQ
        Protocol major version: 2
        Protocol minor version: 2
        Message size:26
    }
    代码结构体
    typedef struct SPICE_ATTR_PACKED SpiceLinkHeader {
        uint32_t magic;
        uint32_t major_version;
        uint32_t minor_version;
        uint32_t size;
    } SpiceLinkHeader;
    2、LinkMess
    抓包协议:Main主通道类型为1 ,Session ID: 4B,Channel type: 1B,Channel ID: 1B, common number: 4B, channel number: 4B, offset: 4B = total: 18B 
    {
        Session ID: 0x00000000
        Channel type: Main(1)
        Channel ID: 0
        Number of common capabilities: 1
        Number of channel capabilities: 1
        Capabilities offset (bytes): 18
    }
    代码结构体
    typedef struct SPICE_ATTR_PACKED SpiceLinkMess {
        uint32_t connection_id;
        uint8_t channel_type;
        uint8_t channel_id;
        uint32_t num_common_caps;
        uint32_t num_channel_caps;
        uint32_t caps_offset;
    } SpiceLinkMess;
    3、以spicy为例,通道发送spice send client link 
    int main(int argc, char *argv[])
        connection_connect(conn);
            spice_session_connect(conn->session);
                s->cmain = spice_channel_new(session, SPICE_CHANNEL_MAIN, 0);
                return spice_channel_connect(s->cmain);
                    return channel_connect(channel, FALSE);
                        c->connect_delayed_id = g_idle_add(connect_delayed, channel);
                            co->stack_size = 16 << 20; /* 16Mb */
                            co->entry = spice_channel_coroutine;
                                spice_channel_send_link(channel);
                                if (!spice_channel_recv_link_hdr(channel) || !spice_channel_recv_link_msg(channel) || !spice_channel_recv_auth(channel)) 
                                //接收link回复,并解析link header,解析msg,解析auth
                                while (spice_channel_iterate(channel));
                                    if (!c->has_error)SPICE_CHANNEL_GET_CLASS(channel)->iterate_write(channel); //klass->iterate_write = spice_channel_iterate_write;
                                    if (!c->has_error)SPICE_CHANNEL_GET_CLASS(channel)->iterate_read(channel);//klass->iterate_read  = spice_channel_iterate_read;
                                        klass->handle_msg = spice_channel_handle_msg;
    4、能力集
    {
        Client Common Capabilities(4 Byte)
            ...1 =  Auth Selection: Set
            ..0. =  Auth Spice : Not Set
            .0.. = Auth SASL: Not Set
            1... = Mini Header: Set
            Client Channel-specific Capabilities (4 Byte)
            ...1 = Semi-seamless migration capability: Set
            ..1. = VM name and UUID messages capability: Set
            .1.. = Agent connected tokens capability: Set
            1... = Seamless migration capability : Set
    }
    二、服务器回复Server link message消息
    协议分析:
    1、link header与客户端一样
    2、SpiceLinkReply
    抓捕分析
    {
        spice ERROR: OK(0)
        X.509 SubjectPublicKeyInfo(ASN.1)
        Number of common capabilities: 1
        Number of channel capabilities: 1
        Capabilities offset (bytes): 178
    }
    代码分析
    #define SPICE_TICKET_KEY_PAIR_LENGTH 1024
    #define SPICE_TICKET_PUBKEY_BYTES (SPICE_TICKET_KEY_PAIR_LENGTH / 8 + 34)
    typedef struct SPICE_ATTR_PACKED SpiceLinkReply {
        uint32_t error;
        uint8_t pub_key[SPICE_TICKET_PUBKEY_BYTES];
        uint32_t num_common_caps;
        uint32_t num_channel_caps;
        uint32_t caps_offset;
    } SpiceLinkReply;
    3、能力
    Common Capabilities (4 bytes)
        ...1 = Auth Selection: Set
        ..1. = Auth Spice: Set
        .0.. = Auth SASL: Set
        1... = Mini Header: Set
    Channel Capabilities (4 bytes)
        ...1 = Semi-seamless migration capability: Set
        ..1. = VM name and UUID messages capability: Set
        .1.. = Agent connected tokens capability: Set
        1... = Seamless migration capability : Set
    4、spice-server代码分析
    int spice_server_init(SpiceServer *reds, SpiceCoreInterface *core) //qemu调用初始化spice库,位于spice-server.h头文件
        ret = do_spice_init(reds, core);
           reds_init_net(reds)
                reds->listen_watch = reds_core_watch_add(reds, reds->listen_socket,SPICE_WATCH_EVENT_READ,reds_accept, reds);
                                if (spice_server_add_client(reds, socket, 0) < 0) {
                        reds_handle_new_link(link);
                            red_stream_set_async_error_handler(link->stream, reds_handle_link_error);
                            red_stream_async_read(link->stream, ...,sizeof(link->link_header.magic), reds_handle_read_magic_done, link);     
                                red_stream_async_read(link->stream,reinterpret_cast(&link->link_header) + sizeof(header->magic),sizeof(SpiceLinkHeader) - sizeof(header->magic),reds_handle_read_header_done, link);  
                                    red_stream_async_read(link->stream, reinterpret_cast(link->link_mess), header->size,reds_handle_read_link_done, link);            
  • 相关阅读:
    Chapter6:线性离散系统的分析
    python getopt模块的使用
    金九银十!我说这是十月最全的《高频Java面试题合集》不过分吧!
    【Web前端】HTML详解(上篇)
    设置Ubuntu 20.04的静态IP地址(wifi模式下)
    伪类应用——
    策略模式【算法选择】
    MySQL成长手册(待续)
    火山引擎 RTC 自研音频编码器 NICO 实践之路
    leetcode -658--找到 K 个最接近的元素
  • 原文地址:https://blog.csdn.net/cai742925624/article/details/127724611