標籤:spice協議
1 SPICE協議簡介
SPICE協議定義了一組協議訊息來訪問、控制、和接收通過網路從遠端電腦裝置(如:鍵盤、視頻、滑鼠)的操作,並回複發送輸出。控制裝置既可以在用戶端,也可以在服務端。另外,協議定義了一組支援遠程伺服器從一個網路地址遷移到另一個網路地址。加密傳輸資料,有一個例外,在選擇加密方法上比較靈活。SPICE使用簡單的訊息傳遞和不依賴於任何RPC標準或特定的傳輸層。
SPICE通訊會話分為多種溝通通道道(每個通道針對一個遠程裝置)為了有能力控制通訊和執行根據通道類型的訊息(如QOS加密),並在運行時添加和刪除通道(支援SPICE自訂)。
1) 主通道作為主要的SPICE會話通道
2) 顯示通道接收遠程顯示更新
3) 輸入通道發送滑鼠和鍵盤事件
4) 游標通道接收指標形狀和位置
5) 播放通道接收音頻流
6) 錄音通道發送用戶端音頻輸入。
隨著協議的發展將添加更多的通道類型,SPICE還定義了一組協議同步通道在遠端站台上執行。
2 普通協議定義2.1位元組順序
除非另有規定,所有資料結構封裝和位元組位順序是小段位元組格式。
2.2協議版本
協議版本定義為兩個UINT32值,主要協議版本和次要協議版本。伺服器和用戶端擁有相同的主要版本,為了保持相容性不管次要版本號碼。
?RED_VERSION_MAJOR = 1
?RED_VERSION_MINOR = 0
2.3通道類型-UINT8
?RED_CHANNEL_MAIN = 1
?RED_CHANNEL_DISPLAY = 2
?RED_CHANNEL_INPUTS = 3
? RED_CHANNEL_CURSOR = 4
?RED_CHANNEL_PLAYBACK = 5
?RED_CHANNEL_RECORD = 6
2.4通道連結-建立一個通道串連2.4.1 串連過程
通道串連過程是由用戶端發起。用戶端發送RedLinkMess,作為回應伺服器發送RedLinkReply。當用戶端接收到RedLinkReply時,它檢查返回錯誤碼,如果沒有錯誤它會加密公開金鑰密碼在RedLinkReply並將其發送到伺服器。伺服器接收密碼並將連結的結果發給用戶端。用戶端檢查串連的結果,如果結果為RED_ERROR_OK,建立一個有效連結。除了RED_CHANNEL_MAIN以外其他的通道類型只允許在用戶端主動串連RED_CHANNEL_MAIN。僅僅在RED_CHANNEL_MAIN通道被允許後,才會建立起與遠程伺服器的會話。
2.4.2 Ticketing
Ticketing是SPICE協議的一種實現機制目的是為了確保只允許有授權的來源串連。為了確保這種機制,Ticketing是一個在SPICE伺服器端有密碼和有效時間段的組成。時間到期後,這個Ticketing也就到期了。這個Ticketing是加密的。為了使用加密,伺服器產生一個1024位的RSA密鑰並向用戶端發送公開金鑰(通過RedLinkInfo)。用戶端使用這個公開金鑰加密密碼並將其發回伺服器(RedLinkMess之後)。伺服器解密密碼,比較它的ticketing和確保在允許的時間架構內。
2.4.3 RedLinkMess定義
typedef structSPICE_ATTR_PACKED SpiceLinkHeader {
uint32_t magic; //必須為RED_MAGIC
uint32_t major_version; //用戶端主要版本號
uint32_t minor_version;//用戶端次版本號碼
uint32_t size; //後續資料的大小
}SpiceLinkHeader;
typedef structSPICE_ATTR_PACKED SpiceLinkMess {
uint32_t connection_id; //針對一個新的會話(例如RED_CHANNEL_MAIN)這個數值被設定為0,伺服器將分配會話ID並在RedLinkMess訊息中發給用戶端。其他通道類型。使用分配的會話ID。
uint8_t channel_type; //通道類型
uint8_t channel_id; //通道ID,同一個ID可能有多個通道。
uint32_t num_common_caps;//普通用戶端通道功能詞數量
uint32_t num_channel_caps; //特殊用戶端通道功能詞數量
uint32_t caps_offset; //這個結構體的大小。後續還有能力集數值
} SpiceLinkMess;
2.4.4 RedLinkReply定義
typedef structSPICE_ATTR_PACKED SpiceLinkHeader { uint32_t magic; //必須為RED_MAGIC uint32_t major_version; //伺服器主要版本號 uint32_t minor_version;// 伺服器次版本號碼 uint32_t size; //後續資料的大小}SpiceLinkHeader;typedef structSPICE_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;
2.4.5 加密密碼
用戶端使用公開金鑰加密密碼發送回伺服器
2.4.6 驗證結果
接收驗證結果
2.5協議訊息定義
在串連建立後,所有的訊息傳輸都遵循下面的格式。開始於RedDataHeader描述一個主要訊息和一個可選的子訊息。在實際傳輸中使用SpiceMiniDataHeader。2.5.2、2.5.3、2.5.4結構體就不再詳細說明了。
2.5.1 SpiceMiniDataHeader
typedef structSPICE_ATTR_PACKED SpiceMiniDataHeader {
uint16_t type; //訊息類型,根據通道類型選擇各自的處理函數。
uint32_t size;//資料大小
} SpiceMiniDataHeader;
2.5.2 SpiceDataHeader
在實際傳輸中並未用到這個資料頭而使用下面的mini_header.
typedef structSPICE_ATTR_PACKED SpiceDataHeader {
uint64_t serial; //通道內,訊息的序號。開始於1,後續逐漸增加
uint16_t type; //訊息類型
uint32_t size; //訊息體的大小,如果sublist不是0,則sub_list為訊息的實際大小
uint32_t sub_list;//offset to SpiceSubMessageList[]//後續資料的大小
}SpiceDataHeader;
2.5.3 SpiceSubMessage
typedef structSPICE_ATTR_PACKED SpiceSubMessage {
uint16_t type;
uint32_t size;
}SpiceSubMessage;
2.5.4 SpiceSubMessageList
typedef structSPICE_ATTR_PACKED SpiceSubMessageList {
uint16_t size;
uint32_t sub_messages[0]; //offsets toSpicedSubMessage
}SpiceSubMessageList;
2.6常見訊息和訊息傳遞命名規範
訊息和訊息體結構類型首碼描述了訊息的來源。具體如下:
伺服器---》用戶端:RED
用戶端---》伺服器:REDC
這個命名是SPICE協議文檔中的描述,在實際源碼中,可能是下面的定義:
伺服器---》用戶端:SPICE_MSG
用戶端---》伺服器:SPICE_MSGC
2.7Ping
SPICE協議提供了ping訊息用於調試的目的。SPICE伺服器發送RED_PING,用戶端回應REDC_PING。伺服器可以使用這個調試測試網路情況。同時也可以用來同步用戶端和伺服器時間的一個通道。
2.7.1 SpiceMsgPing結構體描述
typedef structSpiceMsgPing {
uint32_t id; //訊息的ID,伺服器發給用戶端,用戶端回應這個ID
uint64_t timestamp;//訊息的時間戳記
void *data; //這個資料用途不明
uint32_t data_len;
} SpiceMsgPing;
2.8通道遷移
SPICE支援SPICE伺服器端的遷移。這個功能暫時不說明了。
2.9通道同步
SPICE協議提供了訊息在用戶端執行同步機制。伺服器發送RED_WAIT_FOR_CHANNELS訊息包含一個頻道列表的訊息等待(RedWaitForChannels)。SPICE用戶端等待完成這個列表的所有訊息在其他的所有訊息執行之前。
2.9.1 SpiceWaitForChannel結構體描述
typedef structSpiceWaitForChannel {
uint8_t channel_type; //通道的類別。5個
uint8_t channel_id; //通道ID
uint64_t message_serial;//等待訊息的序列ID號
}SpiceWaitForChannel;
2.9.2 SpiceMsgWaitForChannels;結構體描述
typedef structSpiceMsgWaitForChannels {
uint8_t wait_count; //等待訊息的數量
SpiceWaitForChannel wait_list[0];//需要等待的頻道列表
}SpiceMsgWaitForChannels;
2.10 斷開原因
下面訊息用於通知有序斷開伺服器或者用戶端
2.10.1 SpiceMsgDisconnect描述
typedef structSpiceMsgDisconnect {
uint64_t time_stamp;//伺服器或用戶端斷開的時間戳記
uint32_t reason; // SPICE_ERR_?
}SpiceMsgDisconnect;
2.11 伺服器通知訊息
SPICE協議定義了訊息的互動通知到用戶端使用RED_NOTIFY訊息。訊息可以劃分為嚴重性和可見度。以後可以用做訊息的方式顯示給使用者。
2.11.1 SpiceMsgNotify結構體描述
typedef structSpiceMsgNotify {
uint64_t time_stamp; //這個訊息在server端的時間戳記
uint32_t severity; //訊息的嚴重程度
uint32_t visibilty; //訊息的可見程度
uint32_t what; //訊息的類別,錯誤、警告、協助等等
uint32_t message_len;//訊息長度
uint8_t message[0]; //訊息資料
}SpiceMsgNotify;
SPICE協議-----基本簡介及普通協議定義