Privet

Privet は、クラウド サービスで使用される Cloud Device Local Discovery API です。このドキュメントは、次のセクションで構成されています。

  1. はじめに: Privet の概要
  2. 検出: ローカル検出メカニズム
  3. お知らせ: ローカル ディスカバリのお知らせ
  4. API: 一般的なクラウド デバイス用のプライベート API
  5. Printer API: プリンタで使用される Privet API
  6. 付録: 補足図

1. はじめに

クラウド接続デバイスには多くのメリットがあります。オンライン変換サービスを使用したり、デバイスがオフラインの間にジョブキューをホストしたり、世界中のどこからでもアクセスできるようにしたりできます。ただし、特定のユーザーがアクセスできるクラウド デバイスが多数あるため、位置情報に基づいて最も近いデバイスを見つける方法を提供する必要があります。Privet プロトコルの目的は、クラウド デバイスの柔軟性を適切なローカル検出メカニズムにバインドして、新しい環境でデバイスを簡単に検出できるようにすることです。

このプロトコルの目標は次のとおりです。
  • クラウド デバイスをローカルで検出可能にする
  • クラウド デバイスをクラウド サービスに登録する
  • 登録されたデバイスをクラウド表現に関連付ける
  • オフライン機能を有効にする
  • 実装を簡素化して、小型デバイスでも利用できるようにする

Privet プロトコルは、検出と API の 2 つの主要部分で構成されています。検出はローカル ネットワーク上のデバイスを見つけるために使用され、API はデバイスに関する情報を取得してアクションを実行するために使用されます。このドキュメントでは、デバイスは Privet プロトコルを実装するクラウド接続デバイスを指します。

2. ファインド

ディスカバリは、zeroconf ベース(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」のみを検索します。

デバイスは、メインのサービスタイプに加えて、対応するサブタイプ(DNS-SD 仕様の「7.1. Selective Instance Enumeration(サブタイプ)」を参照してください。形式は _<subtype>._sub._privet._tcp にする必要があります。

現在サポートされているデバイス サブタイプは printer のみです。したがって、すべてのプリンタは 2 つの PTR レコードをアドバタイズしなければなりません。

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

2.2. TXT レコード

DNS サービス ディスカバリは、TXT レコードにサービスに関するオプション情報を追加するためのフィールドを定義します。TXT レコードは Key-Value ペアで構成されます。各 Key-Value ペアは、長さバイトで始まり、その後に最大 255 バイトのテキストが続きます。キーは最初の「=」文字の前のテキストで、値は最初の「=」文字の後のテキストから末尾までです。この仕様では、レコードに値がない場合も許容されます。この場合、「=」文字がないか、「=」文字の後にテキストがありません。(DNS-SD 仕様の「6.1. DNS TXT レコードの形式については「General Format Rules for DNS TXT Records」を、DNS-SD TXT レコード サイズ」(推奨される長さ)。

Privet では、デバイスが TXT レコードで次の Key-Value ペアを送信する必要があります。キーと値の文字列では大文字と小文字は区別されません。たとえば、「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(省略可)

デバイスのユーザー可読形式の名前を提供します。次に例を示します。

note=1st floor lobby printer

注: これは省略可能なキーであり、スキップできます。ただし、この値が存在する場合は、ユーザーが変更できるようにすべきです。デバイスを登録する際は、同じ説明文を使用しなければなりません。

2.2.4. url

このデバイスが接続されているサーバーの URL(プロトコルを含む)。次に例を示します。

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

2.2.5. type

このデバイスでサポートされているデバイス サブタイプのカンマ区切りのリスト。形式は「type=_subtype1,_subtype2」です。現在、サポートされているデバイス サブタイプは printer のみです。

type=printer

リストされている各サブタイプは、対応する PTR レコードを使用してアドバタイズする必要があります。サポートされているサービス サブタイプごとに、対応するアイテムが 1 つ必要です。サービス サブタイプ名(<subtype>._sub._privet._tcp)は、ここでデバイスタイプと等しくなければなりません。

2.2.6. id

デバイス ID。デバイスがまだ登録されていない場合、このキーは存在しますが、値は空になります。次に例を示します。

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

2.2.7. cs

デバイスの現在の接続状態を示します。この仕様では、4 つの可能な値が定義されています。

  • 「オンライン」は、デバイスが現在クラウドに接続されていることを示します。
  • 「オフライン」は、デバイスがローカル ネットワークで利用可能だが、サーバーと通信できないことを示します。
  • 「接続中」は、デバイスが起動シーケンスを実行中で、まだ完全にオンラインになっていないことを示します。
  • 「not-configured」は、デバイスのインターネット アクセスがまだ構成されていないことを示します。この値は現在使用されていませんが、仕様の今後のバージョンで役立つ可能性があります。
例:
  • cs=online
  • cs=offline
  • cs=connecting

デバイスがクラウドに登録されている場合、起動時にサーバーとの接続を確認して、接続状態を検出する必要があります(たとえば、クラウド API を呼び出してデバイス設定を取得します)。デバイスは、通知チャネル(XMPP など)の接続状態を使用してこの値を報告することがあります。起動時に登録されていないデバイスは、接続状態を検出するためにドメインに ping を送信することがあります(クラウド プリント デバイスの場合は www.google.com に ping を送信するなど)。

3. お知らせ

デバイスの起動、シャットダウン、状態変更時に、デバイスは mDNS 仕様に記載されているアナウンス ステップを実行しなければなりません。対応するアナウンスを少なくとも 2 回送信すべきです。アナウンスの間隔は少なくとも 1 秒です。

3.1. 起動

デバイスの起動時に、mDNS 仕様に記載されているプロービングとアナウンスの手順を実行しなければなりません。この場合、SRV、PTR、TXT レコードを送信する必要があります。可能な場合は、すべてのレコードを 1 つの DNS レスポンスにグループ化することをおすすめします。そうでない場合は、SRV、PTR、TXT レコードの順序をおすすめします。

3.2. シャットダウン

デバイスのシャットダウン時に、TTL=0 の「goodbye パケット」を送信して(mDNS ドキュメントに記載されているとおり)、関係者全員に通知を試みるべきです。

3.3. 更新

TXT に記載されている情報が変更された場合、デバイスは更新アナウンスを送信しなければなりません。この場合は、新しい TXT レコードのみを送信すれば十分です。たとえば、デバイスが登録された後、新しいデバイス ID を含む更新アナウンスを送信しなければなりません。

4. API

クラウド デバイスが検出されると、ローカル ネットワーク経由でデバイスとのクライアント通信が直接有効になります。すべての API は HTTP 1.1 ベースです。データ形式は JSON ベースです。API リクエストは GET リクエストまたは POST リクエストです。

各リクエストには、有効な「X-Privet-Token」ヘッダーを含めなければなりません。「X-Privet-Token」ヘッダーを空にできるのは、/privet/info リクエストのみです(ヘッダーは必ず存在している必要があります)。「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

デバイスのみが「local_settings」の「current」セクションを変更できます。他のユーザーは「保留中」セクションを変更し、デバイスによって変更が「現在」セクションに伝播されるまで待機します。

4.1.4. オフライン

起動時にサーバーに接続できない場合、通知後、デバイスは最後に確認されたローカル設定を使用しなければなりません。

4.1.5. サービスからデバイスを削除する

デバイスがサービス(GCP など)から削除された場合、XMPP 通知がデバイスに送信されます。通知は次の形式になります。

<device_id>/delete

このような通知を受信すると、デバイスはサーバーにアクセスして状態を確認しなければなりません。クラウド プリント デバイスは以下を使用しなければなりません。

/cloudprint/printer?printerid=<printer_id>

デバイスは、success=false でデバイス/プリンタの説明がない成功の HTTP 応答を受信しなければなりません。デバイスがサーバーから削除されたことを意味します。デバイスは認証情報を消去し、出荷時のデフォルト設定モードに移行しなければなりません。

デバイスが /cloudprint/printer API の結果として削除されたことを示す応答を受信した場合は、いつでも(起動時、設定更新通知時、毎日の ping 時)、認証情報を削除してデフォルト モードに移行しなければなりません。

4.2. /privet/info API

情報 API は必須であり、すべてのデバイスで実装しなければなりません。これは、「/privet/info」URL の HTTP GET リクエストです。GET /privet/info HTTP/1.1

info API は、デバイスとサポートされている機能に関する基本情報を返します。この API は XSRF 攻撃に対して脆弱であるため、デバイスのステータスを変更したり、アクションを実行したりしてはなりません。これは、「X-Privet-Token」ヘッダーを空にできる唯一の API です。クライアントは、X-Privet-Token に X-Privet-Token: "" を設定した "X-Privet-Token" ヘッダーを使用して /privet/info API を呼び出す必要があります。

情報 API は、検出時に TXT レコードで利用可能なデータと一貫性のあるデータを返さなければなりません。

4.2.1. 入力

/privet/info API には入力パラメータはありません。

4.2.2. 戻る

/privet/info API は、デバイスとサポートされている機能に関する基本情報を返します。

TXT 列は、DNS-SD TXT レコードの対応するフィールドを示します。

値の名前値の型説明TXT
version文字列サポートされている API の最大バージョン(major.minor)。現在は 1.0
name文字列人が読める形式のデバイス名。ty
説明文字列(省略可)デバイスの説明。ユーザーが変更できるようにすべきです。注意事項
URL文字列このデバイスが通信しているサーバーの URL。URL にはプロトコル指定を含める必要があります(例: https://www.google.com/cloudprint)。URL
type文字列のリストサポートされているデバイスタイプのリスト。type
id文字列デバイス ID。デバイスがまだ登録されていない場合は空。 id
device_state文字列デバイスの状態。
idle はデバイスが準備完了状態であることを意味します。
processing はデバイスがビジー状態であり、機能がしばらく制限される可能性があることを意味します。
stopped はデバイスが動作しておらず、ユーザーの介入が必要であることを意味します。
connection_state文字列サーバー(base_url)への接続の状態
online - 接続可能
offline - 接続なし
connecting - 起動ステップを実行中
not-configured - 接続がまだ構成されていない
登録されたデバイスは、通知チャンネルの状態(XMPP 接続の状態など)に基づいて接続状態をレポートすることがあります。
cs
メーカー文字列デバイス メーカーの名前
モデル文字列デバイスのモデル
serial_number文字列デバイスの固有識別子。この仕様では、これは UUID でなければなりません。(GCP 1.1 仕様)
(省略可)同じシリアル番号 ID をすべての場所で使用することを強く推奨します。これにより、異なるクライアントが同じデバイスを識別できるようになります。たとえば、IPP を実装するプリンタは、「printer-device-id」フィールドでこのシリアル番号 ID を使用できます。
ファームウェア文字列デバイスのファームウェア バージョン
稼働時間intデバイスの起動からの秒数。
setup_url文字列(省略可)設定手順が記載されているページの URL(プロトコルを含む)
support_url文字列(省略可)サポート、FAQ 情報を含むページの URL(プロトコルを含む)
update_url文字列(省略可)ファームウェアの更新手順が記載されているページの URL(プロトコルを含む)
x-privet-token文字列XSSI 攻撃と XSRF 攻撃を防ぐために、すべての API に渡す必要がある X-Privet-Token ヘッダーの値。詳しくは、6.1 をご覧ください。
APIAPI の説明サポートされている API のリスト(下記を参照)
semantic_stateJSON(省略可)CloudDeviceState 形式のデバイスのセマンティック状態。

api - ローカル ネットワーク経由で利用可能な API のリストを含む JSON リストです。ローカル ネットワーク経由で同時に利用できる 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. エラー

/privet/info API は、X-Privet-Token ヘッダーがない場合にのみエラーを返す必要があります。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" URL でこの 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 Cloud Print コネクタ)。

登録プロセスは 3 つのステップで構成されています(Cloud Print の匿名登録を参照)。

  1. 匿名登録プロセスを開始します。
  2. クライアントは、/privet/register API を呼び出してこのプロセスを開始します。その時点で、デバイスはユーザーの確認を待つ場合があります。
  3. リクエスト トークンを取得します。

クライアントは、デバイスが続行の準備ができているかどうかをポーリングで確認します。デバイスの準備が整うと、サーバーにリクエストを送信して登録トークンと登録 URL を取得します。受信したトークンと URL はクライアントに返す必要があります。このステップで、デバイスが登録の初期化を求める別の呼び出しを受信した場合、デバイスは次の処理を行う必要があります。

  • 登録を開始したユーザーと同じユーザーである場合、以前のデータ(ある場合)をすべて削除し、新しい登録プロセスを開始します。
  • 別のユーザーの場合は、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 - 登録プロセスを完了します
ユーザーこのデバイスの所有権を主張するユーザーのメールアドレス。

デバイスは、すべてのアクション(start、getClaimToken、cancel、complete)のメールアドレスが一致することを確認しなければなりません。

4.3.2. 戻る

/privet/register API は次のデータを返します。
値の名前値の型説明
アクション文字列入力パラメータと同じアクション。
ユーザー文字列(省略可)入力パラメータと同じユーザー(入力で省略された場合は欠落している可能性があります)。
token文字列(省略可)登録トークン(getClaimToken レスポンスでは必須、start、complete、cancel では省略)。
claim_url文字列(省略可)登録 URL(「getClaimToken」レスポンスでは必須、「start」、「complete」、「cancel」では省略)。クラウド プリンタの場合、サーバーから受け取った「complete_invite_url」である必要があります。
automated_claim_url文字列(省略可)登録 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」URL でこの API を実装しなければなりません。
GET /privet/accesstoken HTTP/1.1

デバイスが /accesstoken API 呼び出しを受け取った場合、サーバーを呼び出して指定されたユーザーのアクセス トークンを取得し、トークンをクライアントに返す必要があります。クライアントは、アクセス トークンを使用してクラウド経由でこのデバイスにアクセスします。

クラウド プリント デバイスは、次の 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」ヘッダーをチェックしなければなりません。デバイスは、この API を「/privet/capabilities」URL で実装しなければなりません。
GET /privet/capabilities HTTP/1.1
デバイスが /capabilities API 呼び出しを受信したとき、デバイスが対応している場合、更新された機能を取得するためにサーバーに接続すべきです。たとえば、プリンタがクラウド プリント サービスを介して印刷ジョブ(ローカルで受信)を自身に投稿することをサポートしている場合、クラウド プリント サービスが返す機能を返す必要があります。この場合、クラウド プリントは、プリンタにジョブを送信する前に実行する新機能を追加することで、元のプリンタの機能を変更する可能性があります。最も一般的なケースは、サポートされているドキュメント タイプのリストです。プリンタがオフラインの場合は、サポートするドキュメント タイプを返す必要があります。ただし、プリンタがオンラインで、クラウド プリントに登録されている場合は、サポートされているタイプの 1 つとして「*/*」を返さなければなりません。この場合、クラウド プリント サービスが必要な変換を行います。オフライン印刷の場合、プリンタは少なくとも「image/pwg-raster」形式をサポートしなければなりません。

4.5.1. 入力

/privet/capabilities API には次の入力パラメータがあります。
名前
オフライン(省略可)「offline=1」のみにできます。この場合、デバイスはオフラインで使用するための機能(「オンライン」の機能と異なる場合)を返す必要があります。

4.5.2. 戻る

/privet/capabilities API は、デバイスの機能を Cloud Device Description(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" }
                ]
        }
}

: プリンタは、順序を使用してサポートされているコンテンツ タイプの優先度を表します。たとえば、上記のサンプルでは、プリンタは「image/pwg-raster」や「image/jpeg」よりも「application/pdf」データを優先することを指定しています。クライアントは、可能な限りプリンタの優先順位を尊重すべきです(詳しくは 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 エラーコードが含まれます。
timeoutint(省略可)クライアントが再試行するまで待機する秒数(回復可能なエラーの場合のみ)。クライアントは、この値から + 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

このプロトコルがサポートするデバイスタイプの 1 つはプリンタです。このタイプをサポートするデバイスは、プリンタに固有の機能を実装しても構いません。理想的には、クラウド対応プリンタへの印刷はクラウド プリント サーバーを経由します。

場合によっては、クライアントがドキュメントをローカルで送信する必要があることがあります。クライアントに 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" }
                ]
        }
}
クライアントがローカル ネットワーク経由で印刷を開始する方法は 2 つあります。

シンプルな印刷 - クライアントがローカル ネットワーク経由で /submitdoc API にドキュメントを送信します(job_id パラメータは指定しません)。送信されたドキュメントは、デフォルトの印刷チケット設定を使用して印刷されます。印刷ジョブのステータスは必要ありません。プリンタがこのタイプの印刷のみをサポートする場合、/privet /info API レスポンスで/submitdoc API のみをアドバタイズしなければなりません。

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

高度な印刷 - クライアントは、まずリクエストで有効な CJT ジョブチケットを使用して /privet/printer/createjob API を呼び出し、プリンタで印刷ジョブを作成する必要があります。プリンタは、印刷チケットをメモリに保存し、job_id をクライアントに返す必要があります。クライアントは /printer/submitdoc API を呼び出し、以前に受信した job_id を指定します。その時点で、プリンタが印刷を開始します。クライアントは、/privet/printer/jobstate API を呼び出して、印刷ジョブのステータスをプリンタにポーリングします。

マルチクライアント環境では、この API の呼び出し方法は保証されません。1 つのクライアントが別のクライアントの/createjob->/submitdoc 呼び出しの間に /createjob を呼び出すことができます。デッドロックの可能性を排除し、ユーザビリティを向上させるため、プリンタに保留中の印刷ジョブの小さなキュー(少なくとも 3 ~ 5 個)を用意することをおすすめします。

  • /createjob は、キューの最初の空きスポットを取得します。
  • ジョブの有効期間(キュー内)が 5 分以上である。
  • キュー内のすべてのスポットが使用されている場合は、最も古い印刷されていないジョブが削除され、新しいジョブがそこに配置されます。
  • デバイスで現在印刷中の印刷ジョブがある場合(簡易印刷または高度な印刷)、/submitdoc はステータス busy を返し、この印刷ジョブを再試行するためのタイムアウトを提案します。
  • /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」ヘッダーをチェックしなければなりません。デバイスは、この API を「/privet/printer/createjob」URL で実装しなければなりません。

POST /privet/printer/createjob HTTP/1.1
/privet/printer/createjob API 呼び出しを受信したとき、プリンタは新しい印刷ジョブ ID を作成し、受信した印刷チケットを CJT 形式で保存し、印刷ジョブ ID をクライアントに返さなければなりません。

5.1.1. 入力

/privet/printer/createjob API の URL に入力パラメータがありません。リクエスト本文には、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

ローカル ネットワーク経由の印刷(オフラインまたは Cloud Print への再投稿)を実装するには、/privet/printer/submitdoc API が必要です。HTTP POST リクエストです。/privet/printer/submitdoc API は、有効な「X-Privet-Token」ヘッダーをチェックしなければなりません。デバイスは、この API を「/privet/printer/submitdoc」URL で実装しなければなりません。
POST /privet/printer/submitdoc HTTP/1.1
/privet/printer/submitdoc API 呼び出しを受信すると、プリンタは印刷を開始します。印刷を開始できない場合、エラー printer_busy と、クライアントが再試行前に待機する推奨タイムアウト期間を返さなければなりません。

プリンタが内部バッファにすべてのデータを保持できない場合、ドキュメントの一部を印刷してバッファの一部を再び利用可能にするまで、TCP メカニズムを使用してデータ転送を遅くすべきです。(たとえば、プリンタが TCP レイヤで windowsize=0 を設定すると、クライアントは待機することになります)。

ドキュメントをプリンタに送信するのに時間がかかることがあります。印刷の進行中に、クライアントがプリンタとジョブの状態(高度な印刷)を確認できるようにします。そのため、プリンタは /privet/printer/submitdoc API 呼び出しの処理中に、クライアントが/privet/info API と /privet/printer/jobstate API を呼び出すことを許可しなければなりません。すべてのクライアントで新しいスレッドを開始して /privet/printer/submitdoc API 呼び出しを実行し、メインスレッドで /privet/info API と /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。単純な印刷ケースでは省略できます(上記参照)。プリンタから返されたものと一致する必要があります。
user_name(省略可)人が読める形式のユーザー名。これは確定的なものではなく、印刷ジョブのアノテーションにのみ使用する必要があります。ジョブがクラウド プリント サービスに再投稿される場合、この文字列はクラウド プリント ジョブに付加される必要があります。
client_name(省略可)このリクエストを行うクライアント アプリケーションの名前。表示目的のみ。ジョブがクラウド プリント サービスに再投稿される場合、この文字列はクラウド プリント ジョブに付加される必要があります。
job_name(省略可)記録する印刷ジョブの名前。ジョブがクラウド プリント サービスに再投稿される場合、この文字列はクラウド プリント ジョブに付加される必要があります。
オフライン(省略可)offline=1 のみ。この場合、プリンタはオフラインでの印刷のみを試行します(Cloud Print サーバーへの再投稿は行いません)。

リクエストの本文には、印刷用の有効なドキュメントを含める必要があります。「Content-Length」には、リクエストの正しい長さを含める必要があります。「Content-Type」ヘッダーは、ドキュメントの MIME タイプに設定し、CDD のタイプのいずれかと一致させる必要があります(CDD で「*/*」が指定されている場合を除く)。

このリクエストでは、有効なユーザー名(またはメールアドレス)、クライアント名、ジョブ名を指定することを強く推奨します。これらのフィールドは、ユーザー エクスペリエンスを向上させるために UI でのみ使用されます。

5.2.2. 戻る

/privet/printer/submitdoc API は次のデータを返します。
値の名前値の型説明
job_id文字列新しく作成された印刷ジョブの ID(シンプルな印刷)またはリクエストで指定された job_id(高度な印刷)。
expires_inintこの印刷ジョブが有効な秒数。
job_type文字列送信されたドキュメントの Content-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_errorCloud Print へのドキュメントの投稿に失敗しました。
invalid_x_privet_tokenリクエストの X-Privet-Token が無効であるか、空です。

デバイスが /privet/printer/submitdoc を公開していない場合、HTTP 404 エラーを返さなければなりません。X-Privet-Token ヘッダーがない場合、デバイスは HTTP 400 エラーを返さなければなりません。

: /privet/printer/submitdoc API では、プリンタ側で特別な処理が必要になる場合があります(大きなペイロードが添付されているため)。場合によっては(プリンタの HTTP サーバーの実装とプラットフォームによって異なります)、プリンタが HTTP エラーを返す前にソケットを閉じることがあります。それ以外の場合、プリンタは(Privet エラーではなく)503 エラーを返すことがあります。プリンタは、できる限り 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" URL でこの 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。
state文字列draft - デバイスで印刷ジョブが作成されました(/privet/printer/submitdoc 呼び出しはまだ受信されていません)。
queued - 印刷ジョブが受信され、キューに登録されましたが、印刷はまだ開始されていません。
in_progress - 印刷ジョブが印刷中です。
stopped - 印刷ジョブは一時停止されていますが、手動または自動で再開できます。
done - 印刷ジョブが完了しました。
aborted - 印刷ジョブが失敗しました。
説明文字列(省略可)印刷ジョブのステータスの説明(人が読める形式)。state< が stopped または aborted の場合は、追加情報を含める必要があります。通常、semantic_state フィールドは、クライアントに対してより適切で意味のある説明を提供します。
expires_inintこの印刷ジョブが有効な秒数。
job_type文字列(省略可)送信されたドキュメントの Content-type。
job_sizeint 64 ビット(省略可)印刷データのサイズ(バイト単位)。
job_name文字列(省略可)入力と同じジョブ名(ある場合)。
server_job_id文字列(省略可)サーバーから返されたジョブの ID(ジョブが Google クラウド プリント サービスに投稿されている場合)。オフライン印刷では省略されます。
semantic_stateJSON(省略可)PrintJobState 形式のジョブのセマンティック状態。

例(Cloud Print を介してレポートで印刷する場合):

{
        "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 API と /privet/register API のみをサポートすべきです。他のすべての API(/privet/accesstoken、ローカル印刷など)は無効にする必要があります。
  • 登録にはデバイスの物理的な操作が必要です。
    • ユーザーは、デバイスへのアクセスを確認するために、デバイス上で物理的な操作(ボタンを押すなど)を行わなければなりません。
    • ユーザーが上記のアクションを行うと、プリンタは /cloudprint/register リクエストを送信します。このリクエストは、アクションが実行されるまで送信しないでください(シーケンス図 1 を参照)。
    • デバイスが /privet/register リクエストを処理している場合(たとえば、上記のアクションを待機している場合)、他のすべての /privet/register リクエストを拒否する必要があります。この場合、デバイスは device_busy エラーを返さなければなりません。
    • デバイスは、上記の物理的な操作を 60 秒以内に受け取らなかった /register リクエストをタイムアウトさせるべきです。この場合、デバイスは confirmation_timeout エラーを返さなければなりません。
    • 省略可: 推奨されますが必須ではありません。以下はユーザー エクスペリエンスを向上させる可能性があります。
      • プリンタが点滅したり、画面に登録を確認する操作が必要であることを示すメッセージが表示されたりすることがあります。
      • プリンタの画面に「ユーザー「abc@def.com」の Google クラウド プリントに登録中です。続行するには [OK] を押してください」と表示されることがあります。ここで、abc@def.com は /register API 呼び出しのユーザー パラメータです。これにより、ユーザーは次のことをより明確に認識できるようになります。
        • 確認しているのは登録リクエストであること
        • リクエストをトリガーしていない場合はどうなりますか?
      • プリンタから確認する物理的な操作([OK] ボタンを押してください」)と表示されることがあります。また、プリンタによっては、リクエストをキャンセルするボタン((「キャンセルを押して拒否」など)。これにより、登録リクエストをトリガーしていないユーザーは、60 秒のタイムアウト前に登録リクエストをキャンセルできます。この場合、デバイスは user_cancel エラーを返さなければなりません。
  • 所有権の移行:
    • デバイスがクラウド サービスから明示的に削除されている可能性があります。
      • デバイスが成功を受け取ったものの、/cloudprint/printer(GCP の場合)呼び出しの結果としてデバイスの説明を受け取らなかった場合、デフォルト(初期設定)モードに戻さなければなりません。
      • デバイスの認証情報が機能しなくなった場合(サーバーからの「無効な認証情報」という応答が明示的に返された場合)、デフォルト(初期設定)モードに戻さなければなりません。
    • ローカルでの出荷時の設定へのリセットでは、デバイスの認証情報をクリアし、デフォルトの状態に設定しなければなりません。
    • 省略可: デバイスは、認証情報をクリアしてデフォルト モードにするためのメニュー項目を提供しても構いません。
  • XMPP 通知をサポートするデバイスは、サーバーに ping を送信する機能を備えなければなりません。ping タイムアウトは、サーバーから「local_settings」を通じて制御できなければなりません。
  • デバイスは、同期を確実にするため、1 日(24 時間)に 1 回を超えない頻度で、サーバーに明示的に ping を送信する(GCP の場合は /cloudprint/printer API、XMPP 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 をご覧ください。
通常、XSSI 攻撃と XSRF 攻撃は、サイトが Cookie 認証メカニズムを使用している場合に発生する可能性があります。Google は Cloud Print Service で 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 がトークン内のものと一致する場合、デバイスは 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. プリンタ設定の確認ワークフロー