Privet

Privet é uma API de descoberta local de dispositivos na nuvem usada por serviços de nuvem. Este documento é organizado nas seguintes seções:

  1. Introdução: introdução ao Privet
  2. Discovery: mecanismos de descoberta local
  3. Avisos: avisos de descoberta local
  4. API: APIs Privet para dispositivos gerais na nuvem
  5. API Printer: APIs Privet usadas por impressoras.
  6. Apêndice: diagramas complementares

1. Introdução

Os dispositivos conectados à nuvem têm muitos benefícios. Eles podem usar serviços de conversão on-line, hospedar filas de trabalhos enquanto o dispositivo está off-line e ser acessados de qualquer lugar do mundo. No entanto, com muitos dispositivos de nuvem acessíveis por um determinado usuário, precisamos fornecer um método para encontrar o dispositivo mais próximo com base na localização. O objetivo do protocolo Privet é unir a flexibilidade dos dispositivos de nuvem com um mecanismo de descoberta local adequado para que os dispositivos sejam facilmente descobertos em novos ambientes.

As metas deste protocolo são:
  • tornar os dispositivos na nuvem detectáveis localmente
  • registrar dispositivos na nuvem com um serviço na nuvem
  • associar dispositivos registrados à representação deles na nuvem;
  • ativar a funcionalidade off-line.
  • simplificar a implementação para que dispositivos pequenos possam usá-lo

O protocolo Privet consiste em duas partes principais: descoberta e API. A descoberta é usada para encontrar o dispositivo na rede local, e a API é usada para receber informações sobre o dispositivo e realizar algumas ações. Neste documento, o dispositivo se refere a um dispositivo conectado à nuvem que implementa o protocolo Privet.

2. Discovery

A descoberta é um protocolo baseado em zeroconf (mDNS + DNS-SD). O dispositivo PRECISA implementar o endereçamento link-local IPv4. O dispositivo PRECISA estar em conformidade com as especificações mDNS e DNS-SD.

O dispositivo PRECISA realizar a resolução de conflitos de nomes de acordo com as especificações acima.

2.1. Tipo de serviço

A descoberta de serviços DNS usa o seguinte formato para tipos de serviço: _applicationprotocol._transportprotocol. No caso do protocolo Privet, o tipo de serviço para DNS-SD deve ser: _privet._tcp

O dispositivo também pode implementar outros tipos de serviço. Recomendamos usar o mesmo nome de instância de serviço para todos os tipos de serviço implementados pelo dispositivo. Por exemplo, uma impressora pode implementar os serviços "Printer XYZ._privet._tcp" e "Printer XYZ._printer._tcp". Isso vai simplificar a configuração para o usuário. No entanto, os clientes Privet procuram apenas por "_privet._tcp".

Além do tipo de serviço principal, o dispositivo PRECISA anunciar os registros PTR para os subtipos correspondentes (consulte a especificação DNS-SD: "7.1. Enumeração seletiva de instâncias (subtipos)"). O formato precisa ser: _<subtype>._sub._privet._tcp

No momento, o único subtipo de dispositivo compatível é printer. Portanto, todas as impressoras PRECISAM anunciar dois registros PTR:

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

2.2. Registro TXT

A descoberta de serviços DNS define campos para adicionar informações opcionais sobre um serviço nos registros TXT. Um registro TXT consiste em pares de chave/valor. Cada par chave/valor começa com o byte de comprimento, seguido por até 255 bytes de texto. A chave é o texto antes do primeiro caractere "=", e o valor é o texto após o primeiro caractere "=" até o final. A especificação permite que não haja valor no registro. Nesse caso, não haverá o caractere "=" OU não haverá texto após o caractere "=". Consulte a especificação DNS-SD: "6.1. Regras gerais de formato para registros TXT do DNS" para o formato de registro TXT do DNS e "6.2. Tamanho do registro TXT DNS-SD" para o comprimento recomendado).

O Privet exige que o dispositivo envie os seguintes pares de chave-valor no registro TXT. As strings de chave/valor não diferenciam maiúsculas de minúsculas. Por exemplo, "CS=online" e "cs=ONLINE" são iguais. As informações no registro TXT precisam ser as mesmas acessíveis pela API /info (consulte 4.1. seção "API").

Recomendamos manter o tamanho do registro TXT abaixo de 512 bytes.

2.2.1. txtvers

Versão da estrutura TXT. txtvers PRECISA ser o primeiro registro da estrutura TXT. No momento, a única versão compatível é a 1.

txtvers=1

2.2.2. ty

Fornece um nome legível para o usuário do dispositivo. Exemplo:

ty=Google Cloud Ready Printer Model XYZ

2.2.3. note (opcional)

Fornece um nome legível para o usuário do dispositivo. Exemplo:

note=1st floor lobby printer

Observação:essa é uma chave opcional e pode ser ignorada. No entanto, se presente, o usuário DEVE poder modificar esse valor. A mesma descrição PRECISA ser usada ao registrar o dispositivo.

2.2.4. url

URL do servidor a que este dispositivo está conectado (incluindo o protocolo). Exemplo:

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

2.2.5. type

Lista separada por vírgulas de subtipos de dispositivos compatíveis com este dispositivo. O formato é: "type=_subtype1,_subtype2". No momento, o único subtipo de dispositivo compatível é printer.

type=printer

Cada subtipo listado precisa ser anunciado usando um registro PTR correspondente. Para cada subtipo de serviço compatível, deve haver um item correspondente. O nome do subtipo de serviço (<subtype>._sub._privet._tcp) precisa ser igual ao tipo de dispositivo aqui.

2.2.6. id

ID do dispositivo. Se o dispositivo ainda não tiver sido registrado, essa chave vai estar presente, mas o valor vai estar vazio. Exemplo:

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

2.2.7. cs

Indica o estado atual da conexão do dispositivo. Quatro valores possíveis são definidos nesta especificação.

  • "online" indica que o dispositivo está conectado à nuvem.
  • "offline" indica que o dispositivo está disponível na rede local, mas não consegue se comunicar com o servidor.
  • "conectando" indica que o dispositivo está executando a sequência de inicialização e ainda não está totalmente on-line.
  • "not-configured" indica que o acesso à Internet do dispositivo ainda não foi configurado. Esse valor não é usado no momento, mas pode ser útil em versões futuras da especificação.
Por exemplo:
  • cs=online
  • cs=offline
  • cs=connecting

Se o dispositivo tiver sido registrado em uma nuvem, na inicialização, ele vai verificar a conectividade com um servidor para detectar o estado da conexão (por exemplo, chamando a API de nuvem para receber as configurações do dispositivo). O dispositivo pode usar o estado da conexão do canal de notificações (por exemplo, XMPP) para informar esse valor. Dispositivos não registrados na inicialização podem fazer ping em um domínio para detectar o estado da conexão. Por exemplo, faça ping em www.google.com para dispositivos de impressão na nuvem.

3. Anúncios

Na inicialização, no desligamento ou na mudança de estado do dispositivo, ele PRECISA executar a etapa de anúncio, conforme descrito na especificação mDNS. Ele DEVE enviar o anúncio correspondente pelo menos duas vezes com um intervalo de pelo menos um segundo entre eles.

3.1. Inicialização

Na inicialização do dispositivo, ele PRECISA realizar as etapas de sondagem e anúncio, conforme descrito na especificação mDNS. Nesse caso, os registros SRV, PTR e TXT precisam ser enviados. Recomendamos agrupar todos os registros em uma resposta de DNS, se possível. Caso contrário, a ordem recomendada é: SRV, PTR e TXT.

3.2. Encerrar

Ao desligar o dispositivo, ele DEVE tentar notificar todas as partes interessadas enviando um "pacote de despedida" com TTL=0 (conforme descrito na documentação do mDNS).

3.3. Atualizar

Se alguma informação descrita no TXT mudar, o dispositivo PRECISA enviar um anúncio de atualização. Basta enviar apenas o novo registro TXT nesse caso. Por exemplo, depois que um dispositivo é registrado, ele PRECISA enviar um anúncio de atualização incluindo o novo ID do dispositivo.

4. API

Depois que um dispositivo de nuvem é descoberto, a comunicação do cliente é ativada diretamente com ele pela rede local. Todas as APIs são baseadas em HTTP 1.1. Os formatos de dados são baseados em JSON. As solicitações de API podem ser GET ou POST.

Cada solicitação PRECISA conter um cabeçalho "X-Privet-Token" válido. A ÚNICA solicitação permitida a ter um cabeçalho "X-Privet-Token" vazio é a solicitação /privet/info. Observe que o cabeçalho AINDA precisa estar presente. Se o cabeçalho "X-Privet-Token" estiver faltando, o dispositivo PRECISA responder com o seguinte erro HTTP 400:

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

Se o cabeçalho "X-Privet-Token" estiver vazio ou inválido, o dispositivo PRECISA responder com "invalid X-Privet-Token error" (invalid_x_privet_token, consulte a seção "Erros" para detalhes). A única exceção é a API /info. Para mais informações sobre por que isso é feito e como os tokens devem ser gerados, consulte o Apêndice A: ataques e prevenção de XSSI e XSRF.

Se uma API solicitada não existir ou não for compatível, o dispositivo precisará retornar um erro HTTP 404.

4.1. de disponibilidade da API

Antes de qualquer API ser exposta (incluindo a API /info), o dispositivo PRECISA entrar em contato com o servidor para verificar as configurações locais. As configurações locais PRECISAM ser preservadas entre reinicializações. Se o servidor não estiver disponível, as últimas configurações locais conhecidas deverão ser usadas. Se o dispositivo ainda não tiver sido registrado, ele vai seguir as configurações padrão.

Os dispositivos do Cloud Print PRECISAM seguir as etapas abaixo para registrar, receber e atualizar as configurações locais.

4.1.1. Registro

Quando o dispositivo se registra, ele PRECISA especificar o parâmetro "local_settings", da seguinte forma:

{
       "current": {
                "local_discovery": true,
                "access_token_enabled": true,
                "printer/local_printing_enabled": true,
                "printer/conversion_printing_enabled": true,
                "xmpp_timeout_value": 300
        }
}
É possível definir as seguintes configurações:
Nome do valorTipo de valorDescrição
local_discoverybooleanoIndica se a funcionalidade de descoberta local é permitida. Se for "false", todas as APIs locais (incluindo /info) e a descoberta DNS-SD precisam ser desativadas. Por padrão, os dispositivos recém-registrados transmitem "true".
access_token_enabledbooleano (opcional)Indica se a API /accesstoken deve ser exposta na rede local. O padrão é "true".
printer/local_printing_enabledbooleano (opcional)Indica se a funcionalidade de impressão local (/printer/createjob, /printer/submitdoc, /printer/jobstate) deve ser exposta na rede local. O padrão é "true".
printer/conversion_printing_enabledbooleano (opcional)Indica se a impressão local pode enviar o job para o servidor para conversão. Só faz sentido quando a impressão local está ativada.
xmpp_timeout_valueint (opcional)Indica o número de segundos entre os pings do canal XMPP. Por padrão, precisa ser de 300 (5 minutos) ou mais.

Importante:a falta de um valor opcional indica que a funcionalidade correspondente não é compatível com o dispositivo.

4.1.2. Inicialização

Na inicialização do dispositivo, ele precisa entrar em contato com o servidor para verificar quais APIs estão disponíveis para serem expostas na rede local. Para impressoras conectadas ao Cloud Print, chame:

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

/cloudprint/printer é preferível a /cloudprint/list, mas ambos funcionam.

Essa API retorna os parâmetros atuais do dispositivo, incluindo configurações para a API local. A resposta do servidor terá o seguinte formato:

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

O objeto "current" indica as configurações em vigor no momento.

O objeto "pending" indica as configurações que precisam ser aplicadas ao dispositivo. Esse objeto pode estar ausente.

Quando o dispositivo encontrar configurações "pendentes", ele DEVE atualizar o estado (veja abaixo).

4.1.3. Atualizar

Se for necessário atualizar as configurações, uma notificação XMPP será enviada ao dispositivo. A notificação vai estar no seguinte formato:

<device_id>/update_settings

Ao receber essa notificação, o dispositivo PRECISA consultar o servidor para receber as configurações mais recentes. Os dispositivos do Cloud Print PRECISAM usar:

/cloudprint/printer?printerid=<printer_id>

Quando o dispositivo vê a seção "pendente" como resultado da API /cloudprint/printer (na inicialização ou devido à notificação), ele PRECISA atualizar o estado interno para lembrar as novas configurações. Ele PRECISA chamar a API do servidor para confirmar as novas configurações. Para impressoras na nuvem, o dispositivo PRECISA chamar a API /cloudprint/update e usar o parâmetro "local_settings" como durante o registro.

Ao se reconectar ao canal XMPP, o dispositivo PRECISA chamar a API /cloudprint/printer para verificar se as configurações locais foram alteradas desde a última vez.

4.1.3.1. Configurações locais pendentes

O parâmetro "local_settings" que o dispositivo usa para chamar a API do servidor NUNCA pode conter a seção "pending".

4.1.3.2. Local Settings Current

SOMENTE o dispositivo pode mudar a seção "atual" de "local_settings". Todos os outros vão mudar a seção "pendente" e aguardar até que as mudanças sejam propagadas para a seção "atual" pelo dispositivo.

4.1.4. Off-line

Quando não for possível entrar em contato com o servidor durante a inicialização, após a notificação, o dispositivo DEVE usar as últimas configurações locais conhecidas.

4.1.5. Excluir o dispositivo do serviço

Se o dispositivo tiver sido excluído do serviço (GCP, por exemplo), uma notificação XMPP será enviada para ele. A notificação vai estar no seguinte formato:

<device_id>/delete

Ao receber essa notificação, o dispositivo PRECISA acessar o servidor para verificar o estado. Os dispositivos do Cloud Print precisam usar:

/cloudprint/printer?printerid=<printer_id>

O dispositivo PRECISA receber uma resposta HTTP bem-sucedida com success=false e sem descrição do dispositivo/impressora. Isso significa que o dispositivo foi removido do servidor e PRECISA apagar as credenciais e entrar no modo de configurações padrão de fábrica.

SEMPRE que o dispositivo receber uma resposta indicando que ele foi excluído como resultado da API /cloudprint/printer (inicialização, notificação de atualização de configurações, ping diário), ele DEVERÁ excluir as credenciais e entrar no modo padrão.

4.2. API /privet/info

A API de informações é OBRIGATÓRIA e precisa ser implementada por todos os dispositivos. É uma solicitação HTTP GET para o URL "/privet/info": GET /privet/info HTTP/1.1

A API de informações retorna informações básicas sobre um dispositivo e a funcionalidade que ele oferece suporte. Essa API NÃO PODE mudar o status do dispositivo nem realizar nenhuma ação, já que é vulnerável a ataques XSRF. Essa é a ÚNICA API que pode ter um cabeçalho "X-Privet-Token" vazio. Os clientes precisam chamar a API /privet/info com o cabeçalho "X-Privet-Token" definido como X-Privet-Token: ""

A API de informações PRECISA retornar dados consistentes com os disponíveis no registro TXT durante a descoberta.

4.2.1. Entrada

A API /privet/info não tem parâmetros de entrada.

4.2.2. Retornar

A API /privet/info retorna informações básicas sobre o dispositivo e a funcionalidade compatível.

A coluna TXT indica o campo correspondente no registro TXT do DNS-SD.

Nome do valorTipo de valorDescriçãoTXT
versionstringVersão mais recente (principal.secundária) da API compatível, atualmente 1.0
nomestringNome legível do dispositivo.ty
descriçãostring(opcional) Descrição do dispositivo. PRECISA ser modificável pelo usuário.nota
urlstringURL do servidor com que este dispositivo está se comunicando. O URL PRECISA incluir a especificação do protocolo, por exemplo: https://www.google.com/cloudprint.url
tipolista de stringsLista de tipos de dispositivos compatíveis.tipo
idstringID do dispositivo, vazio se o dispositivo ainda não tiver sido registrado. id
device_statestringEstado do dispositivo.
idle significa que o dispositivo está pronto
processing significa que o dispositivo está ocupado e a funcionalidade pode ser limitada por algum tempo
stopped significa que o dispositivo não está funcionando e é necessária a intervenção do usuário
connection_statestringEstado da conexão com o servidor (base_url)
online: conexão disponível
offline: sem conexão
connecting: realizando etapas de inicialização
not-configured: a conexão ainda não foi configurada
Um dispositivo registrado pode informar o estado da conexão com base no estado do canal de notificação (por exemplo, estado da conexão XMPP).
cs
fabricantestringNome do fabricante do dispositivo
modelostringModelo do dispositivo
serial_numberstringIdentificador exclusivo do dispositivo. Nesta especificação, ele PRECISA ser um UUID. (Especificação do GCP 1.1)
(opcional) Recomendamos usar o mesmo ID de número de série em todos os lugares para que diferentes clientes possam identificar o mesmo dispositivo. Por exemplo, impressoras que implementam IPP podem usar esse ID de número de série no campo "printer-device-id".
firmwarestringVersão do firmware do dispositivo
tempo de atividadeintNúmero de segundos desde a inicialização do dispositivo.
setup_urlstring(opcional) URL (incluindo o protocolo) da página com instruções de configuração
support_urlstring(opcional) URL (incluindo protocolo) da página com suporte, informações de perguntas frequentes
update_urlstring(opcional) URL (incluindo o protocolo) da página com instruções de atualização do firmware
x-privet-tokenstringValor do cabeçalho X-Privet-Token que precisa ser transmitido a todas as APIs para evitar ataques XSSI e XSRF. Consulte 6.1 para mais detalhes.
apidescrição das APIsLista de APIs compatíveis (descritas abaixo)
semantic_stateJSON(Opcional) Estado semântico do dispositivo no formato CloudDeviceState.

api: é uma lista JSON que contém as APIs disponíveis na rede local. Nem todas as APIs podem estar disponíveis ao mesmo tempo na rede local. Por exemplo, um dispositivo conectado recentemente só pode oferecer suporte à API /register:

"api": [
        "/privet/register",
]
Depois que o registro do dispositivo for concluído, ele NÃO DEVE mais oferecer suporte à API /register. O dispositivo também precisa verificar com o serviço quais APIs podem ser expostas na rede local. Exemplo:
"api": [
        "/privet/accesstoken",
        "/privet/capabilities",
        "/privet/printer/submitdoc",
]

As seguintes APIs estão disponíveis no momento:

  • /privet/register: API para registro de dispositivos na rede local. Consulte a API /privet/register para mais detalhes. Essa API PRECISA ser ocultada quando o dispositivo for registrado com êxito na nuvem.
  • /privet/accesstoken: API para solicitar um token de acesso do dispositivo. Consulte a API /privet/accesstoken para mais detalhes.
  • /privet/capabilities: API para recuperar recursos do dispositivo. Consulte a API /privet/capabilities para mais detalhes.
  • /privet/printer/*: API específica para o tipo de dispositivo "impressora". Consulte as APIs específicas da impressora para mais detalhes.
Confira um exemplo da resposta /privet/info. (Observe a falta da API /privet/register, já que este é um dispositivo já registrado):
{
        "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",
        ]
}
Confira um exemplo da resposta /privet/info para uma impressora que ficou sem tinta (campo 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. Erros

A API /privet/info SÓ vai retornar um erro se o cabeçalho X-Privet-Token estiver faltando. Ele PRECISA ser um erro HTTP 400:

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

4.3. API /privet/register

A API /privet/register é OPCIONAL. É uma solicitação HTTP POST. A API /privet/register PRECISA verificar um cabeçalho X-Privet-Token válido. O dispositivo PRECISA implementar essa API no 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

O dispositivo só deve expor a API /privet/register quando permitir o registro anônimo no momento. Exemplo:

  • Quando o dispositivo é ligado (ou depois de clicar em um botão especial nele) e ainda não foi registrado, ele expõe a API /privet/register para permitir que um usuário da rede local reivindique a impressora.
  • Depois que o registro for concluído, o dispositivo vai parar de expor a API /privet/register para evitar que outro usuário na rede local reivindique o dispositivo.
  • Alguns dispositivos podem ter maneiras diferentes de registrar dispositivos e não devem expor a API /privet/register (por exemplo, o conector do Chrome Cloud Print).

O processo de registro consiste em três etapas (consulte o registro anônimo do Cloud Print).

  1. Inicie o processo de registro anônimo.
  2. Um cliente inicia esse processo chamando a API /privet/register. O dispositivo pode aguardar a confirmação do usuário nesse momento.
  3. Recebe um token de reivindicação.

O cliente faz uma pesquisa para descobrir quando o dispositivo está pronto para continuar. Quando o dispositivo está pronto, ele envia uma solicitação ao servidor para recuperar o token e o URL de registro. O token e o URL recebidos DEVEM ser retornados ao cliente. Durante essa etapa, se o dispositivo receber outra chamada para inicializar o registro, ele deverá:

  • Se for o mesmo usuário que iniciou o registro, descarte todos os dados anteriores (se houver) e inicie um novo processo de registro.
  • Se for um usuário diferente, retorne o erro device_busy e um tempo limite de 30 segundos.

Conclua o processo de registro.

Depois que o cliente reivindicar o dispositivo, ele precisará notificar o dispositivo para concluir o registro. Depois que o processo de registro for concluído, o dispositivo vai enviar um anúncio de atualização, incluindo o ID recém-adquirido.

Observação: quando o dispositivo está processando uma chamada de API /privet/register, nenhuma outra chamada de API /privet/register pode ser processada simultaneamente. O dispositivo PRECISA retornar o erro device_busy e um tempo limite de 30 segundos.

É MUITO recomendável que o usuário confirme o registro no dispositivo. Se implementado, o dispositivo PRECISA aguardar a confirmação do usuário APÓS receber uma chamada de API /privet/register?action=start.  O cliente vai chamar a API /privet/register?action=getClaimToken para saber quando a confirmação do usuário for concluída e o token de reivindicação estiver disponível. Se o usuário cancelar o registro no dispositivo (por exemplo, pressionar o botão "Cancelar"), o erro user_cancel precisará ser retornado. Se o usuário não confirmar o registro em um determinado período, o erro confirmation_timeout DEVERÁ ser retornado. Consulte a seção de padrões para mais detalhes.

4.3.1. Entrada

A API /privet/register tem os seguintes parâmetros de entrada:
NomeValor
açãoPode ser um dos seguintes:
start: para iniciar o processo de registro
getClaimToken: para recuperar o token de reivindicação do dispositivo
cancel: para cancelar o processo de registro
complete: para concluir o processo de registro
usuárioE-mail do usuário que vai reivindicar o dispositivo.

O dispositivo PRECISA verificar se o endereço de e-mail de todas as ações (start, getClaimToken, cancel, complete) corresponde.

4.3.2. Retornar

A API /privet/register retorna os seguintes dados:
Nome do valorTipo de valorDescrição
açãostringMesma ação do parâmetro de entrada.
usuáriostring (opcional)O mesmo usuário do parâmetro de entrada (pode estar ausente se omitido na entrada).
tokenstring (opcional)Token de registro (obrigatório para a resposta "getClaimToken", omitido para "start", "complete", "cancel").
claim_urlstring (opcional)URL de registro (obrigatório para a resposta "getClaimToken", omitido para "start", "complete", "cancel"). Para impressoras na nuvem, ele precisa ser o "complete_invite_url" recebido do servidor.
automated_claim_urlstring (opcional)URL de registro (obrigatório para a resposta "getClaimToken", omitido para "start", "complete", "cancel"). Para impressoras na nuvem, ele precisa ser o "automated_invite_url" recebido do servidor.
device_idstring (opcional)Novo ID do dispositivo (omitido para a resposta "start", obrigatório para "complete").

O dispositivo PRECISA retornar o ID na resposta da API /privet/info SOMENTE depois que o registro for concluído.

Exemplo 1:

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

Exemplo 2:

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

Exemplo 3:

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

4.3.3. Erros

A API /privet/register pode retornar os seguintes erros (consulte a seção "Erros" para mais detalhes):
ErroDescrição
device_busyO dispositivo está ocupado e não pode realizar a ação solicitada. Tente de novo após o tempo limite.
pending_user_actionEm resposta a "getClaimToken", esse erro indica que o dispositivo ainda está aguardando a confirmação do usuário, e a solicitação "getClaimToken" precisa ser repetida após o tempo limite.
user_cancelO usuário cancelou explicitamente o processo de registro no dispositivo.
confirmation_timeoutO tempo limite da confirmação do usuário expira.
invalid_actionUma ação inválida é chamada. Por exemplo, se o cliente chamou action=complete antes de chamar action=start e action=getClaimToken.
invalid_paramsParâmetros inválidos especificados na solicitação. (Parâmetros desconhecidos podem ser ignorados com segurança para compatibilidade futura). Por exemplo, retorne isso se o cliente chamou action=unknown ou user=.
device_config_errorA data/hora (ou outras configurações) está incorreta no dispositivo. O usuário precisa acessar o site interno do dispositivo e configurar as opções.
off-lineO dispositivo está off-line e não pode se comunicar com o servidor.
server_errorOcorreu um erro no servidor durante o processo de registro.
invalid_x_privet_tokenO X-Privet-Token é inválido ou está vazio na solicitação.

O dispositivo NÃO PODE expor a API /privet/register depois que o registro for concluído. Se o dispositivo não estiver expondo a API /privet/register, ele PRECISA retornar o erro HTTP 404. Portanto, se um dispositivo já estiver registrado, a chamada dessa API vai retornar 404. Se o cabeçalho X-Privet-Token estiver faltando, o dispositivo vai retornar um erro HTTP 400.

4.4. API /privet/accesstoken

A API /privet/accesstoken é OPCIONAL. É uma solicitação HTTP GET. A API /privet/accesstoken PRECISA verificar um cabeçalho "X-Privet-Token" válido. O dispositivo PRECISA implementar essa API no URL "/privet/accesstoken":
GET /privet/accesstoken HTTP/1.1

Quando o dispositivo receber a chamada de API /accesstoken, ele precisará chamar o servidor para recuperar o token de acesso do usuário especificado e retornar o token ao cliente. Em seguida, o cliente vai usar o token de acesso para acessar esse dispositivo pela nuvem.

Os dispositivos do Cloud Print PRECISAM chamar a seguinte API:

/cloudprint/proximitytoken
e transmita o parâmetro "printerid=<printer_id>" e "user" da API local. Se for bem-sucedida, a resposta do servidor vai conter o seguinte objeto:
"proximity_token": {
        "user": "user@domain.com",
        "token": "AAA111222333444555666777",
        "expires_in": 600
}
Os dispositivos do Cloud Print PRECISAM transmitir o valor do objeto "proximity_token" na resposta para chamadas de API local /privet/accesstoken. É mais vantajoso (à prova de futuro) se o dispositivo puder transmitir TODOS os parâmetros (incluindo aqueles que não são descritos nesta especificação).

4.4.1. Entrada

A API /privet/accesstoken tem os seguintes parâmetros de entrada:
NomeValor
usuárioE-mail do usuário que pretendia usar este token de acesso. Pode estar vazio na solicitação.

4.4.2. Retornar

A API /privet/accesstoken retorna os seguintes dados:
Nome do valorTipo de valorDescrição
tokenstringToken de acesso retornado pelo servidor.
usuáriostringO mesmo usuário do parâmetro de entrada.
expires_inintNúmero de segundos até a expiração deste token. Recebido do servidor e transmitido nesta resposta.

Exemplo:

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

4.4.3. Erros

A API /privet/accesstoken pode retornar os seguintes erros (consulte a seção "Erros" para mais detalhes):
ErroDescrição
off-lineO dispositivo está off-line e não pode se comunicar com o servidor.
access_deniedDireitos insuficientes. Acesso negado. O dispositivo precisa retornar esse erro quando a solicitação for explicitamente negada pelo servidor.
invalid_paramsParâmetros inválidos especificados na solicitação. (Parâmetros desconhecidos podem ser ignorados com segurança para compatibilidade futura). Por exemplo, se o cliente chamou /accesstoken?user= ou /accesstoken.
server_errorErro do servidor.
invalid_x_privet_tokenO X-Privet-Token está inválido ou vazio na solicitação.

Se o dispositivo não estiver expondo a API /privet/accesstoken, ele precisará retornar o erro HTTP 404. Se o cabeçalho X-Privet-Token estiver faltando, o dispositivo vai retornar um erro HTTP 400.

4.5. API /privet/capabilities

A API /privet/capabilities é OPCIONAL. É uma solicitação HTTP GET. A API /privet/capabilities PRECISA verificar um cabeçalho "X-Privet-Token" válido. O dispositivo PRECISA implementar essa API no URL "/privet/capabilities":
GET /privet/capabilities HTTP/1.1
Quando o dispositivo recebe a chamada de API /capabilities, se possível, ele DEVE entrar em contato com o servidor para receber recursos atualizados. Por exemplo, se uma impressora aceitar o envio de um trabalho de impressão (recebido localmente) para ela mesma pelo serviço Cloud Print, ela vai retornar recursos que o serviço Cloud Print retornaria. Nesse caso, o Cloud Print pode alterar os recursos originais da impressora adicionando novos recursos que podem ser executados antes de enviar o trabalho para a impressora. O caso mais comum é uma lista de tipos de documentos aceitos. Se a impressora estiver off-line, ela vai retornar os tipos de documentos compatíveis. No entanto, se a impressora estiver on-line e registrada no Cloud Print, ela PRECISA retornar "*/*" como um dos tipos compatíveis. O serviço do Cloud Print vai fazer a conversão necessária nesse caso. Para impressão off-line, a impressora PRECISA ser compatível com pelo menos o formato "image/pwg-raster".

4.5.1. Entrada

A API /privet/capabilities tem os seguintes parâmetros de entrada:
NomeValor
off-line(opcional) Só pode ser "offline=1". Nesse caso, o dispositivo precisa retornar recursos para uso off-line (se forem diferentes dos recursos "on-line").

4.5.2. Retornar

A API /privet/capabilities retorna recursos do dispositivo no formato JSON da descrição do dispositivo na nuvem (CDD). Consulte o documento do CDD para mais detalhes. As impressoras precisam retornar uma lista de tipos compatíveis aqui. Por exemplo, uma impressora pronta para a nuvem que está on-line pode retornar algo assim (no mínimo):
{
        "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": "*/*" }
                ]
        }
}
e, quando ele é desconectado do servidor, pode retornar:
{
        "version": "1.0",
        "printer": {
                "supported_content_type": [
                        {
                                "content_type": "application/pdf",
                                "min_version": "1.4"
                        },
                        { "content_type": "image/pwg-raster" },
                        { "content_type": "image/jpeg" }
                ]
        }
}

Observação: as impressoras expressam a prioridade do tipo de conteúdo compatível usando a ordem. Por exemplo, nas amostras acima, a impressora especifica que prefere dados "application/pdf" em vez de "image/pwg-raster" e "image/jpeg". Os clientes precisam respeitar a priorização da impressora, se possível. Consulte o documento CDD para mais detalhes.

4.5.3. Erros

A API /privet/capabilities pode retornar os seguintes erros (consulte a seção "Erros" para mais detalhes):
ErroDescrição
invalid_x_privet_tokenO X-Privet-Token é inválido ou está vazio na solicitação.

Se o dispositivo não estiver expondo a API /privet/capabilities, ele precisará retornar o erro HTTP 404. Se o cabeçalho X-Privet-Token estiver faltando, o dispositivo vai retornar um erro HTTP 400.

4.6. Erros

Os erros são retornados das APIs acima no seguinte formato:
Nome do valorTipo de valorDescrição
errostringTipo de erro (definido por API)
descriçãostring (opcional)Descrição legível do erro.
server_apistring (opcional)Em caso de erro do servidor, esse campo contém a API do servidor que falhou.
server_codeint (opcional)Em caso de erro do servidor, este campo contém o código de erro retornado pelo servidor.
server_http_codeint (opcional)Em caso de erro HTTP do servidor, este campo contém o código de erro HTTP retornado pelo servidor.
timeoutint (opcional)Número de segundos que o cliente deve esperar antes de tentar novamente (somente para erros recuperáveis). O cliente PRECISA randomizar o tempo limite real desse valor para um valor que seja + 20%.

Todas as APIs precisam retornar o erro HTTP 400 se o cabeçalho X-Privet-Token estiver ausente.

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

Exemplo 1:

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

Exemplo 2:

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

5. API Printer

Um dos tipos de dispositivo compatíveis com esse protocolo é o tipo impressora. Os dispositivos compatíveis com esse tipo PODEM implementar algumas funcionalidades específicas para impressoras. O ideal é que a impressão em impressoras prontas para a nuvem passe por um servidor do Cloud Print:

Em alguns casos, um cliente pode precisar enviar um documento localmente. Isso pode ser necessário quando o cliente não tem um ID do Google ou não consegue se comunicar com o servidor do Cloud Print. Nesse caso, o trabalho de impressão será enviado localmente para a impressora. A impressora, por sua vez, usará o serviço Cloud Print para conversão e enfileiramento de trabalhos. A impressora vai postar novamente o trabalho enviado localmente para o serviço Cloud Print e, em seguida, vai solicitá-lo, já que foi enviado pela nuvem. Esse processo vai oferecer uma experiência do usuário flexível em termos de serviço (conversão) e gerenciamento/rastreamento de trabalhos de impressão.

Como o serviço Cloud Print implementa a conversão, a impressora DEVE anunciar o suporte a todos os formatos de entrada ("*/*") na lista de tipos de conteúdo compatíveis:

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

Em alguns casos, uma solução completamente off-line é desejada. Como as impressoras aceitam um número limitado de formatos de entrada, um cliente precisa converter documentos para alguns formatos de impressora compatíveis nativamente.

Essa especificação EXIGE que todas as impressoras ofereçam suporte a pelo menos o formato PWG Raster ("image/pwg-raster") para impressão off-line. Uma impressora pode ser compatível com outros formatos (por exemplo, JPEG) e, se um cliente for compatível, poderá enviar documentos nesse formato. A impressora PRECISA expor os tipos compatíveis pela API /capabilities, por exemplo:

{
        "version": "1.0",
        "printer": {
                "supported_content_type": [
                        { "content_type": "image/pwg-raster" },
                        { "content_type": "image/jpeg" }
                ]
        }
}
Há duas maneiras de um cliente iniciar a impressão na rede local.

Impressão simples: o cliente envia o documento pela rede local para a API /submitdoc (sem especificar o parâmetro job_id). O documento enviado será impresso usando as configurações padrão de tíquete de impressão, e não será necessário verificar o status do trabalho de impressão. Se a impressora for compatível APENAS com esse tipo de impressão, ela precisará anunciar APENAS a API /submitdoc na resposta da API /privet/info.

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

Impressão avançada: primeiro, o cliente precisa criar um trabalho de impressão na impressora chamando a API /privet/printer/createjob com um tíquete de trabalho CJT válido na solicitação. A impressora PRECISA armazenar o tíquete de impressão na memória e retornar um job_id ao cliente. Em seguida, o cliente vai chamar a API /printer/submitdoc e especificar o job_id recebido anteriormente. Nesse momento, a impressora vai começar a imprimir. O cliente vai consultar o status do trabalho de impressão na impressora chamando a API /privet/printer/jobstate.

Em um ambiente de vários clientes, não há garantia de como essa API é chamada. É possível que um cliente chame /createjob entre as chamadas /createjob->/submitdoc de outro cliente. Para eliminar possíveis impasses e melhorar a usabilidade, recomendamos ter uma pequena fila de trabalhos de impressão pendentes na impressora (pelo menos de 3 a 5):

  • /createjob pega o primeiro lugar disponível na fila.
  • A vida útil do job (na fila) é de pelo menos 5 minutos.
  • Se todos os espaços da fila estiverem ocupados, o job mais antigo que não estiver sendo impresso será removido e um novo será colocado no lugar.
  • Se houver um trabalho de impressão em andamento no dispositivo (impressão simples ou avançada), /submitdoc vai retornar o status "ocupado" e propor um tempo limite para tentar novamente.
  • Se /submitdoc se referir a um job que foi removido da fila (devido a substituição ou tempo limite), a impressora vai retornar um erro invalid_print_job e o cliente vai tentar novamente o processo na etapa /createjob. O cliente PRECISA aguardar um período de tempo limite aleatório de até 5 segundos antes de tentar novamente.

Se as restrições de memória impedirem o armazenamento de vários jobs pendentes no dispositivo, será possível ter uma fila de um job de impressão. Ele ainda vai seguir o mesmo protocolo acima. Depois que um job for concluído ou falhar com um erro, a impressora vai armazenar informações sobre o status dele por pelo menos cinco minutos. O tamanho da fila para armazenar status de jobs concluídos precisa ser de pelo menos 10. Se houver mais status de job que precisam ser armazenados, o mais antigo poderá ser removido da fila antes do tempo limite de 5 minutos.

Observação:por enquanto, os clientes vão pesquisar o status do job. No futuro, talvez seja necessário que a impressora envie uma notificação TXT DNS quando o status de QUALQUER trabalho de impressão mudar.

5.1. API /privet/printer/createjob

A API /privet/printer/createjob é OPCIONAL (consulte "Impressão simples" acima). É uma solicitação HTTP POST. A API /privet/printer/createjob precisa verificar se há um cabeçalho "X-Privet-Token" válido. O dispositivo PRECISA implementar essa API no URL "/privet/printer/createjob":

POST /privet/printer/createjob HTTP/1.1
Ao receber a chamada de API /privet/printer/createjob, a impressora PRECISA criar um novo ID de trabalho de impressão, armazenar o tíquete de impressão recebido no formato CJT e retornar o ID do trabalho de impressão ao cliente.

5.1.1. Entrada

A API /privet/printer/createjob não tem parâmetros de entrada no URL. O corpo da solicitação precisa conter os dados do tíquete do job de impressão no formato CJT.

5.1.2. Retornar

A API /privet/printer/createjob retorna os seguintes dados:
Nome do valorTipo de valorDescrição
job_idstringID do job de impressão recém-criado.
expires_inintNúmero de segundos em que este job de impressão é válido.

Exemplo:

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

5.1.3. Erros

A API /privet/printer/createjob pode retornar os seguintes erros (consulte a seção "Erros" para mais detalhes):
ErroDescrição
invalid_ticketO comprovante de impressão enviado é inválido.
printer_busyA impressora está ocupada e não pode processar /createjob no momento. Tente de novo após o tempo limite.
printer_errorA impressora está em estado de erro e exige interação do usuário para ser corrigida. A descrição precisa conter uma explicação mais detalhada (por exemplo, "Atolamento de papel na bandeja 1").
invalid_x_privet_tokenO X-Privet-Token é inválido ou está vazio na solicitação.

Se o dispositivo não estiver expondo /privet/printer/createjob, ele precisará retornar o erro HTTP 404. Se o cabeçalho X-Privet-Token estiver faltando, o dispositivo vai retornar um erro HTTP 400.

5.2. API /privet/printer/submitdoc

A API /privet/printer/submitdoc é OBRIGATÓRIA para implementar a impressão em uma rede local (off-line ou repostagem no Cloud Print). É uma solicitação HTTP POST. A API /privet/printer/submitdoc precisa verificar um cabeçalho "X-Privet-Token" válido. O dispositivo PRECISA implementar essa API no URL "/privet/printer/submitdoc":
POST /privet/printer/submitdoc HTTP/1.1
Ao receber a chamada de API /privet/printer/submitdoc, a impressora deve começar a imprimir. Se não for possível iniciar a impressão, ele PRECISA retornar o erro printer_busy e um período de tempo limite recomendado para que o cliente aguarde antes de tentar novamente.

Se a impressora não conseguir armazenar todos os dados no buffer interno, ela DEVE usar mecanismos TCP para diminuir a transferência de dados até imprimir uma parte do documento, disponibilizando novamente parte do buffer. Por exemplo, a impressora pode definir windowsize=0 nas camadas TCP, o que fará com que o cliente espere.

O envio de um documento para a impressora pode levar um tempo considerável. O cliente precisa poder verificar o estado da impressora e do trabalho (impressão avançada) enquanto a impressão está em andamento. Para isso, a impressora PRECISA permitir que o cliente chame as APIs /privet/info e /privet/printer/jobstate ao processar chamadas de API /privet/printer/submitdoc. Recomendamos que todos os clientes iniciem uma nova linha de execução para executar a chamada de API /privet/printer/submitdoc. Assim, a linha de execução principal pode usar as APIs /privet/info e /privet/printer/jobstate para verificar os estados da impressora e do trabalho.

Observação: ao concluir ou cancelar o trabalho de impressão local, é altamente recomendável (e será obrigatório em uma versão futura desta especificação) informar o estado final do trabalho à interface /cloudprint/submit para fins de contabilidade e experiência do usuário. Os parâmetros "printerid", "title", "contentType" e "final_semantic_state" (no formato PrintJobState) são obrigatórios, assim como os parâmetros "tag" (parâmetro repetido) e "ticket" (o tíquete do trabalho no formato CloudJobTicket). O PrintJobState fornecido precisa ser final.Ou seja, o tipo precisa ser DONE ou ABORTED, e uma causa precisa ser fornecida caso seja ABORTED. Consulte JobState para mais detalhes. Além disso, o uso da interface /cloudprint/submit para informar jobs de impressão locais não é mencionado na especificação porque essa seção descreve o uso principal da interface: enviar um job de impressão com o documento a ser impresso fornecido no parâmetro "content".

5.2.1. Entrada

A API /privet/printer/submitdoc tem os seguintes parâmetros de entrada:
NomeValor
job_id(opcional) ID do job de impressão. Pode ser omitido para impressão simples (veja acima). Precisa corresponder ao retornado pela impressora.
user_name(opcional) Nome de usuário legível. Isso não é definitivo e só deve ser usado para anotações de trabalhos de impressão. Se o job for postado novamente no serviço Cloud Print, essa string será anexada ao job do Cloud Print.
client_name(opcional) Nome do aplicativo cliente que está fazendo esta solicitação. Somente para fins de exibição. Se o job for postado novamente no serviço Cloud Print, essa string será anexada ao job do Cloud Print.
job_name(Opcional) Nome do trabalho de impressão a ser registrado. Se o job for postado novamente no serviço Cloud Print, essa string será anexada ao job do Cloud Print.
off-line(opcional) Só pode ser "offline=1". Nesse caso, a impressora só deve tentar imprimir off-line (sem postagem novamente no servidor do Cloud Print).

O corpo da solicitação precisa conter um documento válido para impressão. "Content-Length" precisa incluir o tamanho correto da solicitação. O cabeçalho "Content-Type" precisa ser definido como o tipo MIME do documento e corresponder a um dos tipos no CDD, a menos que o CDD especifique "*/*".

É ALTAMENTE recomendável que os clientes forneçam um nome de usuário (ou e-mail) válido, um nome de cliente e um nome de trabalho com essa solicitação. Esses campos são usados apenas em interfaces para melhorar a experiência do usuário.

5.2.2. Retornar

A API /privet/printer/submitdoc retorna os seguintes dados:
Nome do valorTipo de valorDescrição
job_idstringID do trabalho de impressão recém-criado (impressão simples) ou job_id especificado na solicitação (impressão avançada).
expires_inintNúmero de segundos em que este job de impressão é válido.
job_typestringTipo de conteúdo do documento enviado.
job_sizeint de 64 bitsTamanho dos dados de impressão em bytes.
job_namestring(opcional) Mesmo nome do job que na entrada (se houver).

Exemplo:

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

5.2.3. Erros

A API /privet/printer/submitdoc pode retornar os seguintes erros (consulte a seção "Erros" para mais detalhes):
ErroDescrição
invalid_print_jobUm ID de job inválido/expirado foi especificado na solicitação. Tente de novo após o tempo limite.
invalid_document_typeO tipo MIME do documento não é compatível com a impressora.
invalid_documentO documento enviado é inválido.
document_too_largeO documento excede o tamanho máximo permitido.
printer_busyA impressora está ocupada e não pode processar o documento no momento. Tente de novo após o tempo limite.
printer_errorA impressora está em estado de erro e exige interação do usuário para ser corrigida. A descrição precisa conter uma explicação mais detalhada (por exemplo, "Atolamento de papel na bandeja 1").
invalid_paramsParâmetros inválidos especificados na solicitação. (Parâmetros desconhecidos devem ser ignorados com segurança para compatibilidade futura)
user_cancelO usuário cancelou explicitamente o processo de impressão no dispositivo.
server_errorFalha ao postar o documento no Cloud Print.
invalid_x_privet_tokenO X-Privet-Token é inválido ou está vazio na solicitação.

Se o dispositivo não estiver expondo /privet/printer/submitdoc, ele precisará retornar o erro HTTP 404. Se o cabeçalho X-Privet-Token estiver faltando, o dispositivo vai retornar um erro HTTP 400.

Observação: a API /privet/printer/submitdoc pode exigir um tratamento especial no lado da impressora (devido à grande carga útil anexada). Em alguns casos (depende da implementação e da plataforma do servidor HTTP da impressora), a impressora pode fechar o soquete ANTES de retornar um erro HTTP. Em outros casos, a impressora pode retornar um erro 503 em vez de um erro do Privet. As impressoras DEVEM tentar ao máximo retornar Privet. No entanto, todo cliente que implementa a especificação Privet DEVE ser capaz de processar o fechamento do soquete (sem erro HTTP) e os casos de erro HTTP 503 para a API /privet/printer/submitdoc. Nesse caso, o cliente PRECISA processar como um erro "printer_busy" do Privet com "timeout" definido como 15 segundos. Para evitar novas tentativas infinitas, o cliente pode parar de tentar novamente após um número razoável de tentativas (por exemplo, 3).

5.3. API /privet/printer/jobstate

A API /privet/printer/jobstate é OPCIONAL (consulte "Impressão simples" acima). É uma solicitação HTTP GET. A API /privet/printer/jobstate PRECISA verificar se há um cabeçalho "X-Privet-Token" válido. O dispositivo PRECISA implementar essa API no URL "/privet/printer/jobstate":
GET /privet/printer/jobstate HTTP/1.1
Ao receber uma chamada de API /privet/printer/jobstate, uma impressora deve retornar o status do trabalho de impressão solicitado ou o erro invalid_print_job.

5.3.1. Entrada

A API /privet/printer/jobstate tem os seguintes parâmetros de entrada:
NomeValor
job_idID do trabalho de impressão para retornar o status.

5.3.2. Retornar

A API /privet/printer/jobstate retorna os seguintes dados:
Nome do valorTipo de valorDescrição
job_idstringID do trabalho de impressão para o qual as informações de status são válidas.
estadostringdraft: o trabalho de impressão foi criado no dispositivo. Ainda não foram recebidas chamadas /privet/printer/submitdoc.
na fila: o trabalho de impressão foi recebido e colocado na fila, mas a impressão ainda não começou.
in_progress: o trabalho de impressão está em andamento.
stopped: o job de impressão foi pausado, mas pode ser reiniciado manual ou automaticamente.
done: o trabalho de impressão foi concluído.
abortado: o trabalho de impressão falhou.
descriçãostring(Opcional) Descrição legível por humanos do status do trabalho de impressão. Inclua informações adicionais se state for stopped ou aborted. O campo semantic_state geralmente fornece uma descrição melhor e mais significativa para o cliente.
expires_inintNúmero de segundos em que este job de impressão é válido.
job_typestring(opcional) Tipo de conteúdo do documento enviado.
job_sizeint de 64 bits(opcional) Tamanho dos dados de impressão em bytes.
job_namestring(opcional) Mesmo nome do job que na entrada (se houver).
server_job_idstring(opcional) ID do job retornado do servidor (se o job tiver sido postado no serviço do Cloud Print). Omitido para impressão off-line.
semantic_stateJSON(Opcional) Estado semântico do job no formato PrintJobState.

Exemplo (impressão por relatórios usando o 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"
}

Exemplo (erro de impressão off-line):

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

Exemplo (trabalho de impressão cancelado pelo usuário):

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

Exemplo: o trabalho de impressão foi interrompido por falta de papel. Observe a referência ao estado do dispositivo. O cliente precisa chamar a API /privet/info para receber mais detalhes sobre o estado do dispositivo:

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

A API /privet/printer/jobstate pode retornar os seguintes erros (consulte a seção "Erros" para mais detalhes):
ErroDescrição
invalid_print_jobUm ID do job inválido/expirado foi especificado na solicitação.
server_errorFalha ao receber o status do trabalho de impressão (para trabalhos de impressão postados no Cloud Print).
invalid_x_privet_tokenO X-Privet-Token é inválido ou está vazio na solicitação.

Se o dispositivo não estiver expondo /privet/printer/jobstate, ele precisará retornar o erro HTTP 404. Se o cabeçalho X-Privet-Token estiver faltando, o dispositivo vai retornar um erro HTTP 400.

6. Apêndice

6.1. Comportamento e configurações padrão

Esta seção explica o comportamento padrão esperado de TODOS os dispositivos compatíveis com o Privet.
  • Os dispositivos prontos para uso só podem oferecer suporte às APIs /privet/info e /privet/register. Todas as outras APIs (por exemplo, /privet/accesstoken, impressão local) precisam ser desativadas.
  • O registro exige interação física com um dispositivo.
    • O usuário PRECISA realizar uma ação física no dispositivo (por exemplo, pressionar um botão) para confirmar o acesso a ele.
    • Depois que o usuário realizar a ação observada acima, a impressora vai enviar a solicitação /cloudprint/register. Ele não deve enviar essa solicitação até que a ação seja realizada (consulte o diagrama de sequência 1).
    • Se o dispositivo estiver processando uma solicitação /privet/register (por exemplo, aguardando a ação acima), ele precisará rejeitar todas as outras solicitações /privet/register. Nesse caso, o dispositivo PRECISA retornar o erro device_busy.
    • O dispositivo deve atingir o tempo limite de qualquer solicitação /register que não receba a ação física mencionada acima em 60 segundos. Nesse caso, o dispositivo PRECISA retornar o erro confirmation_timeout.
    • Opcional: recomendado, mas não obrigatório. O seguinte pode melhorar a experiência do usuário:
      • A impressora pode piscar uma luz ou a tela para indicar que o usuário precisa realizar uma ação para confirmar o registro.
      • A impressora pode mostrar na tela que "está sendo registrada no Google Cloud Print para o usuário abc@def.com. Pressione OK para continuar", em que abc@def.com é o parâmetro do usuário da chamada de API /register. Isso deixaria mais claro para um usuário que:
        • é o pedido de inscrição que eles estão confirmando
        • o que está acontecendo se ele/ela não acionou a solicitação.
      • Além de uma ação física para confirmar na impressora (por exemplo, "Pressione o botão OK"), uma impressora também pode oferecer ao usuário um botão para cancelar a solicitação (por exemplo, Pressione "Cancelar" para rejeitar. Isso permitiria que os usuários que não acionaram a solicitação de registro cancelassem antes do tempo limite de 60 segundos. Nesse caso, o dispositivo PRECISA retornar o erro user_cancel.
  • Transferências de propriedade:
    • O dispositivo pode ser excluído explicitamente do serviço de nuvem.
      • Se o dispositivo receber uma resposta de sucesso, mas nenhuma descrição como resultado de uma chamada /cloudprint/printer (para GCP), ele precisará voltar ao modo padrão (pronto para uso).
      • Se as credenciais do dispositivo não funcionarem mais (explicitamente devido à resposta "credenciais inválidas" do servidor), ele DEVERÁ voltar ao modo padrão (pronto para uso).
    • A redefinição de fábrica local PRECISA limpar as credenciais do dispositivo e definir o estado padrão.
    • Opcional: o dispositivo pode fornecer um item de menu para limpar as credenciais e colocá-lo no modo padrão.
  • Os dispositivos que oferecem suporte a notificações XMPP PRECISAM incluir a capacidade de fazer ping no servidor. O tempo limite de ping PRECISA ser controlável pelo servidor usando "local_settings".
  • O dispositivo pode fazer ping no servidor (/cloudprint/printer API para GCP, além de pings XMPP) no máximo uma vez por dia (24 horas) para garantir que eles estejam sincronizados. É recomendável aleatorizar a janela de verificação em um período de 24 a 32 horas.
  • Opcional: para dispositivos Cloud Print, é recomendável, mas não obrigatório, ter uma maneira manual (botão) para permitir que o usuário inicie uma verificação de novos trabalhos de impressão no dispositivo. Algumas impressoras já têm essa opção.
  • Opcional. As impressoras empresariais podem ter uma opção para desativar completamente a descoberta local. Nesse caso, o dispositivo PRECISA atualizar essas configurações locais no servidor. As novas configurações locais precisam estar vazias. Definir "local_discovery" como "false" significa que elas podem ser reativadas no serviço do GCP.

6.1.2 Diagrama de registro padrão

6.2. Ataques e prevenção de XSSI e XSRF

Esta seção explica a possibilidade de ataques XSSI e XSRF no dispositivo e como se proteger contra eles, incluindo técnicas de geração de tokens.
Mais detalhes aqui: http://googleonlinesecurity.blogspot.com/2011/05/website-security-for-webmasters.html
Normalmente, os ataques XSSI e XSRF são possíveis quando um site usa mecanismos de autenticação de cookies. Embora o Google não use cookies com o serviço Google Cloud Printer, esses ataques ainda são possíveis. O acesso à rede local, por design, confia implicitamente nas solicitações.

6.2.1. XSSI

É possível que um site malicioso adivinhe o endereço IP e o número da porta de um dispositivo compatível com o Privet e tente chamar a API Privet usando "src=<nome da API>" dentro de uma tag <script>:
<script type="text/javascript" src="http://192.168.1.42:8080/privet/info"></script>
Sem proteção, sites maliciosos poderiam executar chamadas de API e acessar resultados.
Para evitar esse tipo de ataque, TODAS as chamadas da API Privet precisam exigir o cabeçalho "X-Privet-Token" na solicitação. As tags de script "src=<api>" não podem adicionar cabeçalhos, protegendo contra esse tipo de ataque.

6.2.2. XSRF

http://en.wikipedia.org/wiki/Cross-site_request_forgery
É possível que um site malicioso adivinhe o endereço IP e o número da porta de um dispositivo compatível com o Privet e tente chamar a API Privet usando um <iframe>, formulários ou algum outro mecanismo de carregamento entre sites. Os invasores não conseguiriam acessar os resultados da solicitação, mas, se ela realizasse uma ação (por exemplo, impressão), eles poderiam acioná-la.

Para evitar esse ataque, precisamos da seguinte proteção:

  • Deixar a API /privet/info aberta para XSRF
  • A API /privet/info NÃO PODE realizar nenhuma ação no dispositivo.
  • Use a API /privet/info para receber x-privet-token
  • Todas as outras APIs precisam verificar um x-privet-token válido no cabeçalho "X-Privet-Token".
  • x-privet-token SHOULD be valid for only 24 hours.

Mesmo que um invasor consiga executar a API /privet/info, ele não poderá ler x-privet-token da resposta e, portanto, não poderá chamar nenhuma outra API.

Recomendamos gerar o token XSRF usando o seguinte algoritmo:

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

Elementos de geração de token XSRF:

  • DELIMITER é um caractere especial, geralmente ":"
  • issue_timecounter é um número de segundos desde algum evento (época para carimbo de data/hora) ou tempo de inicialização do dispositivo (para contadores de CPU). issue_timecounter aumenta constantemente quando o dispositivo está funcionando (consulte a verificação de token abaixo).
  • SHA1: função de hash que usa o algoritmo SHA1.
  • base64: codificação base64
  • device_secret: senha específica do dispositivo. O secret do dispositivo PRECISA ser atualizado a cada reinicialização.

Formas recomendadas de gerar o secret do dispositivo:

  • Gerar um novo UUID a cada reinicialização
  • Gerar um número aleatório de 64 bits a cada reinicialização

O dispositivo não precisa armazenar todos os tokens XSRF emitidos. Quando o dispositivo precisa verificar a validade de um token XSRF, ele precisa decodificar o token em base64. Extraia o issue_timecounter da segunda metade (texto simples) e tente gerar o hash SHA1 de device_secret + DELIMITER + issue_timecounter, em que issue_timecounter é do token. Se o SHA1 recém-gerado corresponder ao do token, o dispositivo precisará verificar se o issue_timecounter está dentro do período de validade (24 horas) do contador de tempo atual. Para isso, o dispositivo usa o contador de tempo atual (contador da CPU, por exemplo) e subtrai issue_timecounter dele. O resultado PRECISA ser o número de segundos desde a emissão do token.

Importante:esta é a maneira recomendada de implementar a proteção contra XSRF. Os clientes da especificação Privet não devem tentar entender o token XSRF, mas tratá-lo como uma caixa preta. A Figura 6.2.3 ilustra uma maneira recomendada de implementar o X-Privet-Token e a verificação de uma solicitação típica.

6.2.3 Diagrama de sequência de geração e verificação de token X-Privet

6.3. Diagramas de fluxo de trabalho

Esta seção vai ilustrar um fluxo de trabalho em diferentes casos.

6.3.1. Fluxo de trabalho da impressora pronta para uso

6.3.2. Inicialização da impressora registrada

6.3.3 Fluxo de trabalho de processamento de notificações XMPP

6.3.4. Verificar o fluxo de trabalho das configurações da impressora