水蠟樹

Privet 是雲端服務使用的 Cloud Device Local Discovery API。本文件分為以下幾個部分:

  1. 簡介:Privet 簡介
  2. 探索:本機探索機制
  3. 公告:在地探索公告
  4. API:一般雲端裝置的私有 API
  5. Printer API:印表機使用的 Privet API
  6. 附錄:補充圖表

1. 簡介

連上雲端的裝置有許多優點。他們可以使用線上轉換服務、在裝置離線時代管工作佇列,以及從世界各地存取。不過,如果使用者可存取許多雲端裝置,我們就需要提供方法,根據位置資訊找出最近的裝置。Privet 通訊協定的目的是將雲端裝置的彈性與適當的本機探索機制繫結,讓裝置在新環境中輕鬆探索。

這項通訊協定的目標如下:
  • 讓雲端裝置可供本機探索
  • 向雲端服務註冊雲端裝置
  • 將註冊裝置與雲端代表建立關聯
  • 啟用離線功能
  • 簡化實作程序,讓小型裝置也能使用

Privet 通訊協定包含 2 個主要部分:探索和 API。探索功能可用於尋找區域網路上的裝置,而 API 則可用於取得裝置資訊及執行某些動作。本文中的「裝置」是指實作 Privet 通訊協定的雲端連線裝置。

2. 探索

探索功能採用無須調整設定 (mDNS 和 DNS-SD) 的通訊協定。裝置「必須」實作 IPv4 連結本機定址。裝置必須符合 mDNS 和 DNS-SD 規格。

裝置「必須」根據上述規格執行名稱衝突解決作業。

2.1. 服務類型

DNS 服務探索功能會使用下列格式表示服務類型: _applicationprotocol._transportprotocol。如果是 Privet 通訊協定,DNS-SD 的服務類型應為:_privet._tcp

裝置也可以實作其他服務類型。建議您為裝置實作的所有服務類型使用相同的服務執行個體名稱。舉例來說,印表機可能會實作「Printer XYZ._privet._tcp」和「Printer XYZ._printer._tcp」服務。這可簡化使用者的設定程序。不過,Privet 用戶端只會尋找「__privet._tcp」。

除了主要服務類型,裝置也「必須」為對應的子類型宣傳 PTR 記錄 (請參閱 DNS-SD 規格:「7.1. 選擇性執行個體列舉 (子類型)」。 格式應如下所示: _<subtype>._sub._privet._tcp

目前支援的裝置子類型只有「printer」。因此,所有印表機都「必須」宣傳 兩筆 PTR 記錄:

  • _privet._tcp.local.
  • _printer._sub._privet._tcp.local.

2.2. TXT 記錄

DNS 服務探索會定義欄位,以便在 TXT 記錄中新增服務的選用資訊。TXT 記錄是由鍵/值組合所組成。每個鍵/值組合都以長度位元組開頭,後面最多可接 255 個位元組的文字。鍵是第一個「=」字元前的文字,值則是第一個「=」字元後的文字,直到結尾為止。規格允許記錄中沒有值,在這種情況下,不會有「=」字元,或「=」字元後沒有文字。(請參閱 DNS-SD 規格: 「6.1. DNS TXT 記錄的一般格式規則」,瞭解 DNS TXT 記錄格式,以及「6.2. DNS-SD TXT 記錄大小」一節,瞭解建議長度)。

Privet 需要裝置在 TXT 記錄中傳送下列鍵/值組合。鍵/值字串不區分大小寫,例如「CS=online」和「cs=ONLINE」相同。TXT 記錄中的資訊必須與透過 /info API 存取的資訊相同 (請參閱 4.1. API 專區)。

建議 TXT 記錄大小不要超過 512 個位元組。

2.2.1. txtvers

TXT 結構的版本。txtvers 必須是 TXT 結構的第一筆記錄。目前僅支援版本 1。

txtvers=1

2.2.2. ty

提供使用者可理解的裝置名稱。例如:

ty=Google Cloud Ready Printer Model XYZ

2.2.3. 附註 (選填)

提供使用者可理解的裝置名稱。例如:

note=1st floor lobby printer

注意:這是選用金鑰,可以略過。不過,如果存在,使用者「應該」可以修改這個值。註冊裝置時必須使用相同的說明。

2.2.4. url

這部裝置連線的伺服器網址 (包括通訊協定)。例如:

url=https://www.google.com/cloudprint

2.2.5. type

以半形逗號分隔的裝置子類型清單,列出這部裝置支援的子類型。格式為: 「type=_subtype1,_subtype2」。目前唯一支援的裝置子類型是印表機

type=printer

列出的每個子類型都應使用對應的 PTR 記錄進行宣傳。每個支援的服務子類型都應有一個對應項目。服務子類型名稱 (<subtype>._sub._privet._tcp) 應與此處的裝置類型相同。

2.2.6. id

裝置 ID。如果裝置尚未註冊,這個鍵應該會存在,但值應為空白。例如:

  id=11111111-2222-3333-4444-555555555555
  id=

2.2.7. cs

顯示裝置目前的連線狀態。這項規格定義了四個可能的值。

  • 「線上」表示裝置目前已連上雲端。
  • 「離線」表示裝置可透過區域網路連線,但無法與伺服器通訊。
  • 「連線中」表示裝置正在執行啟動程序,尚未完全連上網路。
  • 「not-configured」表示裝置的網際網路存取權尚未設定。目前未使用這個值,但日後版本的規格可能會用到。
例如:
  • cs=online
  • cs=offline
  • cs=connecting

如果裝置已向雲端註冊,啟動時應檢查與伺服器的連線,偵測連線狀態 (例如呼叫雲端 API 取得裝置設定)。裝置可能會使用通知管道 (例如 XMPP) 連線狀態來回報這個值。啟動時,未註冊的裝置可能會對網域執行 Ping 作業,以偵測連線狀態 (例如,對雲端列印裝置執行 Ping 作業 www.google.com)。

3. 公告事項

裝置啟動、關機或狀態變更時,裝置「必須」按照 mDNS 規格說明執行公告步驟。至少應傳送兩次相應的公告,且兩次公告之間至少間隔一秒。

3.1. 啟動

裝置啟動時,必須執行 mDNS 規格所述的探查和公告步驟。在這種情況下,應傳送 SRV、PTR 和 TXT 記錄。建議盡可能將所有記錄歸入一個 DNS 回應。如果不是,建議依下列順序新增:SRV、PTR、TXT 記錄。

3.2. 關閉

裝置關機時,系統「應」嘗試傳送 TTL=0 的「再見封包」(如 mDNS 文件所述),通知所有相關單位。

3.3. 更新

如果 TXT 中描述的任何資訊有變更,裝置「必須」傳送更新公告。在這種情況下,您只需要傳送新的 TXT 記錄。舉例來說,裝置註冊後「必須」傳送更新公告,其中包含新的裝置 ID。

4. API

發現雲端裝置後,用戶端即可透過本機網路直接與該裝置通訊。所有 API 都是以 HTTP 1.1 為基礎。資料格式以 JSON 為基礎。API 要求可以是 GET 或 POST 要求。

每個要求都必須包含有效的「X-Privet-Token」標頭。只有 /privet/info 要求可以有空白的「X-Privet-Token」標頭 (請注意,標頭仍須存在)。如果缺少「X-Privet-Token」標頭,裝置必須傳回下列 HTTP 400 錯誤:

HTTP/1.1 400 Missing X-Privet-Token header.

如果「X-Privet-Token」標頭空白或無效,裝置「必須」回應「無效的 X-Privet-Token 錯誤」(invalid_x_privet_token,詳情請參閱「錯誤」一節)。/info API 是唯一的例外。如要進一步瞭解這麼做的原因,以及如何產生權杖,請參閱附錄 A:XSSI 和 XSRF 攻擊與防範。

如果要求的 API 不存在或不受支援,裝置必須傳回 HTTP 404 錯誤。

4.1. API 適用性

公開任何 API (包括 /info API) 前,裝置必須先聯絡伺服器,檢查本機設定。重新啟動後,必須保留本機設定。如果伺服器無法使用,請使用最後已知的本機設定。如果裝置尚未註冊,則應採用預設設定。

Cloud Print 裝置「必須」按照下列步驟註冊、接收及更新本機設定。

4.1.1. 註冊

裝置註冊時,必須指定「local_settings」參數,如下所示:

{
       "current": {
                "local_discovery": true,
                "access_token_enabled": true,
                "printer/local_printing_enabled": true,
                "printer/conversion_printing_enabled": true,
                "xmpp_timeout_value": 300
        }
}
您可以設定下列項目:
值名稱值類型說明
local_discovery布林值指出是否允許本機探索功能。如果為「false」,則必須停用所有本機 API (包括 /info) 和 DNS-SD 探索。根據預設,新註冊的裝置應會通過「true」。
access_token_enabled布林值 (選填)指出 /accesstoken API 是否應在區域網路上公開。預設值應為「true」。
printer/local_printing_enabled布林值 (選填)指出是否應在區域網路上公開本機列印功能 (「/printer/createjob」、「/printer/submitdoc」、「/printer/jobstate」)。預設值應為「true」。
printer/conversion_printing_enabled布林值 (選填)指出本機列印是否可將工作傳送至伺服器進行轉換。只有在啟用本機列印時才有意義。
xmpp_timeout_valueint (選填)指出 XMPP 頻道 Ping 之間的秒數。預設值必須為 300 (5 分鐘) 以上。

重要事項:如果缺少任何選用值,表示裝置完全不支援對應功能。

4.1.2. 啟動

裝置啟動時,應與伺服器聯絡,確認可在區域網路中公開哪些 API。如果印表機已連上雲端列印,則應呼叫:

/cloudprint/printer?printerid=<printer_id>
/cloudprint/list

建議使用 /cloudprint/printer,但 /cloudprint/list 也可以。

這個 API 會傳回目前的裝置參數,包括本機 API 的設定。伺服器的回覆格式如下:

"local_settings": {
        "current": {
                "local_discovery": true,
                "access_token_enabled": true,
                "printer/local_printing_enabled": true,
                "printer/conversion_printing_enabled": true,
                "xmpp_timeout_value": 300
         },
         "pending": {
                "local_discovery": true,
                "access_token_enabled": true,
                "printer/local_printing_enabled": false,
                "printer/conversion_printing_enabled": false,
                "xmpp_timeout_value": 500
         }
}

「current」物件表示目前生效的設定。

「pending」物件表示應套用至裝置的設定 (這個物件可能遺失)。

裝置看到「待處理」設定後,必須更新狀態 (請參閱下文)。

4.1.3. 更新

如果需要更新設定,系統會將 XMPP 通知傳送至裝置。通知的格式如下:

<device_id>/update_settings

收到這類通知後,裝置「必須」查詢伺服器,取得最新設定。 雲端列印裝置必須使用:

/cloudprint/printer?printerid=<printer_id>

裝置透過 /cloudprint/printer API (在啟動時或因通知而) 看到「待處理」部分後,就必須更新內部狀態,記住新設定。它「必須」呼叫伺服器 API,確認新設定。如果是雲端印表機,裝置「必須」呼叫 /cloudprint/update API,並使用「local_settings」參數,就像註冊時一樣。

重新連線至 XMPP 管道時,裝置「必須」呼叫 /cloudprint/printer API,檢查自上次連線以來,本機設定是否有所變更。

4.1.3.1. 地區設定待處理

裝置用來呼叫伺服器 API 的「local_settings」參數絕不能包含「pending」部分。

4.1.3.2. 目前地區設定

只有裝置可以變更「local_settings」的「current」部分。 其他人則會變更「待處理」部分,並等待裝置將變更傳播到「目前」部分。

4.1.4. 離線

如果無法在啟動期間與伺服器聯絡,裝置必須在收到通知後使用最後已知的本機設定。

4.1.5. 從服務中刪除裝置

如果裝置已從服務 (例如 GCP) 中刪除,系統會將 XMPP 通知傳送至裝置。通知格式如下:

<device_id>/delete

收到這類通知後,裝置「必須」前往伺服器檢查狀態。雲端列印裝置必須使用:

/cloudprint/printer?printerid=<printer_id>

裝置必須收到 HTTP 回應,且 success=false,且沒有裝置/印表機說明。這表示裝置已從伺服器移除,且裝置必須清除憑證並恢復原廠設定模式。

只要裝置收到回覆,指出裝置已因 /cloudprint/printer API (啟動、更新設定通知、每日 Ping) 而遭到刪除,就必須刪除憑證並進入預設模式。

4.2. /privet/info API

資訊 API 為必要項目,每部裝置都必須實作。這是對「/privet/info」網址發出的 HTTP GET 要求:GET /privet/info HTTP/1.1

資訊 API 會傳回裝置的基本資訊,以及支援的功能。這個 API 絕不能變更裝置狀態或執行任何動作,因為這類 API 容易受到 XSRF 攻擊。這是唯一允許「X-Privet-Token」標頭為空白的 API。用戶端應呼叫 /privet/info API,並將「X-Privet-Token」標頭設為 X-Privet-Token:

資訊 API 必須傳回與探索期間 TXT 記錄中資料一致的資料。

4.2.1. 輸入

/privet/info API 沒有輸入參數。

4.2.2. 回攻員

/privet/info API 會傳回裝置和支援功能的基本資訊。

TXT 欄會指出 DNS-SD TXT 記錄中的對應欄位。

值名稱值類型說明TXT
版本字串支援的最高 API 版本 (主要版本.次要版本),目前為 1.0
名稱字串裝置的易讀名稱。ty
說明字串(選用) 裝置說明。使用者「應」可修改。記事
網址字串這部裝置通訊的伺服器網址。網址必須包含通訊協定規格,例如:https://www.google.com/cloudprint。網址
類型字串清單支援的裝置類型清單。類型
id字串裝置 ID,如果裝置尚未註冊,則為空白。 id
device_state字串裝置狀態。
idle 表示裝置已準備就緒
processing 表示裝置忙碌中,功能可能會暫時受限
stopped 表示裝置無法運作,需要使用者介入
connection_state字串與伺服器 (base_url) 的連線狀態
online - 連線可用
offline - 無連線
connecting - 正在執行啟動步驟
not-configured - 尚未設定連線
註冊裝置可能會根據通知管道的狀態 (例如 XMPP 連線狀態) 回報連線狀態。
cs
製造商字串裝置製造商名稱
模型字串裝置型號
serial_number字串裝置的專屬 ID。在本規格中,這項屬性「必須」是 UUID。(GCP 1.1 規格)
(選用) 我們強烈建議在所有位置使用相同的序號 ID,這樣不同用戶端就能識別出同一部裝置。舉例來說,實作 IPP 的印表機可能會在「printer-device-id」欄位中使用這個序號 ID。
韌體字串裝置韌體版本
正常運行時間int裝置啟動後經過的秒數。
setup_url字串(選用) 含有設定說明的網頁網址 (包括通訊協定)
support_url字串(選用) 包含支援和常見問題資訊的網頁網址 (包括通訊協定)
update_url字串(選用) 包含更新韌體說明的頁面網址 (包括通訊協定)
x-privet-token字串X-Privet-Token 標頭的值,必須傳遞至所有 API,以防範 XSSI 和 XSRF 攻擊。詳情請參閱 6.1 節。
apiAPI 說明支援的 API 清單 (如下所述)
semantic_stateJSON(選用) 裝置的語意狀態,格式為 CloudDeviceState

api - 是 JSON 清單,內含透過本機網路提供的 API 清單。請注意,並非所有 API 都能同時透過本機網路使用。舉例來說,新連線的裝置應只支援 /register API:

"api": [
        "/privet/register",
]
裝置註冊完成後,裝置「應」停止支援 /register API。裝置也應向服務確認,哪些 API 可透過本機網路公開。例如:
"api": [
        "/privet/accesstoken",
        "/privet/capabilities",
        "/privet/printer/submitdoc",
]

目前可用的 API 如下:

  • /privet/register - 透過本機網路註冊裝置的 API。(詳情請參閱 /privet/register API)。裝置成功在雲端註冊後,就必須隱藏這個 API。
  • /privet/accesstoken - 用於向裝置要求存取權杖的 API (詳情請參閱 /privet/accesstoken API)。
  • /privet/capabilities - 用於擷取裝置功能的 API (詳情請參閱 /privet/capabilities API)。
  • /privet/printer/* - 裝置類型「印表機」專用的 API,詳情請參閱印表機專用 API。
以下是 /privet/info 回應的範例。(請注意,由於這是已註冊的裝置,因此缺少 /privet/register API):
{
        "version": "1.0",
        "name": "Gene’s printer",
        "description": "Printer connected through Chrome connector",
        "url": "https://www.google.com/cloudprint",
        "type": [
                "printer"
        ],
        "id": "11111111-2222-3333-4444-555555555555",
        "device_state": "idle",
        "connection_state": "online",
        "manufacturer": "Google",
        "model": "Google Chrome",
        "serial_number": "1111-22222-33333-4444",
        "firmware": "24.0.1312.52",
        "uptime": 600,
        "setup_url": "http://support.google.com/cloudprint/answer/1686197/?hl=en",
        "support_url": "http://support.google.com/cloudprint/?hl=en",
        "update_url": "http://support.google.com/cloudprint/?hl=en",
        "x-privet-token": "AIp06DjQd80yMoGYuGmT_VDAApuBZbInsQ:1358377509659",
        "api": [
                "/privet/accesstoken",
                "/privet/capabilities",
                "/privet/printer/submitdoc",
        ]
}
以下是墨水用盡的印表機的 /privet/info 回應範例 (請注意 semantic_state 欄位):
{
        "version": "1.0",
        "name": "Gene’s printer",
        "description": "Printer connected through Chrome connector",
        "url": "https://www.google.com/cloudprint",
        "type": [
                "printer"
        ],
        "id": "11111111-2222-3333-4444-555555555555",
        "device_state": "stopped",
        "connection_state": "online",
        "manufacturer": "Google",
        "model": "Google Chrome",
        "serial_number": "1111-22222-33333-4444",
        "firmware": "24.0.1312.52",
        "uptime": 600,
        "setup_url": "http://support.google.com/cloudprint/answer/1686197/?hl=en",
        "support_url": "http://support.google.com/cloudprint/?hl=en",
        "update_url": "http://support.google.com/cloudprint/?hl=en",
        "x-privet-token": "AIp06DjQd80yMoGYuGmT_VDAApuBZbInsQ:1358377509659",
        "api": [
                "/privet/accesstoken",
                "/privet/capabilities",
                "/privet/printer/submitdoc",
        ],
        "semantic_state": {
                "version": "1.0",
                "printer": {
                        "state": "STOPPED",
                        "marker_state": {
                                "item": [
                                        {
                                                "vendor_id": "ink",
                                                "state": "EXHAUSTED",
                                                "level_percent": 0
                                        }
                                ]
                        }
                }
        }
}

4.2.3. 錯誤

只有在缺少 X-Privet-Token 標頭時,/privet/info API 才應傳回錯誤。這「必須」是 HTTP 400 錯誤:

HTTP/1.1 400 Missing X-Privet-Token header.

4.3. /privet/register API

/privet/register API 為選用。這是 HTTP POST 要求。/privet/register API 必須檢查有效的 X-Privet-Token 標頭。裝置必須在「/privet/register」網址上實作這項 API:

POST /privet/register?action=start&user=user@domain.com HTTP/1.1
POST /privet/register?action=complete&user=user@domain.com HTTP/1.1

裝置應只在允許匿名註冊時公開 /privet/register API。例如:

  • 裝置開啟後 (或點選裝置上的特殊按鈕後),如果尚未註冊,就應公開 /privet/register API,讓區域網路使用者認領印表機。
  • 註冊完成後,裝置應停止公開 /privet/register API,防止本機網路上的其他使用者回收裝置。
  • 部分裝置可能採用不同的裝置註冊方式,且完全不應公開 /privet/register API (例如 Chrome 雲端列印連接器)。

註冊程序包含 3 個步驟 (請參閱「匿名註冊 Google 雲端列印」)。

  1. 啟動匿名註冊程序。
  2. 用戶端會呼叫 /privet/register API,啟動這項程序。裝置可能會等待使用者確認。
  3. 取得要求權杖。

用戶端會輪詢,瞭解裝置何時準備好繼續。裝置準備就緒後,會向伺服器傳送要求,以擷取註冊權杖和註冊網址。收到的權杖和網址「應」傳回給用戶端。在此步驟中,如果裝置收到另一個初始化註冊的呼叫,應採取下列行動:

  • 如果這是開始註冊的同一位使用者,請捨棄所有先前的資料 (如有),然後開始新的註冊程序。
  • 如果使用者不同,請傳回 device_busy 錯誤和 30 秒逾時。

完成註冊程序。

用戶端聲明擁有裝置後,應通知裝置完成註冊。註冊程序完成後,裝置應會傳送更新公告,包括新取得的裝置 ID。

注意:裝置處理 /privet/register API 呼叫時,無法同時處理其他 /privet/register API 呼叫。裝置「必須」傳回 device_busy 錯誤和 30 秒逾時。

強烈建議使用者在裝置上確認註冊。如果實作,裝置收到 /privet/register?action=start API 呼叫後,必須等待使用者確認。用戶端會呼叫 /privet/register?action=getClaimToken API,瞭解使用者何時完成確認,以及何時可取得聲明權杖。如果使用者在裝置上取消註冊 (例如按下「取消」按鈕),系統必須傳回 user_cancel 錯誤。如果使用者未在特定時間範圍內確認註冊,系統「必須」傳回 confirmation_timeout 錯誤。詳情請參閱「預設值」一節。

4.3.1. 輸入

/privet/register API 具有下列輸入參數:
名稱
動作可以是下列其中一項:
start - 開始註冊程序
getClaimToken - 擷取裝置的聲明權杖
cancel - 取消註冊程序
complete - 完成註冊程序
使用者將聲明擁有這部裝置的使用者電子郵件地址。

裝置「必須」檢查所有動作 (開始、getClaimToken、取消、完成) 的電子郵件地址是否相符。

4.3.2. 回攻員

/privet/register API 會傳回下列資料:
值名稱值類型說明
動作字串與輸入參數中的動作相同。
使用者字串 (選填)與輸入參數中的使用者相同 (如果輸入內容中省略,則可能缺少)。
token字串 (選填)註冊權杖 (「getClaimToken」回應必須提供,但「start」、「complete」和「cancel」則可省略)。
claim_url字串 (選填)註冊網址 (「getClaimToken」回應必須提供,但「start」、「complete」和「cancel」則可省略)。如果是雲端印表機,則必須是從伺服器收到的「complete_invite_url」。
automated_claim_url字串 (選填)註冊網址 (「getClaimToken」回應必須提供,但「start」、「complete」和「cancel」則可省略)。如果是雲端印表機,則必須是從伺服器收到的「automated_invite_url」。
device_id字串 (選填)新裝置 ID (「start」回應中省略,但「complete」回應中必須提供)。

裝置必須在註冊完成後,才可透過 /privet/info API 回應傳回裝置 ID。

範例 1:

{
        "action": "start",
        "user": "user@domain.com",
}

範例 2:

{
        "action": "getClaimToken",
        "user": "user@domain.com",
        "token": "AAA111222333444555666777",
        "claim_url": "https://domain.com/SoMeUrL",
}

範例 3:

{
        "action": "complete",
        "user": "user@domain.com",
        "device_id": "11111111-2222-3333-4444-555555555555",
}

4.3.3. 錯誤

/privet/register API 可能會傳回下列錯誤 (詳情請參閱「錯誤」一節):
錯誤說明
device_busy裝置忙碌中,無法執行要求的動作。逾時後重試。
pending_user_action如果「getClaimToken」傳回這個錯誤,表示裝置仍待使用者確認,逾時後應重試「getClaimToken」要求。
user_cancel使用者從裝置明確取消註冊程序。
confirmation_timeout使用者確認逾時。
invalid_action呼叫的動作無效。舉例來說,如果用戶端在呼叫 action=start 和 action=getClaimToken 之前,先呼叫了 action=complete。
invalid_params要求中指定的參數無效。(為確保日後相容性,應安全地忽略不明參數)。舉例來說,如果用戶端呼叫 action=unknown 或 user=,請傳回這個值。
device_config_error裝置端日期/時間 (或其他設定) 有誤。使用者必須前往裝置內部網站,並設定裝置設定。
離線裝置目前處於離線狀態,無法與伺服器通訊。
server_error註冊程序期間發生伺服器錯誤。
invalid_x_privet_token要求中的 X-Privet-Token 無效或空白。

註冊程序成功完成後,裝置「必須」停止公開 /privet/register API。如果裝置未公開 /privet/register API,則必須傳回 HTTP 404 錯誤。 因此,如果裝置已註冊,呼叫這個 API 時必須傳回 404。如果缺少 X-Privet-Token 標頭,裝置必須傳回 HTTP 400 錯誤。

4.4. /privet/accesstoken API

/privet/accesstoken API 為選用項目。這是 HTTP GET 要求。/privet/accesstoken API 必須檢查有效的「X-Privet-Token」標頭。裝置「必須」在「/privet/accesstoken」網址上實作這個 API:
GET /privet/accesstoken HTTP/1.1

裝置收到 /accesstoken API 呼叫時,應呼叫伺服器,為指定使用者擷取存取權杖,並將權杖傳回給用戶端。接著,用戶端會使用存取權杖,透過雲端存取這部裝置。

Cloud Print 裝置「必須」呼叫下列 API:

/cloudprint/proximitytoken
並從本機 API 傳遞「printerid=<printer_id>」和「user」參數。如果成功,伺服器回應會包含下列物件:
"proximity_token": {
        "user": "user@domain.com",
        "token": "AAA111222333444555666777",
        "expires_in": 600
}
Cloud Print 裝置必須將回應中「proximity_token」物件的值傳遞至本機 /privet/accesstoken API 呼叫。如果裝置可以傳遞所有參數 (包括本規格未說明的參數),會更有優勢 (可因應未來需求)。

4.4.1. 輸入

/privet/accesstoken API 具有下列輸入參數:
名稱
使用者打算使用這個存取權杖的使用者電子郵件地址。要求中可能為空白。

4.4.2. 回攻員

/privet/accesstoken API 會傳回下列資料:
值名稱值類型說明
token字串伺服器傳回的存取權杖
使用者字串與輸入參數中的使用者相同。
expires_inint這個權杖的有效期限 (以秒為單位)。從伺服器接收,並傳遞至此回應。

範例:

{
        "token": "AAA111222333444555666777",
        "user": "user@domain.com",
        "expires_in": 600
}

4.4.3. 錯誤

/privet/accesstoken API 可能會傳回下列錯誤 (詳情請參閱「錯誤」一節):
錯誤說明
離線裝置目前處於離線狀態,無法與伺服器通訊。
access_denied權利不足。存取遭拒,如果伺服器明確拒絕要求,裝置應傳回這項錯誤。
invalid_params要求中指定的參數無效。(為確保日後相容性,應安全地忽略不明參數)。舉例來說,如果用戶端呼叫 /accesstoken?user= 或 /accesstoken。
server_error伺服器錯誤。
invalid_x_privet_token要求中的 X-Privet-Token 無效或空白。

如果裝置未公開 /privet/accesstoken API,則必須傳回 HTTP 404 錯誤。如果缺少 X-Privet-Token 標頭,裝置必須傳回 HTTP 400 錯誤。

4.5. /privet/capabilities API

/privet/capabilities API 為選用項目。這是 HTTP GET 要求。/privet/capabilities API 必須檢查有效的「X-Privet-Token」標頭。裝置「必須」在「/privet/capabilities」網址上實作這個 API:
GET /privet/capabilities HTTP/1.1
裝置收到 /capabilities API 呼叫時,如果可以,應與伺服器聯絡以取得更新的功能。舉例來說,如果印表機支援透過雲端列印服務將 (在本機接收到的) 列印工作發布至印表機本身,則應傳回雲端列印服務會傳回的功能。在這種情況下,Google 雲端列印可能會在將工作傳送至印表機前執行新功能,進而改變原始印表機的功能。最常見的情況是支援的文件類型清單。如果印表機處於離線狀態,則應傳回支援的文件類型。不過,如果印表機已連線並註冊使用雲端列印,則「*/*」必須做為其中一種支援的類型傳回。在這種情況下,雲端列印服務會執行必要的轉換作業。如要離線列印,印表機必須至少支援「image/pwg-raster」格式。

4.5.1. 輸入

/privet/capabilities API 具有下列輸入參數:
名稱
離線(選用) 只能是「offline=1」。在這種情況下,裝置應傳回離線使用功能 (如果與「線上」功能不同)。

4.5.2. 回攻員

/privet/capabilities API 會以 Cloud 裝置說明 (CDD) JSON 格式傳回裝置功能 (詳情請參閱 CDD 說明文件)。印表機至少必須在此傳回支援的型號清單。舉例來說,目前處於連線狀態的可雲端列印印表機可能會傳回類似下列的內容 (至少):
{
        "version": "1.0",
        "printer": {
                "supported_content_type": [
                        {
                                "content_type": "application/pdf",
                                "min_version": "1.4"
                        },
                        { "content_type": "image/pwg-raster" },
                        { "content_type": "image/jpeg" },
                        { "content_type": "*/*" }
                ]
        }
}
與伺服器中斷連線時,可能會傳回:
{
        "version": "1.0",
        "printer": {
                "supported_content_type": [
                        {
                                "content_type": "application/pdf",
                                "min_version": "1.4"
                        },
                        { "content_type": "image/pwg-raster" },
                        { "content_type": "image/jpeg" }
                ]
        }
}

注意:印表機支援的內容類型優先順序會以順序表示。舉例來說,在上述範例中,印表機指定偏好「application/pdf」資料,而非「image/pwg-raster」和「image/jpeg」。用戶端應盡可能尊重印表機優先順序 (詳情請參閱 CDD 文件)。

4.5.3. 錯誤

/privet/capabilities API 可能會傳回下列錯誤 (詳情請參閱「錯誤」一節):
錯誤說明
invalid_x_privet_token要求中的 X-Privet-Token 無效或空白。

如果裝置未公開 /privet/capabilities API,則必須傳回 HTTP 404 錯誤。如果缺少 X-Privet-Token 標頭,裝置必須傳回 HTTP 400 錯誤。

4.6. 錯誤

上述 API 會以以下格式傳回錯誤:
值名稱值類型說明
錯誤字串錯誤類型 (依 API 定義)
說明字串 (選填)使用者可理解的錯誤說明。
server_api字串 (選填)如果發生伺服器錯誤,這個欄位會包含失敗的伺服器 API。
server_codeint (選填)如果發生伺服器錯誤,這個欄位會包含伺服器傳回的錯誤代碼。
server_http_codeint (選填)如果發生伺服器 HTTP 錯誤,這個欄位會包含伺服器傳回的 HTTP 錯誤代碼。
逾時int (選填)用戶端等待重試的秒數 (僅適用於可復原的錯誤)。用戶端必須將實際逾時時間從這個值隨機化為 + 20% 的值。

如果缺少 X-Privet-Token 標頭,所有 API 都必須傳回 HTTP 400 錯誤。

HTTP/1.1 400 Missing X-Privet-Token header.

範例 1:

{
        "error": "server_error",
        "description": "Service unavailable",
        "server_api": "/submit",
        "server_http_code": 503
}

範例 2:

{
        "error": "printer_busy",
        "description": "Printer is currently printing other job",
        "timeout": 15
}

5. Printer API

這個通訊協定支援的裝置類型之一是印表機。支援這類裝置的裝置「可能」會實作印表機專屬功能。理想情況下,列印至可雲端列印的印表機時,會透過雲端列印伺服器:

在某些情況下,用戶端可能需要在本機傳送文件。如果用戶端沒有 Google ID 或無法與雲端列印伺服器通訊,可能就需要這項功能。在這種情況下,列印工作會在本機提交至印表機。印表機則會使用雲端列印服務排隊及轉換工作。印表機會將本機提交的工作重新發布至雲端列印服務,然後要求該工作,因為工作是透過雲端提交。這項程序可提供彈性的服務 (轉換) 使用者體驗,以及列印工作管理/追蹤功能。

由於 Cloud Print 服務會實作轉換功能,印表機應在支援的內容類型清單中,宣傳支援所有輸入格式 (*/*):

{
        "version": "1.0",
        "printer": {
                "supported_content_type": [
                        { "content_type": "image/pwg-raster" },
                        { "content_type": "*/*" }
                ]
        }
}

在某些情況下,您可能需要完全離線的解決方案。由於印表機支援的輸入格式有限,用戶端必須將文件轉換為印表機原生支援的幾種格式。

這項規格「要求」所有印表機至少支援 PWG Raster (「image/pwg-raster」) 格式,以供離線列印。印表機可能支援其他格式 (例如 JPEG),如果用戶端支援,可能會以該格式傳送文件。印表機必須透過 /capabilities API 公開支援的類型,例如:

{
        "version": "1.0",
        "printer": {
                "supported_content_type": [
                        { "content_type": "image/pwg-raster" },
                        { "content_type": "image/jpeg" }
                ]
        }
}
用戶端可透過兩種方式,透過本機網路啟動列印作業。

簡單列印 - 用戶端透過本機網路將文件傳送至 /submitdoc API (未指定 job_id 參數)。系統會使用預設列印單設定列印提交的文件,不需要列印工作狀態。如果印表機「僅」支援這類列印作業,則「必須」在 /privet /info API 回應中「僅」宣傳/submitdoc API。

"api": [
        "/privet/accesstoken",
        "/privet/capabilities",
        "/privet/printer/submitdoc",
]

進階列印 - 用戶端應先在印表機上建立列印工作,方法是在要求中呼叫 /privet/printer/createjob API,並提供有效的 CJT 工作單。印表機「必須」將列印票證儲存在記憶體中,並將 job_id 回傳給用戶端。接著,用戶端會呼叫 /printer/submitdoc API,並指定先前收到的 job_id。屆時印表機就會開始列印。用戶端會呼叫 /privet/printer/jobstate API,輪詢印表機的列印工作狀態。

在多重用戶端環境中,無法保證如何呼叫此 API。一個用戶端有可能在另一個用戶端的/createjob->/submitdoc 呼叫之間呼叫 /createjob。為避免可能發生的死結並提升可用性,建議在印表機上保留少量待處理的列印工作佇列 (至少 3 到 5 個):

  • /createjob 會使用佇列中的第一個可用位置。
  • 工作生命週期 (在佇列中) 至少為 5 分鐘。
  • 如果佇列已滿,系統會移除最舊的非列印工作,並將新工作放在該處。
  • 如果裝置目前正在列印工作 (簡單或進階列印),/submitdoc 應會傳回忙碌狀態,並建議逾時時間,以便重試這項列印工作。
  • 如果 /submitdoc 參照的工作已從佇列中移除 (因取代或逾時),印表機應傳回 invalid_print_job 錯誤,且用戶端會從 /createjob 步驟重試程序。用戶端必須等待隨機逾時期間 (最多 5 秒),才能重試。

如果記憶體限制導致裝置無法儲存多個待處理工作,則佇列長度可能為 1 個列印工作。但仍應遵循上述相同通訊協定。工作完成或因錯誤而失敗後,印表機應至少儲存工作狀態資訊 5 分鐘。儲存已完成工作狀態的佇列大小應至少為 10。如果需要儲存更多工作狀態,系統可能會在 5 分鐘逾時前,從佇列中移除最舊的工作狀態。

注意:目前用戶端會輪詢工作狀態。日後,我們可能會要求印表機在「任何」列印工作狀態變更時,傳送 TXT DNS 通知。

5.1. /privet/printer/createjob API

/privet/printer/createjob API 為選用項目 (請參閱上方的「簡易列印」)。這是 HTTP POST 要求。/privet/printer/createjob API 必須檢查有效的「X-Privet-Token」標頭。 裝置「必須」在「/privet/printer/createjob」網址上實作這項 API:

POST /privet/printer/createjob HTTP/1.1
收到 /privet/printer/createjob API 呼叫時,印表機必須建立新的列印工作 ID、以 CJT 格式儲存收到的列印票證,並將列印工作 ID 回傳給用戶端。

5.1.1. 輸入

/privet/printer/createjob API 的網址中沒有輸入參數。要求主體應包含 CJT 格式的列印工作單資料。

5.1.2. 回攻員

/privet/printer/createjob API 會傳回下列資料:
值名稱值類型說明
job_id字串新建立的列印工作 ID。
expires_inint這項列印工作的有效秒數。

範例:

{
        "job_id": "123",
        "expires_in": 600
}

5.1.3. 錯誤

/privet/printer/createjob API 可能會傳回下列錯誤 (詳情請參閱「錯誤」一節):
錯誤說明
invalid_ticket提交的列印票證無效。
printer_busy印表機忙碌中,目前無法處理 /createjob。逾時後重試。
printer_error印表機處於錯誤狀態,需要使用者互動才能修正。 說明應包含更詳細的解釋 (例如「紙張在紙匣 1 中卡住」)。
invalid_x_privet_token要求中的 X-Privet-Token 無效或空白。

如果裝置未公開 /privet/printer/createjob,則必須傳回 HTTP 404 錯誤。如果缺少 X-Privet-Token 標頭,裝置必須傳回 HTTP 400 錯誤。

5.2. /privet/printer/submitdoc API

如要在本機網路 (離線或重新發布至雲端列印) 上實作列印作業,就必須使用 /privet/printer/submitdoc API。這是 HTTP POST 要求。/privet/printer/submitdoc API 必須檢查有效的「X-Privet-Token」標頭。裝置必須在「/privet/printer/submitdoc」網址上實作這項 API:
POST /privet/printer/submitdoc HTTP/1.1
收到 /privet/printer/submitdoc API 呼叫時,印表機應開始列印。如果無法開始列印,則必須傳回 printer_busy 錯誤,以及建議的逾時時間,讓用戶端等待一段時間後再試一次。

如果印表機無法將所有資料保留在內部緩衝區,則應使用 TCP 機制減緩資料傳輸速度,直到印表機列印部分文件,使部分緩衝區再次可用為止。(舉例來說,印表機可能會在 TCP 層設定 windowsize=0,導致用戶端等待)。

將文件提交至印表機可能需要相當長的時間。列印進行中時,用戶端應能檢查印表機和工作的狀態 (進階列印)。為此,印表機在處理 /privet/printer/submitdoc API 呼叫時,必須允許用戶端呼叫/privet/info 和 /privet/printer/jobstate API。建議所有用戶端啟動新執行緒來執行 /privet/printer/submitdoc API 呼叫,這樣主執行緒就能使用 /privet/info 和 /privet/printer/jobstate API 檢查印表機和列印工作狀態。

注意:完成或中止本機列印工作後,強烈建議 (且在日後的規格版本中會強制執行) 向 /cloudprint/submit 介面回報工作的最終狀態,以利會計和提升使用者體驗。「printerid」、「title」、「contentType」和「final_semantic_state」參數 (採用 PrintJobState 格式) 為必填參數,而「tag」參數 (重複參數) 和「ticket」參數 (採用 CloudJobTicket 格式的工作票證) 則為選填參數。請注意,提供的 PrintJobState 必須是最終狀態,也就是說,其類型必須為 DONE 或 ABORTED,且如果是 ABORTED,則必須提供原因 (詳情請參閱「JobState」)。另請注意,規格中未提及使用 /cloudprint/submit 介面回報本機列印工作,因為該節旨在說明介面的主要用途:提交列印工作,並在「content」參數中提供要列印的文件。

5.2.1. 輸入

/privet/printer/submitdoc API 具有下列輸入參數:
名稱
job_id(選用) 列印工作 ID。簡單的列印案例可省略此步驟 (請參閱上文)。必須與印表機傳回的 ID 相符。
user_name(選用) 使用者可判讀的使用者名稱。這並非最終結果,僅供列印工作註解使用。如果工作重新發布至雲端列印服務,這個字串應附加至雲端列印工作。
client_name(選用) 提出這項要求的用戶端應用程式名稱。僅供查看,如果工作重新發布至雲端列印服務,這個字串應附加至雲端列印工作。
job_name(選用) 要記錄的列印工作名稱。如果工作重新發布至雲端列印服務,這個字串應附加至雲端列印工作。
離線(選用) 只能是「offline=1」。在這種情況下,印表機應只嘗試離線列印 (不會重新發布至雲端列印伺服器)。

要求主體應包含可供列印的有效文件。「Content-Length」應包含要求的正確長度。「Content-Type」標頭應設為文件 MIME 類型,並符合 CDD 中的其中一種類型 (除非 CDD 指定「*/*」)。

強烈建議客戶在提出這項要求時,提供有效的使用者名稱 (或電子郵件地址)、客戶名稱和工作名稱。這些欄位只會用於使用者介面,以提升使用者體驗。

5.2.2. 回攻員

/privet/printer/submitdoc API 會傳回下列資料:
值名稱值類型說明
job_id字串新建立的列印工作 ID (簡單列印),或要求中指定的工作 ID (進階列印)。
expires_inint這項列印工作的有效秒數。
job_type字串提交文件的內容類型。
job_sizeint 64 位元列印資料的大小 (以位元組為單位)。
job_name字串(選用) 與輸入內容中的工作名稱相同 (如有)。

範例:

{
        "job_id": "123",
        "expires_in": 500,
        "job_type": "application/pdf",
        "job_size": 123456,
        "job_name": "My PDF document"
}

5.2.3. 錯誤

/privet/printer/submitdoc API 可能會傳回下列錯誤 (詳情請參閱「錯誤」一節):
錯誤說明
invalid_print_job要求中指定的工作 ID 無效/已過期。逾時後重試。
invalid_document_type印表機不支援文件 MIME 類型。
invalid_document提交的文件無效。
document_too_large文件超過允許的大小上限。
printer_busy印表機忙碌中,目前無法處理文件。逾時後重試。
printer_error印表機處於錯誤狀態,需要使用者互動才能修正。 說明應包含更詳細的解釋 (例如「紙張在紙匣 1 中卡住」)。
invalid_params要求中指定的參數無效。(為確保日後相容性,請安全地忽略不明參數)
user_cancel使用者從裝置明確取消列印程序。
server_error無法將文件發布至雲端列印。
invalid_x_privet_token要求中的 X-Privet-Token 無效或空白。

如果裝置未公開 /privet/printer/submitdoc,則必須傳回 HTTP 404 錯誤。如果缺少 X-Privet-Token 標頭,裝置必須傳回 HTTP 400 錯誤。

注意:/privet/printer/submitdoc API 可能需要在印表機端進行特殊處理 (因為附加的酬載較大)。在某些情況下 (取決於印表機 HTTP 伺服器實作和平台),印表機可能會在傳回 HTTP 錯誤前關閉通訊端。在其他情況下,印表機可能會傳回 503 錯誤 (而非 Privet 錯誤)。印表機應盡可能傳回 Privet。不過,實作 Privet 規格的每個用戶端「應該」都能處理 /privet/printer/submitdoc API 的通訊端關閉 (無 HTTP 錯誤) 和 503 HTTP 錯誤案例。在本例中,用戶端應將其視為 Privet「printer_busy」錯誤,並將「timeout」設為 15 秒。為避免無限重試,用戶端可能會在嘗試合理次數 (例如 3 次) 後停止重試。

5.3. /privet/printer/jobstate API

/privet/printer/jobstate API 為選用項目 (請參閱上文的「簡易列印」)。這是 HTTP GET 要求。 /privet/printer/jobstate API 必須檢查「X-Privet-Token」標頭是否有效。裝置「必須」在「/privet/printer/jobstate」網址上實作這項 API:
GET /privet/printer/jobstate HTTP/1.1
收到 /privet/printer/jobstate API 呼叫時,印表機應傳回所要求列印工作的狀態,或 invalid_print_job 錯誤。

5.3.1. 輸入

/privet/printer/jobstate API 具有下列輸入參數:
名稱
job_id要傳回狀態的列印工作 ID。

5.3.2. 回攻員

/privet/printer/jobstate API 會傳回下列資料:
值名稱值類型說明
job_id字串列印工作 ID,用於提供狀態資訊。
字串草稿 - 裝置上已建立列印工作 (尚未收到任何 /privet/printer/submitdoc 呼叫)。
已加入佇列:已收到並加入佇列,但尚未開始列印。
in_progress - 列印工作正在進行中。
已停止 - 列印工作已暫停,但可以手動或自動重新啟動。
done - 列印工作已完成。
已取消 - 列印工作失敗。
說明字串(選用) 使用者可理解的列印工作狀態說明。如果 state< 為 stoppedaborted,則應納入額外資訊。semantic_state 欄位通常會為用戶端提供更優質且更有意義的說明。
expires_inint這項列印工作的有效秒數。
job_type字串(選用) 提交文件的內容類型。
job_sizeint 64 位元(選用) 列印資料的大小 (以位元組為單位)。
job_name字串(選用) 與輸入內容中的工作名稱相同 (如有)。
server_job_id字串(選用) 伺服器傳回的工作 ID (如果工作已發布至雲端列印服務)。離線列印時會省略這項資訊。
semantic_stateJSON(選用) 採用 PrintJobState 格式的工作語意狀態。

範例 (透過雲端列印回報列印作業):

{
        "job_id": "123",
        "state": "in_progress",
        "expires_in": 100,
        "job_type": "application/pdf",
        "job_size": 123456,
        "job_name": "My PDF document",
        "server_job_id": "1111-2222-3333-4444"
}

示例 (離線列印錯誤):

{
        "job_id": "123",
        "state": "stopped",
        "description": "Out of paper",
        "expires_in": 100,
        "job_type": "application/pdf",
        "job_size": 123456,
        "job_name": "My PDF document"
}

範例 (使用者中止列印工作):

{
        "job_id": "123",
        "state": "aborted",
        "description": "User action",
        "expires_in": 100,
        "job_type": "application/pdf",
        "job_size": 123456,
        "job_name": "My PDF document",
        "semantic_state": {
                "version": "1.0",
                "state": {
                        "type": "ABORTED",
                        "user_action_cause": {"action_code": "CANCELLED"}
                },
                "pages_printed": 7
        }
}

例如,紙張用盡而停止列印工作。請注意裝置狀態的參照。用戶端需要呼叫 /privet/info API,才能取得裝置狀態的詳細資料:

{
        "job_id": "123",
        "state": "stopped",
        "description": "Out of paper",
        "expires_in": 100,
        "job_type": "application/pdf",
        "job_size": "123456",
        "job_name": "My PDF document",
        "semantic_state": {
                "version": "1.0",
                "state": {
                        "type": "STOPPED",
                        "device_state_cause": {"error_code": "INPUT_TRAY"}
                },
                "pages_printed": 7
        }
}

5.3.3. 錯誤

/privet/printer/jobstate API 可能會傳回下列錯誤 (詳情請參閱「錯誤」一節):
錯誤說明
invalid_print_job要求中指定的工作 ID 無效/已過期。
server_error無法取得列印工作狀態 (針對發布至雲端列印的列印工作)。
invalid_x_privet_token要求中的 X-Privet-Token 無效或空白。

如果裝置未公開 /privet/printer/jobstate,則必須傳回 HTTP 404 錯誤。如果缺少 X-Privet-Token 標頭,裝置必須傳回 HTTP 400 錯誤。

6. 附錄

6.1. 預設行為和設定

本節將說明所有 Privet 相容裝置的預設行為。
  • 立即可用的裝置應僅支援 /privet/info/privet/register API。應停用所有其他 API (例如 /privet/accesstoken、本機列印)。
  • 註冊時必須與裝置進行實體互動。
    • 使用者必須在裝置上採取實際行動 (例如按下按鈕),確認自己有權存取裝置。
    • 使用者執行上述動作後,印表機應傳送 /cloudprint/register 要求。在採取行動後,才應傳送這項要求 (請參閱序號圖 1)。
    • 如果裝置正在處理 /privet/register 要求 (例如等待上述動作),則必須拒絕所有其他 /privet/register 要求。在這種情況下,裝置「必須」傳回 device_busy 錯誤。
    • 如果裝置在 60 秒內未收到上述實體動作,應會對任何 /register 要求逾時。在這種情況下,裝置「必須」傳回 confirmation_timeout 錯誤。
    • 選用:建議使用,但非必要。下列項目可提升使用者體驗:
      • 印表機可能會閃爍燈號或顯示畫面,表示使用者需要採取行動來確認註冊。
      • 印表機螢幕上可能會顯示「正在為使用者『abc@def.com』向 Google 雲端列印服務註冊 - 按下『確定』繼續」,其中 abc@def.com 是 /register API 呼叫中的使用者參數。這樣一來,使用者就能更清楚瞭解:
        • 確認的是他們的註冊要求
        • 如果對方並未觸發要求,會發生什麼情況?
      • 除了在印表機上進行實體操作來確認 (例如「按一下『確定』按鈕」),印表機也可能會提供取消要求的按鈕 (例如「按一下『取消』拒絕」。這樣一來,如果使用者並未觸發註冊要求,就能在 60 秒逾時前取消要求。在這種情況下,裝置「必須」傳回 user_cancel 錯誤。
  • 擁有權轉移:
    • 裝置可能已從雲端服務中明確刪除。
      • 如果裝置收到成功訊息,但 /cloudprint/printer (適用於 GCP) 呼叫未傳回裝置說明,裝置就必須還原為預設 (開箱即用) 模式。
      • 如果裝置憑證無法再運作 (明確是因為伺服器傳回「無效憑證」回應),裝置「必須」還原為預設 (開箱即用) 模式。
    • 本機恢復原廠設定「必須」清除裝置憑證,並將裝置設為預設狀態。
    • 選用:裝置可能會提供選單項目,用來清除憑證並設為預設模式。
  • 支援 XMPP 通知的裝置「必須」具備 Ping 伺服器的功能。伺服器必須能透過「local_settings」控制 Ping 逾時。
  • 裝置每天最多會明確對伺服器執行一次 Ping 作業 (除了 XMPP Ping 作業外,還會對 GCP 的 /cloudprint/printer API 執行 Ping 作業),確保裝置與伺服器保持同步。建議在 24 到 32 小時內隨機檢查。
  • 選用:如果是雲端列印裝置,建議 (但非必要) 提供手動方式 (按鈕),讓使用者從裝置啟動新列印工作檢查。部分印表機已具備這項功能。
  • (選用步驟) 企業印表機可能提供完全停用本機探索的選項。在這種情況下,裝置必須更新伺服器上的這些本機設定。新的本機設定必須為空白 (將「local_discovery」設定為「false」,表示可以從 GCP 服務重新啟用)。

6.1.2 預設註冊圖

6.2. XSSI 和 XSRF 攻擊與防範

本節將說明裝置可能遭受的 XSSI 和 XSRF 攻擊,以及如何防範這類攻擊 (包括權杖產生技術)。
詳情請參閱: http://googleonlinesecurity.blogspot.com/2011/05/website-security-for-webmasters.html
一般來說,如果網站使用 Cookie 驗證機制,就可能遭受 XSSI 和 XSRF 攻擊。雖然 Google 不會透過雲端列印服務使用 Cookie,但這類攻擊仍有可能發生。根據設計,區域網路存取權會隱含信任要求。

6.2.1. XSSI

惡意網站可能會猜測與 Privet 相容裝置的 IP 位址和通訊埠號碼,並嘗試使用 <script> 標記內的「src=<api name>」呼叫 Privet API:
<script type="text/javascript" src="http://192.168.1.42:8080/privet/info"></script>
如果沒有防護機制,惡意網站就能執行 API 呼叫並存取結果。
為防範這類攻擊,所有 Privet API 呼叫都必須在要求中加入「X-Privet-Token」標頭。「src=<api>」指令碼標記無法新增標頭,可有效防範這類攻擊。

6.2.2. XSRF

http://en.wikipedia.org/wiki/Cross-site_request_forgery
惡意網站可能會猜測與 Privet 相容裝置的 IP 位址和通訊埠號碼,並嘗試使用 <iframe>、表單或其他跨網站載入機制呼叫 Privet API。攻擊者無法存取要求結果,但如果要求會執行動作 (例如列印),攻擊者就能觸發該動作。

為防範這類攻擊,我們需要下列防護措施:

  • 將 /privet/info API 開放給 XSRF
  • /privet/info API 不得在裝置上執行任何動作
  • 使用 /privet/info API 接收 x-privet-token
  • 所有其他 API 都必須檢查「X-Privet-Token」標頭中是否有有效的 x-privet-token。
  • x-privet-token 的效期應只有 24 小時。

即使攻擊者能夠執行 /privet/info API,也無法從回應中讀取 x-privet-token,因此無法呼叫任何其他 API。

強烈建議使用下列演算法產生 XSRF 權杖:

XSRF_token = base64( SHA1(device_secret + DELIMITER + issue_timecounter) + DELIMITER + issue_timecounter )

產生 XSRF 權杖的元素:

  • DELIMITER 是特殊字元,通常為「:」
  • issue_timecounter 是自某個事件 (時間戳記的紀元) 或裝置啟動時間 (適用於 CPU 計數器) 以來的秒數。裝置啟動並執行時,issue_timecounter 會持續增加 (請參閱下方的權杖驗證)。
  • SHA1 - 使用 SHA1 演算法的雜湊函式
  • base64 - base64 編碼
  • device_secret - 裝置專屬密鑰。每次重新啟動時,裝置密鑰都必須更新。

建議產生裝置密鑰的方式:

  • 每次重新啟動時產生新的 UUID
  • 每次重新啟動時產生 64 位元的隨機數字

裝置不必儲存發行的所有 XSRF 權杖。裝置需要驗證 XSRF 權杖是否有效時,應先對權杖進行 Base64 解碼,從後半部 (明文) 取得 issue_timecounter,然後嘗試產生 device_secret + DELIMITER + issue_timecounter 的 SHA1 雜湊,其中 issue_timecounter 來自權杖。如果新產生的 SHA1 與權杖中的 SHA1 相符,裝置現在必須檢查 issue_timecounter 是否在目前時間計數器的效期內 (24 小時)。為此,裝置會取得目前的時間計數器 (例如 CPU 計數器),並從中減去 issue_timecounter。結果必須是自核發權杖以來經過的秒數。

重要事項:建議您採用這種方式實作 XSRF 保護機制。Privet 規格的用戶端不應嘗試瞭解 XSRF 權杖,而是應將其視為黑箱。圖 6.2.3 說明實作 X-Privet-Token 和驗證一般要求的建議方式。

6.2.3 X-Privet 權杖產生和驗證流程圖

6.3. 工作流程圖

本節將說明不同情況下的工作流程。

6.3.1. 印表機開箱即用工作流程

6.3.2. 已註冊印表機啟動

6.3.3 XMPP 通知處理工作流程

6.3.4. 檢查印表機設定工作流程