Privet

Privet est une API Cloud Device Local Discovery utilisée par les services cloud. Ce document est organisé dans les sections suivantes :

  1. Introduction : présentation de Privet
  2. Discovery : mécanismes de découverte locale
  3. Annonces : annonces de découverte locale
  4. API : API Privet pour les appareils cloud généraux
  5. API Printer : API Privet utilisées par les imprimantes
  6. Annexe : schémas supplémentaires

1. Introduction

Les appareils connectés au cloud présentent de nombreux avantages. Ils peuvent utiliser des services de conversion en ligne, héberger des files d'attente de tâches lorsque l'appareil est hors connexion et être accessibles depuis n'importe où dans le monde. Cependant, comme un utilisateur donné peut accéder à de nombreux appareils cloud, nous devons fournir une méthode pour trouver l'appareil le plus proche en fonction de la position. Le protocole Privet a pour objectif de combiner la flexibilité des appareils cloud avec un mécanisme de découverte local adapté afin que les appareils soient facilement détectés dans de nouveaux environnements.

Les objectifs de ce protocole sont les suivants :
  • rendre les appareils cloud détectables localement ;
  • enregistrer des appareils cloud auprès d'un service cloud ;
  • associer les appareils enregistrés à leur représentation dans le cloud.
  • permettre un usage hors connexion.
  • simplifier l'implémentation pour que les petits appareils puissent l'utiliser ;

Le protocole Privet se compose de deux parties principales : la découverte et l'API. La découverte permet de trouver l'appareil sur le réseau local, et l'API permet d'obtenir des informations sur l'appareil et d'effectuer certaines actions. Dans ce document, l'appareil désigne un appareil connecté au cloud qui implémente le protocole Privet.

2. Discovery

La découverte est un protocole basé sur Zeroconf (mDNS + DNS-SD). L'appareil DOIT implémenter l'adressage de liaison locale IPv4. L'appareil DOIT être conforme aux spécifications mDNS et DNS-SD.

L'appareil DOIT résoudre les conflits de noms conformément aux spécifications ci-dessus.

2.1. Type de service

La découverte de services DNS utilise le format suivant pour les types de services : _applicationprotocol._transportprotocol. Dans le cas du protocole Privet, le type de service pour DNS-SD doit être _privet._tcp.

L'appareil peut également implémenter d'autres types de services. Il est conseillé d'utiliser le même nom d'instance de service pour tous les types de services implémentés par l'appareil. Par exemple, une imprimante peut implémenter les services "Printer XYZ._privet._tcp" et "Printer XYZ._printer._tcp". Cela simplifiera la configuration pour l'utilisateur. Toutefois, les clients Privet ne rechercheront que "_privet._tcp".

En plus du type de service principal, l'appareil DOIT annoncer les enregistrements PTR pour ses sous-types correspondants (voir la spécification DNS-SD : "7.1. Énumération sélective des instances (sous-types)"). Le format doit être le suivant : _<subtype>._sub._privet._tcp

Actuellement, le seul sous-type d'appareil accepté est printer. Par conséquent, toutes les imprimantes DOIVENT annoncer deux enregistrements PTR :

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

2.2. Enregistrement TXT

La recherche de services DNS définit les champs permettant d'ajouter des informations facultatives sur un service dans les enregistrements TXT. Un enregistrement TXT est constitué de paires clé/valeur. Chaque paire clé/valeur commence par l'octet de longueur, suivi d'un maximum de 255 octets de texte. La clé correspond au texte avant le premier caractère "=", et la valeur correspond au texte après le premier caractère "=" jusqu'à la fin. La spécification n'autorise aucune valeur dans l'enregistrement. Dans ce cas, il n'y aura pas de caractère "=" ni de texte après le caractère "=". (Consultez la spécification DNS-SD : "6.1. Règles générales de format pour les enregistrements TXT DNS" pour le format des enregistrements TXT DNS et "6.2. Taille de l'enregistrement TXT DNS-SD" (pour connaître la longueur recommandée).

Privet exige que l'appareil envoie les paires clé/valeur suivantes dans l'enregistrement TXT. Les chaînes clé/valeur ne sont pas sensibles à la casse. Par exemple, "CS=online" et "cs=ONLINE" sont identiques. Les informations du fichier TXT DOIVENT être identiques à celles accessibles via l'API /info (voir 4.1). section "API").

Nous vous recommandons de ne pas dépasser 512 octets pour la taille de l'enregistrement TXT.

2.2.1. txtvers

Version de la structure TXT. txtvers DOIT être le premier enregistrement de la structure TXT. Pour le moment, seule la version 1 est acceptée.

txtvers=1

2.2.2. ty

Fournit un nom d'appareil lisible par l'utilisateur. Exemple :

ty=Google Cloud Ready Printer Model XYZ

2.2.3. note (facultatif)

Fournit un nom d'appareil lisible par l'utilisateur. Exemple :

note=1st floor lobby printer

Remarque : Cette clé est facultative et peut être ignorée. Toutefois, si elle est présente, l'utilisateur DOIT pouvoir modifier cette valeur. La même description DOIT être utilisée lors de l'enregistrement de l'appareil.

2.2.4. url

URL du serveur auquel cet appareil est connecté (y compris le protocole). Exemple :

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

2.2.5. type

Liste des sous-types d'appareils compatibles avec cet appareil, séparés par une virgule. Le format est le suivant : "type=_subtype1,_subtype2". Actuellement, le seul sous-type d'appareil accepté est printer.

type=printer

Chaque sous-type listé doit être annoncé à l'aide d'un enregistrement PTR correspondant. Pour chaque sous-type de service compatible, il doit y avoir un élément correspondant. Le nom du sous-type de service (<subtype>._sub._privet._tcp) doit être égal au type d'appareil ici.

2.2.6. id

ID de l'appareil Si l'appareil n'a pas encore été enregistré, cette clé doit être présente, mais la valeur doit être vide. Exemple :

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

2.2.7. cs

Indique l'état de connexion actuel de l'appareil. Quatre valeurs possibles sont définies dans cette spécification.

  • "En ligne" indique que l'appareil est actuellement connecté au cloud.
  • "Hors connexion" indique que l'appareil est disponible sur le réseau local, mais qu'il ne peut pas communiquer avec le serveur.
  • "Connexion" indique que l'appareil effectue sa séquence de démarrage et n'est pas encore entièrement en ligne.
  • "not-configured" (non configuré) indique que l'accès à Internet de l'appareil n'a pas encore été configuré. Cette valeur n'est pas utilisée actuellement, mais elle peut être utile dans les futures versions de la spécification.
Par exemple :
  • cs=online
  • cs=offline
  • cs=connecting

Si l'appareil a été enregistré auprès d'un cloud, il doit vérifier la connectivité avec un serveur au démarrage pour détecter son état de connexion (par exemple, en appelant l'API cloud pour obtenir les paramètres de l'appareil). L'appareil peut utiliser l'état de connexion de son canal de notifications (par exemple, XMPP) pour signaler cette valeur. Au démarrage, les appareils non enregistrés peuvent pinguer un domaine afin de détecter leur état de connexion (par exemple, pinguer www.google.com pour les appareils Cloud Print).

3. Annonces

Au démarrage, à l'arrêt ou lors d'un changement d'état de l'appareil, celui-ci DOIT effectuer l'étape d'annonce décrite dans la spécification mDNS. Il DOIT envoyer l'annonce correspondante au moins deux fois, avec un intervalle d'au moins une seconde entre les deux.

3.1. Démarrage

Au démarrage de l'appareil, il DOIT effectuer les étapes de sondage et d'annonce décrites dans la spécification mDNS. Dans ce cas, les enregistrements SRV, PTR et TXT doivent être envoyés. Il est recommandé de regrouper tous les enregistrements dans une seule réponse DNS, si possible. Si ce n'est pas le cas, l'ordre suivant est recommandé : enregistrements SRV, PTR et TXT.

3.2. Arrêt

Lors de l'arrêt de l'appareil, il DOIT essayer d'en informer toutes les parties intéressées en envoyant un "paquet de clôture" avec TTL=0 (comme décrit dans la documentation mDNS).

3.3. Mettre à jour

Si l'une des informations décrites dans le TXT a changé, l'appareil DOIT envoyer une annonce de mise à jour. Dans ce cas, il suffit d'envoyer le nouvel enregistrement TXT. Par exemple, une fois un appareil enregistré, il DOIT envoyer une annonce de mise à jour incluant le nouvel ID de l'appareil.

4. API

Une fois qu'un appareil cloud a été détecté, la communication du client est activée avec l'appareil directement sur le réseau local. Toutes les API sont basées sur HTTP 1.1. Les formats de données sont basés sur JSON. Les requêtes API peuvent être des requêtes GET ou POST.

Chaque requête DOIT contenir un en-tête "X-Privet-Token" valide. La SEULE requête autorisée à avoir un en-tête "X-Privet-Token" vide est la requête /privet/info (notez que l'en-tête DOIT toujours être présent). Si l'en-tête "X-Privet-Token" est manquant, l'appareil DOIT répondre avec l'erreur HTTP 400 suivante :

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

Si l'en-tête "X-Privet-Token" est vide ou non valide, l'appareil DOIT répondre avec l'erreur "invalid X-Privet-Token error" (invalid_x_privet_token, voir la section "Erreurs" pour plus d'informations). La seule exception concerne l'API /info. Pour en savoir plus sur les raisons de cette procédure et sur la façon de générer des jetons, consultez l'annexe A : Attaques XSSI et XSRF et prévention.

Si une API demandée n'existe pas ou n'est pas compatible, l'appareil DOIT renvoyer une erreur HTTP 404.

4.1. Disponibilité de l'API

Avant qu'UNE API soit exposée (y compris l'API /info), l'appareil DOIT contacter le serveur pour vérifier les paramètres locaux. Les paramètres locaux DOIVENT être conservés entre les redémarrages. Si le serveur n'est pas disponible, les derniers paramètres locaux connus doivent être utilisés. Si l'appareil n'a pas encore été enregistré, il doit suivre les paramètres par défaut.

Les appareils Cloud Print DOIVENT suivre les étapes ci-dessous pour s'enregistrer, recevoir et mettre à jour les paramètres locaux.

4.1.1. Inscription

Lorsque l'appareil s'enregistre, il DOIT spécifier le paramètre "local_settings", comme suit :

{
       "current": {
                "local_discovery": true,
                "access_token_enabled": true,
                "printer/local_printing_enabled": true,
                "printer/conversion_printing_enabled": true,
                "xmpp_timeout_value": 300
        }
}
Vous pouvez définir les paramètres suivants :
Nom de la valeurType de valeurDescription
local_discoverybooléenIndique si la fonctionnalité de découverte locale est autorisée. Si la valeur est "false", toutes les API locales (y compris /info) et la découverte DNS-SD doivent être désactivées. Par défaut, les appareils nouvellement enregistrés doivent renvoyer "true".
access_token_enabledbooléen (facultatif)Indique si l'API /accesstoken doit être exposée sur le réseau local. La valeur par défaut doit être "true".
printer/local_printing_enabledbooléen (facultatif)Indique si la fonctionnalité d'impression locale (/printer/createjob, /printer/submitdoc, /printer/jobstate) doit être exposée sur le réseau local. La valeur par défaut doit être "true".
printer/conversion_printing_enabledbooléen (facultatif)Indique si l'impression locale peut envoyer le travail au serveur pour conversion. N'a de sens que si l'impression locale est activée.
xmpp_timeout_valueint (facultatif)Indique le nombre de secondes entre les pings du canal XMPP. Par défaut, la valeur DOIT être de 300 (5 minutes) ou plus.

Important : L'absence de toute valeur facultative indique que la fonctionnalité correspondante n'est pas du tout prise en charge par l'appareil.

4.1.2. Démarrage

Au démarrage de l'appareil, il doit contacter le serveur pour vérifier quelles API peuvent être exposées sur le réseau local. Pour les imprimantes connectées à Cloud Print, vous devez appeler :

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

/cloudprint/printer est préférable à /cloudprint/list, mais les deux fonctionnent.

Cette API renvoie les paramètres actuels de l'appareil, y compris les paramètres de l'API locale. La réponse du serveur se présente au format suivant :

"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
         }
}

L'objet "current" indique les paramètres en vigueur actuellement.

L'objet "pending" indique les paramètres à appliquer à l'appareil (cet objet peut être manquant).

Une fois que l'appareil détecte des paramètres "en attente", il DOIT mettre à jour son état (voir ci-dessous).

4.1.3. Mettre à jour

Si une mise à jour des paramètres est nécessaire, une notification XMPP sera envoyée à l'appareil. La notification sera au format suivant :

<device_id>/update_settings

Lorsqu'il reçoit une telle notification, l'appareil DOIT interroger le serveur pour obtenir les derniers paramètres. Les appareils Cloud Print DOIVENT utiliser :

/cloudprint/printer?printerid=<printer_id>

Une fois que l'appareil voit la section "En attente" à la suite de l'API /cloudprint/printer (au démarrage ou en raison de la notification), il DOIT mettre à jour son état interne pour mémoriser les nouveaux paramètres. Il DOIT appeler l'API du serveur pour confirmer les nouveaux paramètres. Pour les imprimantes cloud, l'appareil DOIT appeler l'API /cloudprint/update et utiliser le paramètre "local_settings" comme lors de l'enregistrement.

Lors de la reconnexion au canal XMPP, l'appareil DOIT appeler l'API /cloudprint/printer pour vérifier si les paramètres locaux ont été modifiés depuis la dernière fois.

4.1.3.1. Paramètres locaux en attente

Le paramètre "local_settings" que l'appareil utilise pour appeler l'API du serveur ne doit JAMAIS contenir de section "pending".

4.1.3.2. Paramètres actuels des campagnes locales

SEUL l'appareil peut modifier la section "current" (actuel) de "local_settings" (paramètres locaux). Tous les autres utilisateurs modifieront la section "en attente" et attendront que les modifications soient propagées à la section "actuelle" par l'appareil.

4.1.4. Hors connexion

Lorsqu'il est impossible de contacter le serveur au démarrage, l'appareil DOIT utiliser les derniers paramètres locaux connus après la notification.

4.1.5. Supprimer un appareil du service

Si l'appareil a été supprimé du service (GCP, par exemple), une notification XMPP lui sera envoyée. La notification sera au format suivant :

<device_id>/delete

Lorsqu'un appareil reçoit une telle notification, il DOIT accéder au serveur pour vérifier son état. Les appareils Cloud Print DOIVENT utiliser :

/cloudprint/printer?printerid=<printer_id>

L'appareil DOIT recevoir une réponse HTTP réussie avec success=false et aucune description d'appareil/imprimante. Cela signifie que l'appareil a été supprimé du serveur et qu'il DOIT effacer ses identifiants et passer en mode de configuration d'usine par défaut.

À CHAQUE fois que l'appareil reçoit une réponse indiquant qu'il a été supprimé à la suite de l'API /cloudprint/printer (démarrage, notification de mise à jour des paramètres, ping quotidien), il DOIT supprimer ses identifiants et passer en mode par défaut.

4.2. API /privet/info

L'API Info est OBLIGATOIRE et DOIT être implémentée par chaque appareil. Il s'agit d'une requête HTTP GET pour l'URL "/privet/info" : GET /privet/info HTTP/1.1

L'API Info renvoie des informations de base sur un appareil et les fonctionnalités qu'il prend en charge. Cette API ne DOIT jamais modifier l'état de l'appareil ni effectuer d'action, car elle est vulnérable aux attaques XSRF. Il s'agit de la SEULE API autorisée à avoir un en-tête "X-Privet-Token" vide. Les clients doivent appeler l'API /privet/info avec l'en-tête "X-Privet-Token" défini sur X-Privet-Token: ""

L'API d'informations DOIT renvoyer des données cohérentes avec celles disponibles dans l'enregistrement TXT lors de la découverte.

4.2.1. Entrée

L'API /privet/info ne comporte aucun paramètre d'entrée.

4.2.2. Renvois

L'API /privet/info renvoie des informations de base sur l'appareil et les fonctionnalités compatibles.

La colonne "TXT" indique le champ correspondant dans l'enregistrement TXT DNS-SD.

Nom de la valeurType de valeurDescriptionTXT
versionchaîneVersion (majeure.mineure) la plus élevée de l'API acceptée, actuellement 1.0
nomchaîneNom de l'appareil dans un format lisible.ty
descriptionchaîne(facultatif) Description de l'appareil. DOIT être modifiable par l'utilisateur.note
urlchaîneURL du serveur avec lequel cet appareil communique. L'URL DOIT inclure la spécification du protocole, par exemple https://www.google.com/cloudprint.url
typeliste de chaînesListe des types d'appareils compatibles.type
idchaîneID de l'appareil (vide si l'appareil n'a pas encore été enregistré). id
device_statechaîneÉtat de l'appareil.
idle signifie que l'appareil est prêt.
processing signifie que l'appareil est occupé et que les fonctionnalités peuvent être limitées pendant un certain temps.
stopped signifie que l'appareil ne fonctionne pas et qu'une intervention de l'utilisateur est requise.
connection_statechaîneÉtat de la connexion au serveur (base_url)
online : connexion disponible
offline : aucune connexion
connecting : étapes de démarrage en cours
not-configured : la connexion n'a pas encore été configurée
Un appareil enregistré peut indiquer son état de connexion en fonction de l'état du canal de notification (par exemple, l'état de la connexion XMPP).
cs
manufacturerchaîneNom du fabricant de l'appareil
modèlechaîneModèle de l'appareil
serial_numberchaîneIdentifiant unique de l'appareil. Dans cette spécification, il DOIT s'agir d'un UUID. (Spécification GCP 1.1)
(facultatif) Nous vous recommandons vivement d'utiliser le même ID de numéro de série partout, afin que différents clients puissent identifier le même appareil. Par exemple, les imprimantes implémentant IPP peuvent utiliser cet ID de numéro de série dans le champ "printer-device-id".
micrologicielchaîneVersion du micrologiciel de l'appareil
temps de serviceintNombre de secondes depuis le démarrage de l'appareil.
setup_urlchaîne(Facultatif) URL (y compris le protocole) de la page contenant les instructions de configuration
support_urlchaîne(facultatif) URL (y compris le protocole) de la page contenant des informations sur l'assistance et les questions fréquentes
update_urlchaîne(Facultatif) URL (y compris le protocole) de la page contenant les instructions de mise à jour du micrologiciel
x-privet-tokenchaîneValeur de l'en-tête X-Privet-Token qui doit être transmise à toutes les API pour éviter les attaques XSSI et XSRF. Pour en savoir plus, consultez la section 6.1.
apidescription des API ;Liste des API compatibles (décrites ci-dessous)
semantic_stateJSON(Facultatif) État sémantique de l'appareil au format CloudDeviceState.

api : liste JSON contenant la liste des API disponibles sur le réseau local. Notez que toutes les API ne sont pas forcément disponibles en même temps sur le réseau local. Par exemple, un nouvel appareil connecté ne doit prendre en charge que l'API /register :

"api": [
        "/privet/register",
]
Une fois l'enregistrement de l'appareil terminé, l'appareil NE DOIT PLUS être compatible avec l'API /register. L'appareil doit également vérifier auprès du service les API qui peuvent être exposées sur le réseau local. Exemple :
"api": [
        "/privet/accesstoken",
        "/privet/capabilities",
        "/privet/printer/submitdoc",
]

Les API suivantes sont disponibles pour le moment :

  • /privet/register : API permettant d'enregistrer un appareil sur le réseau local. (pour en savoir plus, consultez l'API /privet/register). Cette API DOIT être masquée une fois l'appareil correctement enregistré dans le cloud.
  • /privet/accesstoken : API permettant de demander un jeton d'accès à l'appareil (pour en savoir plus, consultez l'API /privet/accesstoken).
  • /privet/capabilities : API permettant de récupérer les fonctionnalités de l'appareil (pour en savoir plus, consultez l'API /privet/capabilities).
  • /privet/printer/* : API spécifique au type d'appareil "printer" (imprimante). Pour en savoir plus, consultez les API spécifiques aux imprimantes.
Voici un exemple de réponse /privet/info. (Notez l'absence de l'API /privet/register, car il s'agit d'un appareil déjà enregistré) :
{
        "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",
        ]
}
Voici un exemple de réponse /privet/info pour une imprimante à court d'encre (notez le champ 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. Erreurs

L'API /privet/info ne doit renvoyer une erreur que si l'en-tête X-Privet-Token est manquant. Il DOIT s'agir d'une erreur HTTP 400 :

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

4.3. API /privet/register

L'API /privet/register est FACULTATIVE. Il s'agit d'une requête HTTP POST. L'API /privet/register DOIT vérifier la présence d'un en-tête X-Privet-Token valide. L'appareil DOIT implémenter cette API sur l'URL "/privet/register" :

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

L'appareil ne doit exposer l'API /privet/register que lorsqu'il autorise l'enregistrement anonyme. Exemple :

  • Lorsque l'appareil est allumé (ou après avoir cliqué sur un bouton spécial sur l'appareil) et qu'il n'a pas encore été enregistré, il doit exposer l'API /privet/register pour permettre à un utilisateur du réseau local de revendiquer l'imprimante.
  • Une fois l'enregistrement terminé, l'appareil ne doit plus exposer l'API /privet/register pour empêcher un autre utilisateur du réseau local de récupérer l'appareil.
  • Certains appareils peuvent avoir différentes façons d'enregistrer des appareils et ne doivent pas exposer l'API /privet/register du tout (par exemple, le connecteur Chrome Cloud Print).

Le processus d'enregistrement comporte trois étapes (voir l'enregistrement anonyme pour Cloud Print).

  1. Lancez la procédure d'inscription anonyme.
  2. Un client lance ce processus en appelant l'API /privet/register. L'appareil peut attendre la confirmation de l'utilisateur à ce moment-là.
  3. Obtenez un jeton de demande de renseignements.

Le client interroge le serveur pour savoir quand l'appareil est prêt à continuer. Une fois l'appareil prêt, il envoie une requête au serveur pour récupérer le jeton et l'URL d'enregistrement. Le jeton et l'URL reçus DOIVENT être renvoyés au client. Au cours de cette étape, si l'appareil reçoit un autre appel pour initialiser l'enregistrement, il doit :

  • S'il s'agit du même utilisateur qui a commencé l'enregistrement, supprimez toutes les données précédentes (le cas échéant) et lancez un nouvel enregistrement.
  • S'il s'agit d'un autre utilisateur, renvoyez une erreur device_busy et un délai de 30 secondes.

Suivez la procédure d'inscription.

Une fois que le client a revendiqué l'appareil, il doit notifier l'appareil pour finaliser l'enregistrement. Une fois le processus d'enregistrement terminé, l'appareil doit envoyer une annonce de mise à jour, y compris l'ID de l'appareil nouvellement acquis.

Remarque : Lorsque l'appareil traite un appel d'API /privet/register, aucun autre appel d'API /privet/register ne peut être traité simultanément. L'appareil DOIT renvoyer l'erreur device_busy et un délai avant expiration de 30 secondes.

Il est FORTEMENT recommandé de demander à l'utilisateur de confirmer l'enregistrement sur l'appareil. Si elle est implémentée, l'appareil DOIT attendre la confirmation de l'utilisateur APRÈS avoir reçu un appel d'API /privet/register?action=start.  Le client appellera l'API /privet/register?action=getClaimToken pour savoir quand la confirmation de l'utilisateur est terminée et que le jeton de revendication est disponible. Si l'utilisateur annule l'enregistrement sur l'appareil (par exemple, en appuyant sur le bouton "Annuler"), l'erreur user_cancel DOIT être renvoyée. Si l'utilisateur n'a pas confirmé son inscription dans un certain délai, l'erreur confirmation_timeout DOIT être renvoyée. Pour en savoir plus, consultez la section sur les valeurs par défaut.

4.3.1. Entrée

L'API /privet/register comporte les paramètres d'entrée suivants :
NomValeur
actionPeut être l'une des valeurs suivantes :
start : pour démarrer la procédure d'enregistrement
getClaimToken : pour récupérer le jeton de revendication de l'appareil
cancel : pour annuler la procédure d'enregistrement
complete : pour terminer la procédure d'enregistrement
utilisateurAdresse e-mail de l'utilisateur qui revendiquera cet appareil.

L'appareil DOIT vérifier que l'adresse e-mail de toutes les actions (démarrer, getClaimToken, annuler, terminer) correspond.

4.3.2. Renvois

L'API /privet/register renvoie les données suivantes :
Nom de la valeurType de valeurDescription
actionchaîneMême action que dans le paramètre d'entrée.
utilisateurchaîne (facultatif)Même utilisateur que dans le paramètre d'entrée (peut être manquant s'il est omis dans l'entrée).
jetonchaîne (facultatif)Jeton d'enregistrement (obligatoire pour la réponse "getClaimToken", omis pour "start", "complete", "cancel").
claim_urlchaîne (facultatif)URL d'enregistrement (obligatoire pour la réponse "getClaimToken", omise pour "start", "complete", "cancel"). Pour les imprimantes cloud, il doit s'agir de l'URL d'invitation complète reçue du serveur.
automated_claim_urlchaîne (facultatif)URL d'enregistrement (obligatoire pour la réponse "getClaimToken", omise pour "start", "complete", "cancel"). Pour les imprimantes Cloud, il doit s'agir de l'URL d'invitation automatique reçue du serveur.
device_idchaîne (facultatif)ID du nouvel appareil (omis pour la réponse "start", obligatoire pour "complete").

L'appareil DOIT renvoyer son ID dans la réponse de l'API /privet/info UNIQUEMENT une fois l'enregistrement terminé.

Exemple 1 :

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

Exemple 2 :

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

Exemple 3 :

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

4.3.3. Erreurs

L'API /privet/register peut renvoyer les erreurs suivantes (pour en savoir plus, consultez la section "Erreurs") :
ErreurDescription
device_busyL'appareil est occupé et ne peut pas effectuer l'action demandée. Réessayez après le délai d'expiration.
pending_user_actionEn réponse à "getClaimToken", cette erreur indique que l'appareil est toujours en attente de confirmation de l'utilisateur et que la requête "getClaimToken" doit être réessayée après le délai d'expiration.
user_cancelL'utilisateur a explicitement annulé le processus d'enregistrement depuis l'appareil.
confirmation_timeoutLe délai de confirmation de l'utilisateur est dépassé.
invalid_actionUne action non valide est appelée. Par exemple, si le client a appelé action=complete avant d'appeler action=start et action=getClaimToken.
invalid_paramsParamètres non valides spécifiés dans la requête. (Les paramètres inconnus doivent être ignorés sans risque pour la compatibilité future.) Par exemple, renvoyez cette valeur si le client a appelé action=unknown ou user=.
device_config_errorLa date/l'heure (ou d'autres paramètres) sont incorrectes sur l'appareil. L'utilisateur doit accéder au site Web interne de l'appareil et configurer ses paramètres.
Hors connexionL'appareil est actuellement hors connexion et ne peut pas communiquer avec le serveur.
server_errorErreur du serveur lors de la procédure d'enregistrement.
invalid_x_privet_tokenLe jeton X-Privet-Token n'est pas valide ou est vide dans la requête.

L'appareil DOIT cesser d'exposer l'API /privet/register une fois l'enregistrement terminé. Si l'appareil n'expose pas l'API /privet/register, il DOIT renvoyer une erreur HTTP 404. Par conséquent, si un appareil est déjà enregistré, l'appel de cette API DOIT renvoyer une erreur 404. Si l'en-tête X-Privet-Token est manquant, l'appareil DOIT renvoyer une erreur HTTP 400.

4.4. API /privet/accesstoken

L'API /privet/accesstoken est FACULTATIVE. Il s'agit d'une requête HTTP GET. L'API /privet/accesstoken DOIT vérifier si l'en-tête "X-Privet-Token" est valide. L'appareil DOIT implémenter cette API sur l'URL "/privet/accesstoken" :
GET /privet/accesstoken HTTP/1.1

Lorsque l'appareil reçoit l'appel d'API /accesstoken, il doit appeler le serveur pour récupérer le jeton d'accès pour l'utilisateur donné et renvoyer le jeton au client. Le client utilisera ensuite le jeton d'accès pour accéder à cet appareil via le cloud.

Les appareils Cloud Print DOIVENT appeler l'API suivante :

/cloudprint/proximitytoken
et transmettez les paramètres "printerid=<printer_id>" et "user" depuis l'API locale. Si l'opération réussit, la réponse du serveur contient l'objet suivant :
"proximity_token": {
        "user": "user@domain.com",
        "token": "AAA111222333444555666777",
        "expires_in": 600
}
Les appareils Cloud Print DOIVENT transmettre la valeur de l'objet "proximity_token" dans la réponse aux appels d'API /privet/accesstoken locaux. Il est plus avantageux (pour l'avenir) que l'appareil puisse transmettre TOUS les paramètres (y compris ceux qui ne sont pas décrits dans cette spécification).

4.4.1. Entrée

L'API /privet/accesstoken comporte les paramètres d'entrée suivants :
NomValeur
utilisateurAdresse e-mail de l'utilisateur qui souhaitait utiliser ce jeton d'accès. Peut être vide dans la requête.

4.4.2. Renvois

L'API /privet/accesstoken renvoie les données suivantes :
Nom de la valeurType de valeurDescription
jetonchaîneJeton d'accès renvoyé par le serveur
utilisateurchaîneMême utilisateur que dans le paramètre d'entrée.
expires_inintNombre de secondes avant l'expiration de ce jeton. Reçu du serveur et transmis dans cette réponse.

Exemple :

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

4.4.3. Erreurs

L'API /privet/accesstoken peut renvoyer les erreurs suivantes (consultez la section "Erreurs" pour en savoir plus) :
ErreurDescription
Hors connexionL'appareil est actuellement hors connexion et ne peut pas communiquer avec le serveur.
access_deniedDroits insuffisants. Accès refusé. L'appareil doit renvoyer cette erreur lorsque la requête a été explicitement refusée par le serveur.
invalid_paramsParamètres non valides spécifiés dans la requête. (Les paramètres inconnus doivent être ignorés sans risque pour la compatibilité future.) Par exemple, si le client a appelé /accesstoken?user= ou /accesstoken.
server_errorErreur du serveur.
invalid_x_privet_tokenLe jeton X-Privet-Token est vide ou non valide dans la requête.

Si l'appareil n'expose pas l'API /privet/accesstoken, il DOIT renvoyer une erreur HTTP 404. Si l'en-tête X-Privet-Token est manquant, l'appareil DOIT renvoyer une erreur HTTP 400.

4.5. API /privet/capabilities

L'API /privet/capabilities est FACULTATIVE. Il s'agit d'une requête HTTP GET. L'API /privet/capabilities DOIT vérifier la présence d'un en-tête "X-Privet-Token" valide. L'appareil DOIT implémenter cette API sur l'URL "/privet/capabilities" :
GET /privet/capabilities HTTP/1.1
Lorsque l'appareil reçoit l'appel d'API /capabilities, il DOIT contacter le serveur pour obtenir les fonctionnalités mises à jour, si possible. Par exemple, si une imprimante est compatible avec l'envoi d'une tâche d'impression (reçue localement) à elle-même via le service Cloud Print, elle doit renvoyer les fonctionnalités que le service Cloud Print renverrait. Dans ce cas, Cloud Print peut modifier les fonctionnalités d'origine de l'imprimante en ajoutant de nouvelles fonctionnalités qu'il peut effectuer avant d'envoyer le travail à l'imprimante. Le cas le plus courant est une liste des types de documents acceptés. Si l'imprimante est hors connexion, elle doit renvoyer les types de documents qu'elle prend en charge. Toutefois, si l'imprimante est en ligne et enregistrée auprès de Cloud Print, elle DOIT renvoyer "*/*" comme l'un des types compatibles. Le service Cloud Print effectuera la conversion nécessaire dans ce cas. Pour l'impression hors connexion, l'imprimante DOIT être compatible avec au moins le format "image/pwg-raster".

4.5.1. Entrée

L'API /privet/capabilities comporte les paramètres d'entrée suivants :
NomValeur
Hors connexion(facultatif) Ne peut être défini que sur "offline=1". Dans ce cas, l'appareil doit renvoyer les fonctionnalités pour une utilisation hors connexion (si elles sont différentes des fonctionnalités "en ligne").

4.5.2. Renvois

L'API /privet/capabilities renvoie les fonctionnalités de l'appareil au format JSON de la description de l'appareil cloud (CDD, Cloud Device Description). Pour en savoir plus, consultez le document CDD. Les imprimantes DOIVENT au minimum renvoyer une liste des types compatibles ici. Par exemple, une imprimante Cloud Ready actuellement en ligne peut renvoyer une réponse de ce type (au minimum) :
{
        "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": "*/*" }
                ]
        }
}
et lorsqu'il est déconnecté du serveur, il peut renvoyer :
{
        "version": "1.0",
        "printer": {
                "supported_content_type": [
                        {
                                "content_type": "application/pdf",
                                "min_version": "1.4"
                        },
                        { "content_type": "image/pwg-raster" },
                        { "content_type": "image/jpeg" }
                ]
        }
}

Remarque : Les imprimantes expriment la priorité des types de contenu compatibles à l'aide de l'ordre. Par exemple, dans les exemples ci-dessus, l'imprimante indique qu'elle préfère les données "application/pdf" à "image/pwg-raster" et "image/jpeg". Si possible, les clients doivent respecter la priorité des imprimantes (pour en savoir plus, consultez le document CDD).

4.5.3. Erreurs

L'API /privet/capabilities peut renvoyer les erreurs suivantes (consultez la section "Erreurs" pour en savoir plus) :
ErreurDescription
invalid_x_privet_tokenLe jeton X-Privet-Token n'est pas valide ou est vide dans la requête.

Si l'appareil n'expose pas l'API /privet/capabilities, il DOIT renvoyer une erreur HTTP 404. Si l'en-tête X-Privet-Token est manquant, l'appareil DOIT renvoyer une erreur HTTP 400.

4.6. Erreurs

Les erreurs sont renvoyées par les API ci-dessus au format suivant :
Nom de la valeurType de valeurDescription
erreurchaîneType d'erreur (défini par API)
descriptionchaîne (facultatif)Description de l'erreur compréhensible par l'utilisateur.
server_apichaîne (facultatif)En cas d'erreur de serveur, ce champ contient l'API du serveur qui a échoué.
server_codeint (facultatif)En cas d'erreur de serveur, ce champ contient le code d'erreur renvoyé par le serveur.
server_http_codeint (facultatif)En cas d'erreur HTTP du serveur, ce champ contient le code d'erreur HTTP renvoyé par le serveur.
délai avant expirationint (facultatif)Nombre de secondes pendant lesquelles le client doit attendre avant de réessayer (pour les erreurs récupérables uniquement). Le client DOIT randomiser le délai avant expiration réel à partir de cette valeur jusqu'à une valeur supérieure de 20 %.

Toutes les API DOIVENT renvoyer une erreur HTTP 400 si l'en-tête X-Privet-Token est manquant.

HTTP/1.1 400 Missing X-Privet-Token header. (En-tête X-Privet-Token manquant)

Exemple 1 :

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

Exemple 2 :

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

5. API Printer

L'un des types d'appareils compatibles avec ce protocole est le type d'imprimante. Les appareils compatibles avec ce type PEUVENT implémenter certaines fonctionnalités spécifiques aux imprimantes. Idéalement, l'impression sur des imprimantes connectées à Internet passe par un serveur Cloud Print :

Dans certains cas, un client peut avoir besoin d'envoyer un document localement. Il peut être nécessaire lorsque le client ne dispose pas d'un identifiant Google ou ne peut pas communiquer avec le serveur Cloud Print. Dans ce cas, la tâche d'impression sera envoyée localement à l'imprimante. L'imprimante utilisera ensuite le service Cloud Print pour la mise en file d'attente et la conversion des tâches. L'imprimante renverra la tâche soumise localement au service Cloud Print, puis la demandera, car elle a été soumise via le cloud. Ce processus offre une expérience utilisateur flexible en termes de gestion et de suivi des services (conversions) et des tâches d'impression.

Étant donné que le service Cloud Print implémente la conversion, l'imprimante DOIT indiquer qu'elle accepte tous les formats d'entrée ("*/*") dans la liste des types de contenu acceptés :

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

Dans certains cas, une solution entièrement hors connexion est souhaitée. Les imprimantes étant compatibles avec un nombre limité de formats d'entrée, un client devra convertir les documents dans quelques formats d'imprimante compatibles en mode natif.

Cette spécification EXIGE que toutes les imprimantes soient compatibles au moins avec le format PWG Raster ("image/pwg-raster") pour l'impression hors connexion. Une imprimante peut accepter d'autres formats (JPEG, par exemple). Si un client les accepte, il peut envoyer des documents dans ce format. L'imprimante DOIT exposer les types compatibles via l'API /capabilities, par exemple :

{
        "version": "1.0",
        "printer": {
                "supported_content_type": [
                        { "content_type": "image/pwg-raster" },
                        { "content_type": "image/jpeg" }
                ]
        }
}
Un client peut lancer une impression sur le réseau local de deux manières.

Impression simple : le client envoie le document sur le réseau local à l'API /submitdoc (sans spécifier le paramètre job_id). Le document envoyé sera imprimé à l'aide des paramètres par défaut du bon d'impression. Aucun état de tâche d'impression n'est requis. Si l'imprimante N'EST COMPATIBLE QU'AVEC CE TYPE d'impression, elle DOIT annoncer UNIQUEMENT l'API /submitdoc dans la réponse de l'API /privet/info.

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

Impression avancée : le client doit d'abord créer un travail d'impression sur l'imprimante en appelant l'API /privet/printer/createjob avec un ticket de travail CJT valide dans la requête. L'imprimante DOIT stocker le ticket d'impression en mémoire et renvoyer un job_id au client. Le client appellera ensuite l'API /printer/submitdoc et spécifiera l'job_id reçu précédemment. À ce moment-là, l'imprimante commencera à imprimer. Le client interroge l'imprimante pour connaître l'état de la tâche d'impression en appelant l'API /privet/printer/jobstate.

Dans un environnement multiclients, il n'est pas garanti que cette API soit appelée. Il est possible qu'un client appelle /createjob entre les appels /createjob->/submitdoc d'un autre client. Pour éliminer les éventuels blocages et améliorer la facilité d'utilisation, nous vous recommandons de disposer d'une petite file d'attente de tâches d'impression en attente sur l'imprimante (au moins 3 à 5) :

  • /createjob prend la première place disponible dans la file d'attente.
  • La durée de vie d'un job (dans la file d'attente) est d'au moins cinq minutes.
  • Si tous les emplacements de la file d'attente sont occupés, la tâche d'impression la plus ancienne sera supprimée et une nouvelle tâche sera placée à sa place.
  • Si une tâche d'impression est en cours sur l'appareil (impression simple ou avancée), /submitdoc doit renvoyer l'état "occupé" et proposer un délai avant de réessayer cette tâche d'impression.
  • Si /submitdoc fait référence à un job qui a été supprimé de la file d'attente (en raison d'un remplacement ou d'un délai d'expiration), l'imprimante doit renvoyer une erreur invalid_print_job et le client relancera le processus à partir de l'étape /createjob. Le client DOIT attendre une période d'expiration aléatoire pouvant aller jusqu'à cinq secondes avant de réessayer.

Si des contraintes de mémoire empêchent le stockage de plusieurs jobs en attente sur l'appareil, il est possible d'avoir une file d'attente d'un seul job d'impression. Il doit toujours suivre le même protocole que ci-dessus. Une fois qu'un job est terminé ou a échoué avec une erreur, l'imprimante doit stocker des informations sur l'état du job pendant au moins cinq minutes. La taille de la file d'attente pour stocker les états des tâches terminées doit être d'au moins 10. Si d'autres états de job doivent être stockés, le plus ancien peut être supprimé de la file d'attente avant le délai d'expiration de cinq minutes.

Remarque : Pour l'instant, les clients interrogeront l'état du job. À l'avenir, nous pourrions exiger que l'imprimante envoie une notification TXT DNS lorsque l'état d'une tâche d'impression QUELCONQUE a changé.

5.1. API /privet/printer/createjob

L'API /privet/printer/createjob est FACULTATIVE (voir Impression simple ci-dessus). Il s'agit d'une requête HTTP POST. L'API /privet/printer/createjob DOIT vérifier la présence d'un en-tête "X-Privet-Token" valide. L'appareil DOIT implémenter cette API sur l'URL "/privet/printer/createjob" :

POST /privet/printer/createjob HTTP/1.1
Lors de la réception de l'appel d'API /privet/printer/createjob, l'imprimante DOIT créer un ID de tâche d'impression, stocker le ticket d'impression reçu au format CJT et renvoyer l'ID de tâche d'impression au client.

5.1.1. Entrée

L'API /privet/printer/createjob ne comporte aucun paramètre d'entrée dans l'URL. Le corps de la requête doit contenir les données du ticket de tâche d'impression au format CJT.

5.1.2. Renvois

L'API /privet/printer/createjob renvoie les données suivantes :
Nom de la valeurType de valeurDescription
job_idchaîneID de la tâche d'impression nouvellement créée.
expires_inintNombre de secondes pendant lesquelles ce travail d'impression est valide.

Exemple :

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

5.1.3. Erreurs

L'API /privet/printer/createjob peut renvoyer les erreurs suivantes (pour en savoir plus, consultez la section "Erreurs") :
ErreurDescription
invalid_ticketLe bon de commande d'impression envoyé n'est pas valide.
printer_busyL'imprimante est occupée et ne peut pas traiter /créer de tâche pour le moment. Réessayez après le délai d'expiration.
printer_errorL'imprimante est en état d'erreur et l'utilisateur doit intervenir pour résoudre le problème. La description doit contenir une explication plus détaillée (par exemple, "Bourrage papier dans le bac 1").
invalid_x_privet_tokenLe jeton X-Privet-Token n'est pas valide ou est vide dans la requête.

Si l'appareil n'expose pas /privet/printer/createjob, il DOIT renvoyer une erreur HTTP 404. Si l'en-tête X-Privet-Token est manquant, l'appareil DOIT renvoyer une erreur HTTP 400.

5.2. API /privet/printer/submitdoc

L'API /privet/printer/submitdoc est OBLIGATOIRE pour implémenter l'impression sur un réseau local (hors connexion ou renvoi vers Cloud Print). Il s'agit d'une requête HTTP POST. L'API /privet/printer/submitdoc DOIT vérifier la présence d'un en-tête "X-Privet-Token" valide. L'appareil DOIT implémenter cette API sur l'URL "/privet/printer/submitdoc" :
POST /privet/printer/submitdoc HTTP/1.1
Lorsque l'imprimante reçoit l'appel d'API /privet/printer/submitdoc, elle doit commencer à imprimer. S'il ne peut pas commencer l'impression, il DOIT renvoyer l'erreur printer_busy et une période d'attente recommandée pour que le client attende avant de réessayer.

Si l'imprimante n'est pas en mesure de conserver toutes les données dans sa mémoire tampon interne, elle DOIT utiliser les mécanismes TCP pour ralentir le transfert de données jusqu'à ce qu'elle imprime une partie du document, ce qui rend à nouveau une partie de la mémoire tampon disponible. (Par exemple, l'imprimante peut définir windowsize=0 sur les couches TCP, ce qui fera attendre le client.)

L'envoi d'un document à l'imprimante peut prendre beaucoup de temps. Le client doit pouvoir vérifier l'état de l'imprimante et de la tâche (impression avancée) pendant l'impression. Pour ce faire, l'imprimante DOIT permettre au client d'appeler les API /privet/info et /privet/printer/jobstate lors du traitement des appels d'API /privet/printer/submitdoc. Il est recommandé à tous les clients de démarrer un nouveau thread pour exécuter l'appel d'API /privet/printer/submitdoc, afin que le thread principal puisse utiliser les API /privet/info et /privet/printer/jobstate pour vérifier l'état de l'imprimante et des tâches.

Remarque : Une fois la tâche d'impression locale terminée ou annulée, il est fortement recommandé (et cela sera obligatoire dans une future version de cette spécification) de signaler l'état final de la tâche à l'interface /cloudprint/submit à des fins de comptabilité et d'expérience utilisateur. Les paramètres "printerid", "title", "contentType" et "final_semantic_state" (au format PrintJobState) sont obligatoires, ainsi que les paramètres "tag" (paramètre répété) et "ticket" (ticket du job au format CloudJobTicket). Notez que l'état PrintJobState fourni doit être final, c'est-à-dire que son type doit être DONE ou ABORTED, et qu'une cause doit être fournie dans le cas où il est ABORTED (voir JobState pour plus de détails). Notez également que cette utilisation de l'interface /cloudprint/submit pour signaler les tâches d'impression locales n'est pas mentionnée dans sa spécification, car cette section est destinée à décrire l'utilisation principale de l'interface : l'envoi d'une tâche d'impression avec le document à imprimer fourni dans le paramètre "content".

5.2.1. Entrée

L'API /privet/printer/submitdoc comporte les paramètres d'entrée suivants :
NomValeur
job_id(facultatif) ID de la tâche d'impression. Peut être omis pour une impression simple (voir ci-dessus). Doit correspondre à celui renvoyé par l'imprimante.
user_name(Facultatif) Nom d'utilisateur lisible. Cette liste n'est pas définitive et ne doit être utilisée que pour les annotations de tâches d'impression. Si le job est republié sur le service Cloud Print, cette chaîne doit être associée au job Cloud Print.
client_name(facultatif) Nom de l'application cliente à l'origine de cette requête. À des fins d'affichage uniquement. Si le job est republié sur le service Cloud Print, cette chaîne doit être associée au job Cloud Print.
job_name(Facultatif) Nom de la tâche d'impression à enregistrer. Si le job est republié sur le service Cloud Print, cette chaîne doit être associée au job Cloud Print.
Hors connexion(facultatif) Ne peut être que "offline=1". Dans ce cas, l'imprimante ne doit essayer d'imprimer qu'hors connexion (sans renvoyer la tâche au serveur Cloud Print).

Le corps de la requête doit contenir un document valide à imprimer. "Content-Length" doit inclure la longueur correcte de la requête. L'en-tête "Content-Type" doit être défini sur le type MIME du document et correspondre à l'un des types du CDD (sauf si le CDD spécifie "*/*").

Il est FORTEMENT recommandé aux clients de fournir un nom d'utilisateur (ou une adresse e-mail) valide, un nom de client et un nom de tâche avec cette demande. Ces champs ne sont utilisés que dans les UI pour améliorer l'expérience utilisateur.

5.2.2. Renvois

L'API /privet/printer/submitdoc renvoie les données suivantes :
Nom de la valeurType de valeurDescription
job_idchaîneID de la tâche d'impression nouvellement créée (impression simple) ou job_id spécifié dans la requête (impression avancée).
expires_inintNombre de secondes pendant lesquelles ce travail d'impression est valide.
job_typechaîneType de contenu du document envoyé.
job_sizeint 64 bitsTaille des données d'impression en octets.
job_namechaîne(facultatif) Nom de la tâche identique à celui de l'entrée (le cas échéant).

Exemple :

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

5.2.3. Erreurs

L'API /privet/printer/submitdoc peut renvoyer les erreurs suivantes (pour en savoir plus, consultez la section "Erreurs") :
ErreurDescription
invalid_print_jobUn ID de tâche non valide ou expiré est spécifié dans la requête. Réessayez après le délai d'expiration.
invalid_document_typeL'imprimante n'est pas compatible avec le type MIME du document.
invalid_documentLe document envoyé n'est pas valide.
document_too_largeLe document dépasse la taille maximale autorisée.
printer_busyL'imprimante est occupée et ne peut pas traiter le document pour le moment. Réessayez après le délai d'expiration.
printer_errorL'imprimante est en état d'erreur et l'utilisateur doit intervenir pour résoudre le problème. La description doit contenir une explication plus détaillée (par exemple, "Bourrage papier dans le bac 1").
invalid_paramsParamètres non valides spécifiés dans la requête. (Les paramètres inconnus doivent être ignorés pour la compatibilité future)
user_cancelL'utilisateur a explicitement annulé le processus d'impression depuis l'appareil.
server_errorÉchec de l'envoi du document à Cloud Print.
invalid_x_privet_tokenLe jeton X-Privet-Token n'est pas valide ou est vide dans la requête.

Si l'appareil n'expose pas /privet/printer/submitdoc, il DOIT renvoyer une erreur HTTP 404. Si l'en-tête X-Privet-Token est manquant, l'appareil DOIT renvoyer une erreur HTTP 400.

Remarque : L'API /privet/printer/submitdoc peut nécessiter un traitement spécial côté imprimante (en raison de la grande taille de la charge utile associée). Dans certains cas (selon l'implémentation et la plate-forme du serveur HTTP de l'imprimante), l'imprimante peut fermer le socket AVANT de renvoyer une erreur HTTP. Dans d'autres cas, l'imprimante peut renvoyer une erreur 503 (au lieu d'une erreur Privet). Les imprimantes DOIVENT essayer autant que possible de renvoyer Privet. Toutefois, chaque client implémentant la spécification Privet DOIT être en mesure de gérer les cas de fermeture de socket (sans erreur HTTP) et d'erreur HTTP 503 pour l'API /privet/printer/submitdoc. Dans ce cas, le client DOIT le gérer comme une erreur Privet "printer_busy" avec "timeout" défini sur 15 secondes. Pour éviter les nouvelles tentatives infinies, le client peut arrêter de réessayer après un nombre raisonnable de tentatives (par exemple, 3).

5.3. API /privet/printer/jobstate

L'API /privet/printer/jobstate est FACULTATIVE (voir Impression simple ci-dessus). Il s'agit d'une requête HTTP GET. L'API /privet/printer/jobstate DOIT vérifier la validité de l'en-tête "X-Privet-Token". L'appareil DOIT implémenter cette API sur l'URL "/privet/printer/jobstate" :
GET /privet/printer/jobstate HTTP/1.1
Lorsqu'une imprimante reçoit un appel d'API /privet/printer/jobstate, elle doit renvoyer l'état de la tâche d'impression demandée ou une erreur invalid_print_job.

5.3.1. Entrée

L'API /privet/printer/jobstate comporte les paramètres d'entrée suivants :
NomValeur
job_idID de la tâche d'impression pour laquelle renvoyer l'état.

5.3.2. Renvois

L'API /privet/printer/jobstate renvoie les données suivantes :
Nom de la valeurType de valeurDescription
job_idchaîneID de la tâche d'impression pour laquelle les informations sur l'état sont fournies.
statechaînedraft : le job d'impression a été créé sur l'appareil (aucun appel /privet/printer/submitdoc n'a encore été reçu).
En file d'attente : la tâche d'impression a été reçue et mise en file d'attente, mais l'impression n'a pas encore commencé.
in_progress : la tâche d'impression est en cours.
stopped : le travail d'impression a été mis en pause, mais peut être redémarré manuellement ou automatiquement.
done : la tâche d'impression est terminée.
abandonnée : la tâche d'impression a échoué.
descriptionchaîne(facultatif) Description lisible de l'état de la tâche d'impression. Doit inclure des informations supplémentaires si state< est défini sur stopped ou aborted. Le champ semantic_state fournit généralement une description plus pertinente et plus utile au client.
expires_inintNombre de secondes pendant lesquelles ce travail d'impression est valide.
job_typechaîne(facultatif) Type de contenu du document envoyé.
job_sizeint 64 bits(facultatif) Taille des données d'impression en octets.
job_namechaîne(facultatif) Nom de la tâche identique à celui de l'entrée (le cas échéant).
server_job_idchaîne(facultatif) ID du job renvoyé par le serveur (si le job a été envoyé au service Cloud Print). Omission pour l'impression hors connexion.
semantic_stateJSON(Facultatif) État sémantique du job au format PrintJobState.

Exemple (impression par le biais de 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"
}

Exemple (erreur d'impression hors connexion) :

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

Exemple (tâche d'impression abandonnée par l'utilisateur) :

{
        "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
        }
}

Exemple : la tâche d'impression a été arrêtée, car il n'y avait plus de papier. Notez la référence à l'état de l'appareil. Le client devra appeler l'API /privet/info pour obtenir plus d'informations sur l'état de l'appareil :

{
        "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. Erreurs

L'API /privet/printer/jobstate peut renvoyer les erreurs suivantes (pour en savoir plus, consultez la section "Erreurs") :
ErreurDescription
invalid_print_jobUn ID de tâche non valide ou expiré est spécifié dans la requête.
server_errorÉchec de l'obtention de l'état de la tâche d'impression (pour les tâches d'impression envoyées à Cloud Print).
invalid_x_privet_tokenLe jeton X-Privet-Token n'est pas valide ou est vide dans la requête.

Si l'appareil n'expose pas /privet/printer/jobstate, il DOIT renvoyer une erreur HTTP 404. Si l'en-tête X-Privet-Token est manquant, l'appareil DOIT renvoyer une erreur HTTP 400.

6. Annexe

6.1. Comportement et paramètres par défaut

Cette section explique le comportement par défaut attendu de TOUS les appareils compatibles avec Privet.
  • Les appareils prêts à l'emploi ne doivent accepter que les API /privet/info et /privet/register. Toutes les autres API (par exemple, /privet/accesstoken, impression locale) doivent être désactivées.
  • L'enregistrement nécessite une interaction physique avec un appareil.
    • L'utilisateur DOIT effectuer une action physique sur l'appareil (par exemple, appuyer sur un bouton) pour confirmer son accès à l'appareil.
    • Une fois que l'utilisateur a effectué l'action mentionnée ci-dessus, l'imprimante doit envoyer la requête /cloudprint/register. Il ne doit pas envoyer cette demande avant que l'action soit effectuée (voir le diagramme de séquence 1).
    • Si l'appareil traite une requête /privet/register (par exemple, s'il attend l'action ci-dessus), il doit rejeter toutes les autres requêtes /privet/register. Dans ce cas, l'appareil DOIT renvoyer l'erreur device_busy.
    • L'appareil doit faire expirer toute requête /register qui ne reçoit pas l'action physique mentionnée ci-dessus dans les 60 secondes. Dans ce cas, l'appareil DOIT renvoyer l'erreur confirmation_timeout.
    • Facultatif : les éléments suivants sont recommandés, mais pas obligatoires. Ils peuvent améliorer l'expérience utilisateur :
      • L'imprimante peut faire clignoter un voyant ou afficher un message à l'écran pour indiquer à l'utilisateur qu'il doit effectuer une action pour confirmer l'enregistrement.
      • L'imprimante peut afficher sur son écran le message "L'imprimante est en cours d'enregistrement dans Google Cloud Print pour l'utilisateur abc@def.com. Appuyez sur OK pour continuer", où abc@def.com est le paramètre utilisateur de l'appel d'API /register. L'utilisateur comprendra alors plus clairement :
        • il s'agit de leur demande d'inscription qu'ils confirment.
        • ce qui se passe si elle n'est pas à l'origine de la demande.
      • En plus d'une action physique de confirmation depuis l'imprimante (par exemple, "Appuyez sur le bouton OK"), une imprimante peut également proposer à l'utilisateur un bouton pour annuler la demande (par exemple, (appuyez sur "Annuler" pour refuser). Cela permettrait aux utilisateurs qui n'ont pas déclenché la demande d'enregistrement de l'annuler avant le délai de 60 secondes. Dans ce cas, l'appareil DOIT renvoyer l'erreur user_cancel.
  • Transferts de propriété :
    • L'appareil peut être supprimé explicitement du service cloud.
      • Si l'appareil reçoit une réponse positive, mais aucune description d'appareil à la suite de l'appel /cloudprint/printer (pour GCP), il DOIT revenir au mode par défaut (tel qu'il est fourni).
      • Si les identifiants de l'appareil ne fonctionnent plus (explicitement en raison d'une réponse "identifiants non valides" du serveur), il DOIT revenir au mode par défaut (prêt à l'emploi).
    • Le rétablissement de la configuration d'usine local DOIT effacer les identifiants de l'appareil et le définir sur l'état par défaut.
    • Facultatif : L'appareil peut fournir un élément de menu permettant d'effacer les identifiants et de le mettre en mode par défaut.
  • Les appareils compatibles avec les notifications XMPP DOIVENT pouvoir envoyer un ping au serveur. Le délai avant expiration du ping DOIT être contrôlable depuis le serveur via "local_settings".
  • Pour s'assurer qu'ils sont synchronisés, les appareils peuvent envoyer un ping explicite au serveur (API /cloudprint/printer pour GCP, en plus des pings XMPP) au maximum une fois par jour (24 heures). Il est recommandé d'aléatoriser la fenêtre de vérification dans une fenêtre de 24 à 32 heures.
  • Facultatif : Pour les appareils Cloud Print, il est recommandé, mais pas obligatoire, de prévoir un moyen manuel (bouton) permettant à l'utilisateur de lancer une recherche de nouveaux travaux d'impression depuis l'appareil. Certaines imprimantes en sont déjà équipées.
  • Facultatif. Il est possible que les imprimantes d'entreprise permettent de désactiver complètement la découverte locale. Dans ce cas, l'appareil DOIT mettre à jour ces paramètres locaux sur le serveur. Les nouveaux paramètres locaux DOIVENT être vides (si le paramètre "local_discovery" est défini sur "false", cela signifie qu'il peut être réactivé à partir du service GCP).

6.1.2 Diagramme d'enregistrement par défaut

6.2. Attaques XSSI et XSRF, et prévention

Cette section explique la possibilité d'attaques XSSI et XSRF sur l'appareil, et comment s'en protéger (y compris les techniques de génération de jetons).
Pour en savoir plus, consultez : http://googleonlinesecurity.blogspot.com/2011/05/website-security-for-webmasters.html
En règle générale, les attaques XSSI et XSRF sont possibles lorsqu'un site utilise des mécanismes d'authentification par cookie. Bien que Google n'utilise pas de cookies avec son service Cloud Print, de telles attaques sont toujours possibles. Par conception, l'accès au réseau local fait implicitement confiance aux requêtes.

6.2.1. XSSI

Il est possible qu'un site Web malveillant devine l'adresse IP et le numéro de port d'un appareil compatible avec Privet, et qu'il tente d'appeler l'API Privet à l'aide de "src=<nom de l'API>" dans une balise <script> :
<script type="text/javascript" src="http://192.168.1.42:8080/privet/info"></script>
Sans protection, les sites Web malveillants pourraient exécuter des appels d'API et accéder aux résultats.
 Pour éviter ce type d'attaque, TOUS les appels d'API Privet DOIVENT exiger l'en-tête "X-Privet-Token" dans la requête. Les balises de script "src=<api>" ne peuvent pas ajouter d'en-têtes, ce qui protège efficacement contre ce type d'attaque.

6.2.2. XSRF

http://en.wikipedia.org/wiki/Cross-site_request_forgery
Il est possible qu'un site Web malveillant devine l'adresse IP et le numéro de port d'un appareil compatible avec Privet, et tente d'appeler l'API Privet à l'aide d'un <iframe>, de formulaires ou d'un autre mécanisme de chargement intersites. Les pirates informatiques ne pourraient pas accéder aux résultats de la requête, mais ils pourraient la déclencher si elle devait effectuer une action (par exemple, une impression).

Pour éviter cette attaque, nous exigeons la protection suivante :

  • Laisser l'API /privet/info ouverte à la XSRF
  • L'API /privet/info NE DOIT PAS effectuer d'actions sur l'appareil.
  • Utiliser l'API /privet/info pour recevoir x-privet-token
  • Toutes les autres API DOIVENT vérifier la présence d'un jeton x-privet-token valide dans l'en-tête "X-Privet-Token".
  • x-privet-token DOIT être valide pendant 24 heures uniquement.

Même si un pirate informatique parvient à exécuter l'API /privet/info, il ne pourra pas lire le jeton x-privet à partir de la réponse et ne pourra donc pas appeler d'autre API.

Nous vous recommandons vivement de générer le jeton XSRF à l'aide de l'algorithme suivant :

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

Éléments de génération du jeton XSRF :

  • DELIMITER est un caractère spécial, généralement ":".
  • issue_timecounter correspond au nombre de secondes écoulées depuis un événement (époque pour le code temporel) ou depuis le démarrage de l'appareil (pour les compteurs de processeur). issue_timecounter augmente constamment lorsque l'appareil est en marche (voir la validation du jeton ci-dessous).
  • SHA1 : fonction de hachage utilisant l'algorithme SHA1
  • base64 : encodage base64
  • device_secret : code secret spécifique à l'appareil. Le code secret de l'appareil DOIT être mis à jour à chaque redémarrage.

Voici les méthodes recommandées pour générer un secret d'appareil :

  • Générer un nouvel UUID à chaque redémarrage
  • Générer un nombre aléatoire de 64 bits à chaque redémarrage

L'appareil n'est pas tenu de stocker tous les jetons XSRF qu'il a émis. Lorsque l'appareil doit valider un jeton XSRF, il doit le décoder en base64. Récupérez issue_timecounter dans la seconde moitié (texte brut), puis essayez de générer le hachage SHA1 de device_secret + DELIMITER + issue_timecounter, où issue_timecounter provient du jeton. Si le SHA1 nouvellement généré correspond à celui du jeton, l'appareil doit maintenant vérifier si issue_timecounter se trouve dans la période de validité (24 heures) du compteur de temps actuel. Pour ce faire, l'appareil prend le compteur de temps actuel (compteur CPU, par exemple) et en soustrait issue_timecounter. Le résultat DOIT correspondre au nombre de secondes écoulées depuis l'émission du jeton.

Important : Il s'agit de la méthode recommandée pour implémenter la protection XSRF. Les clients de la spécification Privet ne doivent pas essayer de comprendre le jeton XSRF, mais le traiter comme une boîte noire. La figure 6.2.3 illustre une méthode recommandée pour implémenter le jeton X-Privet-Token et la validation d'une requête typique.

6.2.3 Schéma de séquence de génération et de validation du jeton X-Privet

6.3. Diagrammes de workflow

Cette section illustre un workflow dans différents cas.

6.3.1. Workflow de l'imprimante prête à l'emploi

6.3.2. Démarrage de l'imprimante enregistrée

6.3.3 Workflow de gestion des notifications XMPP

6.3.4. Vérifier les paramètres de l'imprimante