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<uint8_t *>(&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<uint8_t *>(link->link_mess), header->size,reds_handle_read_link_done, link);            

猜你喜欢

转载自blog.csdn.net/cai742925624/article/details/127724611