Privet

Privet to interfejs Cloud Device Local Discovery API używany przez usługi w chmurze. Ten dokument jest podzielony na te sekcje:

  1. Wprowadzenie: wprowadzenie do Privet
  2. Discovery: lokalne mechanizmy wykrywania.
  3. Ogłoszenia: ogłoszenia dotyczące lokalnego odkrywania
  4. API: prywatne interfejsy API dla ogólnych urządzeń w chmurze
  5. Printer API: prywatne interfejsy API używane przez drukarki.
  6. Dodatek: dodatkowe diagramy

1. Wprowadzenie

Urządzenia połączone z chmurą mają wiele zalet. Mogą korzystać z usług konwersji online, hostować kolejki zadań, gdy urządzenie jest offline, i być dostępne z dowolnego miejsca na świecie. Jednak w przypadku wielu urządzeń w chmurze dostępnych dla danego użytkownika musimy udostępnić metodę znajdowania najbliższego urządzenia na podstawie lokalizacji. Protokół Privet ma na celu połączenie elastyczności urządzeń w chmurze z odpowiednim mechanizmem wykrywania lokalnego, aby urządzenia można było łatwo wykrywać w nowych środowiskach.

Cele tego protokołu to:
  • umożliwiać wykrywanie urządzeń w chmurze w sieci lokalnej,
  • rejestrować urządzenia w chmurze w usłudze w chmurze,
  • powiązywać zarejestrowane urządzenia z ich reprezentacją w chmurze;
  • włączyć funkcję offline,
  • uprościć implementację, aby można było z niej korzystać na małych urządzeniach;

Protokół Privet składa się z 2 głównych części: wykrywania i interfejsu API. Wykrywanie służy do znajdowania urządzenia w sieci lokalnej, a interfejs API służy do uzyskiwania informacji o urządzeniu i wykonywania niektórych działań. W tym dokumencie termin „urządzenie” odnosi się do urządzenia połączonego z chmurą, które implementuje protokół Privet.

2. Odkrywanie

Wykrywanie to protokół oparty na zeroconf (mDNS + DNS-SD). Urządzenie MUSI obsługiwać adresowanie IPv4 Link-Local. Urządzenie MUSI być zgodne ze specyfikacjami mDNS i DNS-SD.

Urządzenie MUSI rozwiązywać konflikty nazw zgodnie z powyższymi specyfikacjami.

2.1. Typ usługi

W przypadku typów usług usługa DNS Service Discovery używa tego formatu: _applicationprotocol._transportprotocol. W przypadku protokołu Privet typ usługi dla DNS-SD powinien mieć postać: _privet._tcp

Urządzenie może też obsługiwać inne typy usług. Zalecamy używanie tej samej nazwy instancji usługi w przypadku wszystkich typów usług zaimplementowanych na urządzeniu. Na przykład drukarka może implementować usługi „Drukarka XYZ._privet._tcp” i „Drukarka XYZ._printer._tcp”. Ułatwi to użytkownikowi konfigurację. Klienci Privet będą jednak szukać tylko „_privet._tcp”.

Oprócz głównego typu usługi urządzenie MUSI reklamować rekordy PTR dla odpowiednich podtypów (patrz specyfikacja DNS-SD: „7.1. Selective Instance Enumeration (Subtypes)”. Format powinien być następujący: _<subtype>._sub._privet._tcp

Obecnie jedynym obsługiwanym podtypem urządzenia jest drukarka. Dlatego wszystkie drukarki MUSZĄ reklamować 2 rekordy PTR:

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

2.2. Rekord TXT

DNS Service Discovery określa pola, w których można dodać opcjonalne informacje o usłudze w rekordach TXT. Rekord TXT składa się z par klucz/wartość. Każda para klucz/wartość zaczyna się od bajtu długości, po którym następuje maksymalnie 255 bajtów tekstu. Kluczem jest tekst przed pierwszym znakiem „=” i wartością jest tekst po pierwszym znaku „=” aż do końca. Specyfikacja dopuszcza brak wartości w rekordzie. W takim przypadku nie będzie znaku „=” ani tekstu po nim. (Patrz specyfikacja DNS-SD: „6.1. Ogólne reguły formatowania rekordów DNS TXT” w sekcji „6.2. DNS-SD TXT Record Size" (Rozmiar rekordu DNS-SD TXT) w celu sprawdzenia zalecanej długości).

Privet wymaga, aby urządzenie wysyłało w rekordzie TXT te pary klucz/wartość: W ciągach tekstowych klucz/wartość wielkość liter nie jest rozróżniana, np. „CS=online” i „cs=ONLINE” to to samo. Informacje w rekordzie TXT MUSZĄ być takie same jak te, które są dostępne przez interfejs API /info (patrz sekcja 4.1). sekcja API).

Zalecamy, aby rozmiar rekordu TXT nie przekraczał 512 bajtów.

2.2.1. txtvers

Wersja struktury TXT. txtvers MUSI być pierwszym rekordem struktury TXT. Obecnie obsługiwana jest tylko wersja 1.

txtvers=1

2.2.2. ty

Zawiera nazwę urządzenia czytelną dla użytkownika. Na przykład:

ty=Google Cloud Ready Printer Model XYZ

2.2.3. note (opcjonalnie)

Zawiera nazwę urządzenia czytelną dla użytkownika. Na przykład:

note=1st floor lobby printer

Uwaga: ten klucz jest opcjonalny i można go pominąć. Jeśli jednak jest obecna, użytkownik POWINIEN mieć możliwość zmodyfikowania tej wartości. Podczas rejestracji urządzenia MUSI być użyty ten sam opis.

2.2.4. url

Adres URL serwera, z którym połączone jest to urządzenie (wraz z protokołem). Na przykład:

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

2.2.5. type

Lista rozdzielanych przecinkami podtypów urządzeń obsługiwanych przez to urządzenie. Format: „type=_subtype1,_subtype2”. Obecnie jedynym obsługiwanym podtypem urządzenia jest drukarka.

type=printer

Każdy wymieniony podtyp powinien być reklamowany za pomocą odpowiedniego rekordu PTR. Każdy obsługiwany podtyp usługi powinien mieć odpowiadający mu element. Nazwa podtypu usługi (<subtype>._sub._privet._tcp) powinna być tutaj równa typowi urządzenia.

2.2.6. id

Identyfikator urządzenia. Jeśli urządzenie nie zostało jeszcze zarejestrowane, ten klucz powinien być obecny, ale wartość powinna być pusta. Na przykład:

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

2.2.7. cs

Wskazuje bieżący stan połączenia urządzenia. W tej specyfikacji zdefiniowano 4 możliwe wartości.

  • „online” oznacza, że urządzenie jest obecnie połączone z chmurą.
  • „offline” oznacza, że urządzenie jest dostępne w sieci lokalnej, ale nie może komunikować się z serwerem.
  • „Łączenie” oznacza, że urządzenie wykonuje sekwencję uruchamiania i nie jest jeszcze w pełni online.
  • „not-configured” oznacza, że dostęp do internetu na urządzeniu nie został jeszcze skonfigurowany. Ta wartość nie jest obecnie używana, ale może być przydatna w przyszłych wersjach specyfikacji.
Przykład:
  • cs=online
  • cs=offline
  • cs=connecting

Jeśli urządzenie zostało zarejestrowane w chmurze, po uruchomieniu powinno sprawdzić łączność z serwerem, aby wykryć stan połączenia (np. wywołać interfejs API chmury w celu uzyskania ustawień urządzenia). Urządzenie może używać stanu połączenia z kanałem powiadomień (np. XMPP) do raportowania tej wartości. Niezarejestrowane urządzenia mogą podczas uruchamiania wysyłać ping do domeny, aby wykryć stan połączenia (np. wysyłać ping do www.google.com w przypadku urządzeń do drukowania w chmurze).

3. Ogłoszenia

Podczas uruchamiania, wyłączania lub zmiany stanu urządzenie MUSI wykonać krok ogłaszania zgodnie ze specyfikacją mDNS. POWINIEN wysłać odpowiedni komunikat co najmniej 2 razy w odstępie co najmniej 1 sekundy.

3.1. Uruchomienie

Po uruchomieniu urządzenie MUSI wykonać kroki sondowania i ogłaszania opisane w specyfikacji mDNS. W tym przypadku należy wysłać rekordy SRV, PTR i TXT. Zalecamy zgrupowanie wszystkich rekordów w jednej odpowiedzi DNS, jeśli to możliwe. W przeciwnym razie zalecamy kolejność: SRV, PTR, TXT.

3.2. Wyłączono

Podczas wyłączania urządzenia POWINNO ono powiadomić o tym wszystkie zainteresowane strony, wysyłając „pakiet pożegnalny” z TTL=0 (zgodnie z dokumentacją mDNS).

3.3 Aktualizuj

Jeśli jakiekolwiek informacje opisane w rekordzie TXT ulegną zmianie, urządzenie MUSI wysłać powiadomienie o aktualizacji. W tym przypadku wystarczy wysłać tylko nowy rekord TXT. Na przykład po zarejestrowaniu urządzenia MUSI ono wysłać komunikat z informacją o aktualizacji, w tym nowy identyfikator urządzenia.

4. Interfejs API

Po wykryciu urządzenia w chmurze komunikacja klienta z urządzeniem jest włączana bezpośrednio w sieci lokalnej. Wszystkie interfejsy API są oparte na protokole HTTP 1.1. Formaty danych są oparte na formacie JSON. Żądania API mogą być żądaniami GET lub POST.

Każde żądanie MUSI zawierać prawidłowy nagłówek „X-Privet-Token”. JEDYNYM żądaniem, które może mieć pusty nagłówek „X-Privet-Token”, jest żądanie /privet/info (pamiętaj, że nagłówek MUSI być nadal obecny). Jeśli brakuje nagłówka „X-Privet-Token”, urządzenie MUSI odpowiedzieć błędem HTTP 400:

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

Jeśli nagłówek „X-Privet-Token” jest pusty lub nieprawidłowy, urządzenie MUSI odpowiedzieć „invalid X-Privet-Token error” (invalid_x_privet_token, szczegóły znajdziesz w sekcji Błędy). Jedynym wyjątkiem jest interfejs API /info. Więcej informacji o tym, dlaczego to robimy i jak generować tokeny, znajdziesz w Dodatku A: Ataki XSSI i XSRF oraz sposoby zapobiegania im.

Jeśli żądany interfejs API nie istnieje lub nie jest obsługiwany, urządzenie MUSI zwrócić błąd HTTP 404.

4.1. Dostępność interfejsu API

Zanim jakikolwiek interfejs API zostanie udostępniony (w tym interfejs API /info), urządzenie MUSI skontaktować się z serwerem, aby sprawdzić ustawienia lokalne. Ustawienia lokalne MUSZĄ być zachowywane między ponownymi uruchomieniami. Jeśli serwer jest niedostępny, należy użyć ostatnio znanych ustawień lokalnych. Jeśli urządzenie nie zostało jeszcze zarejestrowane, powinno korzystać z ustawień domyślnych.

Aby zarejestrować urządzenie, otrzymywać i aktualizować ustawienia lokalne, urządzenia Cloud Print MUSZĄ wykonać czynności opisane poniżej.

4.1.1. Rejestracja

Podczas rejestracji urządzenia MUSI ono określić parametr „local_settings” w ten sposób:

{
       "current": {
                "local_discovery": true,
                "access_token_enabled": true,
                "printer/local_printing_enabled": true,
                "printer/conversion_printing_enabled": true,
                "xmpp_timeout_value": 300
        }
}
Możesz ustawić te opcje:
Nazwa wartościTyp wartościOpis
local_discoveryWartość logicznaWskazuje, czy funkcja wykrywania lokalnego jest dozwolona. Jeśli wartość to „false”, wszystkie lokalne interfejsy API (w tym /info) i wykrywanie DNS-SD muszą być wyłączone. Domyślnie nowo rejestrowane urządzenia powinny przekazywać wartość „true”.
access_token_enabledwartość logiczna (opcjonalnie)Wskazuje, czy interfejs API /accesstoken ma być udostępniany w sieci lokalnej. Domyślnie powinna mieć wartość „true”.
printer/local_printing_enabledwartość logiczna (opcjonalnie)Wskazuje, czy funkcja drukowania lokalnego (/printer/createjob, /printer/submitdoc, /printer/jobstate) ma być udostępniana w sieci lokalnej. Domyślnie powinna mieć wartość „true”.
printer/conversion_printing_enabledwartość logiczna (opcjonalnie)Wskazuje, czy drukowanie lokalne może wysyłać zadanie do serwera w celu konwersji. Ma sens tylko wtedy, gdy drukowanie lokalne jest włączone.
xmpp_timeout_valueint (opcjonalnie)Wskazuje liczbę sekund między pingami kanału XMPP. Domyślnie MUSI wynosić co najmniej 300 sekund (5 minut).

Ważne: brak wartości opcjonalnej oznacza, że urządzenie w ogóle nie obsługuje odpowiedniej funkcji.

4.1.2. Uruchomienie

Po uruchomieniu urządzenie powinno skontaktować się z serwerem, aby sprawdzić, które interfejsy API są dostępne do udostępnienia w sieci lokalnej. W przypadku drukarek połączonych z Cloud Print należy wywołać:

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

Preferowany jest adres /cloudprint/printer, ale /cloudprint/list też będzie działać.

Ten interfejs API zwraca bieżące parametry urządzenia, w tym ustawienia lokalnego interfejsu API. Odpowiedź serwera będzie miała następujący format:

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

Obiekt „current” wskazuje ustawienia, które są obecnie aktywne.

Obiekt „pending” wskazuje ustawienia, które powinny zostać zastosowane na urządzeniu (tego obiektu może brakować).

Gdy urządzenie zobaczy ustawienia „oczekujące”, MUSI zaktualizować swój stan (patrz poniżej).

4.1.3. Aktualizuj

Jeśli wymagana jest aktualizacja ustawień, na urządzenie zostanie wysłane powiadomienie XMPP. Powiadomienie będzie miało następujący format:

<device_id>/update_settings

Po otrzymaniu takiego powiadomienia urządzenie MUSI wysłać zapytanie do serwera, aby pobrać najnowsze ustawienia. Urządzenia Cloud Print MUSZĄ używać:

/cloudprint/printer?printerid=<printer_id>

Gdy urządzenie zobaczy sekcję „oczekujące” w wyniku wywołania interfejsu API /cloudprint/printer (przy uruchamianiu lub z powodu powiadomienia), MUSI zaktualizować swój stan wewnętrzny, aby zapamiętać nowe ustawienia. MUSI wywołać interfejs API serwera, aby potwierdzić nowe ustawienia. W przypadku drukarek w chmurze urządzenie MUSI wywołać interfejs API /cloudprint/update i użyć parametru „local_settings” tak jak podczas rejestracji.

Podczas ponownego łączenia się z kanałem XMPP urządzenie MUSI wywołać interfejs API /cloudprint/printer, aby sprawdzić, czy od ostatniego połączenia lokalne ustawienia uległy zmianie.

4.1.3.1. Ustawienia lokalne oczekujące

Parametr „local_settings”, którego urządzenie używa do wywoływania interfejsu API serwera, NIE MOŻE zawierać sekcji „pending”.

4.1.3.2. Ustawienia lokalne – bieżące

TYLKO urządzenie może zmieniać sekcję „current” w „local_settings”. Pozostali użytkownicy będą zmieniać sekcję „Oczekujące” i czekać, aż zmiany zostaną przeniesione do sekcji „Bieżące” przez urządzenie.

4.1.4. Offline

Jeśli podczas uruchamiania nie można nawiązać połączenia z serwerem, po wyświetleniu powiadomienia urządzenie MUSI używać ostatnio znanych ustawień lokalnych.

4.1.5. Usuwanie urządzenia z usługi

Jeśli urządzenie zostało usunięte z usługi (np. GCP), na urządzenie zostanie wysłane powiadomienie XMPP. Powiadomienie będzie miało następujący format:

<device_id>/delete

Po otrzymaniu takiego powiadomienia urządzenie MUSI połączyć się z serwerem, aby sprawdzić swój stan. Urządzenia Cloud Print MUSZĄ używać:

/cloudprint/printer?printerid=<printer_id>

Urządzenie MUSI otrzymać odpowiedź HTTP z wartością success=false i bez opisu urządzenia lub drukarki. Oznacza to, że urządzenie zostało usunięte z serwera i MUSI usunąć swoje dane logowania oraz przejść do domyślnych ustawień fabrycznych.

ZA KAŻDYM razem, gdy urządzenie otrzyma odpowiedź wskazującą, że zostało usunięte w wyniku wywołania interfejsu API /cloudprint/printer (podczas uruchamiania, powiadomienia o aktualizacji ustawień, codziennego pingowania), MUSI usunąć swoje dane logowania i przejść do trybu domyślnego.

4.2. /privet/info API

Interfejs API informacji jest OBOWIĄZKOWY i musi być zaimplementowany na każdym urządzeniu. Jest to żądanie HTTP GET dotyczące adresu URL „/privet/info”: GET /privet/info HTTP/1.1

Interfejs Info API zwraca podstawowe informacje o urządzeniu i obsługiwanych przez nie funkcjach. Ten interfejs API NIE MOŻE nigdy zmieniać stanu urządzenia ani wykonywać żadnych działań, ponieważ jest podatny na ataki XSRF. Jest to JEDYNY interfejs API, który może mieć pusty nagłówek „X-Privet-Token”. Klienci powinni wywoływać interfejs API /privet/info z nagłówkiem „X-Privet-Token” ustawionym na X-Privet-Token: „”

Interfejs API informacji MUSI zwracać dane zgodne z danymi dostępnymi w rekordzie TXT podczas wykrywania.

4.2.1. Dane wejściowe

Interfejs API /privet/info nie ma parametrów wejściowych.

4.2.2. Powrót

Interfejs API /privet/info zwraca podstawowe informacje o urządzeniu i obsługiwanych funkcjach.

Kolumna TXT wskazuje odpowiednie pole w rekordzie TXT DNS-SD.

Nazwa wartościTyp wartościOpisTXT
wersjaciąg znakówNajwyższa obsługiwana wersja interfejsu API (główna.pomocnicza), obecnie 1.0
nazwaciąg znakówCzytelna nazwa urządzenia.ty
opisciąg znaków(opcjonalnie) Opis urządzenia. POWINNO być modyfikowane przez użytkownika.notatka
URLciąg znakówAdres URL serwera, z którym komunikuje się to urządzenie. URL MUSI zawierać specyfikację protokołu, np. https://www.google.com/cloudprint.URL
typlista ciągów znaków,Lista obsługiwanych typów urządzeń.typ
idciąg znakówIdentyfikator urządzenia. Jeśli urządzenie nie zostało jeszcze zarejestrowane, pole jest puste. id
device_stateciąg znakówStan urządzenia.
idle oznacza, że urządzenie jest gotowe.
processing oznacza, że urządzenie jest zajęte i przez pewien czas jego funkcjonalność może być ograniczona.
stopped oznacza, że urządzenie nie działa i wymaga interwencji użytkownika.
connection_stateciąg znakówStan połączenia z serwerem (base_url):
online – połączenie jest dostępne;
offline – brak połączenia;
connecting – wykonywanie czynności początkowych;
not-configured – połączenie nie zostało jeszcze skonfigurowane;
Zarejestrowane urządzenie może zgłaszać stan połączenia na podstawie stanu kanału powiadomień (np. stan połączenia XMPP).
cs
producentciąg znakówNazwa producenta urządzenia
modelciąg znakówModel urządzenia
serial_numberciąg znakówUnikalny identyfikator urządzenia. W tej specyfikacji MUSI to być identyfikator UUID. (GCP 1.1 spec)
(opcjonalnie) Zdecydowanie zalecamy używanie tego samego identyfikatora numeru seryjnego wszędzie, aby różni klienci mogli identyfikować to samo urządzenie. Na przykład drukarki implementujące IPP mogą używać tego identyfikatora numeru seryjnego w polu „printer-device-id”.
oprogramowanie układowe,ciąg znakówWersja oprogramowania układowego urządzenia
czas działaniaintLiczba sekund od uruchomienia urządzenia.
setup_urlciąg znaków(opcjonalnie) Adres URL (wraz z protokołem) strony z instrukcjami konfiguracji
support_urlciąg znaków(opcjonalnie) Adres URL (wraz z protokołem) strony z informacjami o pomocy i najczęstszymi pytaniami.
update_urlciąg znaków(opcjonalnie) Adres URL (wraz z protokołem) strony z instrukcjami aktualizacji oprogramowania układowego
x-privet-tokenciąg znakówWartość nagłówka X-Privet-Token, która musi być przekazywana do wszystkich interfejsów API, aby zapobiegać atakom XSSI i XSRF. Więcej informacji znajdziesz w sekcji 6.1.
apiopis interfejsów API,Lista obsługiwanych interfejsów API (opisana poniżej)
semantic_stateJSON(opcjonalnie) Stan semantyczny urządzenia w formacie CloudDeviceState.

api – to lista JSON zawierająca listę interfejsów API dostępnych w sieci lokalnej. Pamiętaj, że nie wszystkie interfejsy API mogą być dostępne w tym samym czasie w sieci lokalnej. Na przykład nowo podłączone urządzenie powinno obsługiwać tylko interfejs API /register:

"api": [
        "/privet/register",
]
Po zakończeniu rejestracji urządzenie NIE POWINNO już obsługiwać interfejsu API /register. Urządzenie powinno też sprawdzić w usłudze, które interfejsy API mogą być udostępniane w sieci lokalnej. Na przykład:
"api": [
        "/privet/accesstoken",
        "/privet/capabilities",
        "/privet/printer/submitdoc",
]

Obecnie dostępne są te interfejsy API:

  • /privet/register – interfejs API do rejestracji urządzenia w sieci lokalnej. (szczegóły znajdziesz w sekcji /privet/register API). Ten interfejs API MUSI być ukryty po zarejestrowaniu urządzenia w chmurze.
  • /privet/accesstoken – interfejs API do wysyłania żądań tokena dostępu z urządzenia (szczegółowe informacje znajdziesz w sekcji /privet/accesstoken API).
  • /privet/capabilities – interfejs API do pobierania funkcji urządzenia (szczegółowe informacje znajdziesz w sekcji /privet/capabilities API).
  • /privet/printer/* – interfejs API specyficzny dla typu urządzenia „drukarka”. Szczegółowe informacje znajdziesz w sekcji interfejsów API specyficznych dla drukarki.
Oto przykład odpowiedzi /privet/info. (Zwróć uwagę na brak interfejsu API /privet/register, ponieważ to urządzenie jest już zarejestrowane):
{
        "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",
        ]
}
Oto przykład odpowiedzi /privet/info dla drukarki, w której skończył się atrament (zwróć uwagę na pole 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. Błędy

Interfejs API /privet/info powinien zwracać błąd TYLKO wtedy, gdy brakuje nagłówka X-Privet-Token. Musi to być błąd HTTP 400:

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

4.3. /privet/register API

Interfejs API /privet/register jest OPCJONALNY. Jest to żądanie POST HTTP. Interfejs API /privet/register MUSI sprawdzać, czy nagłówek X-Privet-Token jest prawidłowy. Urządzenie MUSI implementować ten interfejs API pod adresem 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

Urządzenie powinno udostępniać interfejs API /privet/register TYLKO wtedy, gdy zezwala na rejestrację anonimową. Na przykład:

  • Gdy urządzenie jest włączone (lub po kliknięciu specjalnego przycisku na urządzeniu) i nie zostało jeszcze zarejestrowane, powinno udostępniać interfejs API /privet/register, aby umożliwić użytkownikowi z sieci lokalnej przejęcie drukarki.
  • Po zakończeniu rejestracji urządzenie powinno przestać udostępniać interfejs API /privet/register, aby uniemożliwić innemu użytkownikowi w sieci lokalnej ponowne przejęcie urządzenia.
  • Niektóre urządzenia mogą mieć inne sposoby rejestracji i w ogóle nie powinny udostępniać interfejsu API /privet/register (np. łącznik Google Cloud Print).

Proces rejestracji składa się z 3 etapów (patrz anonimowa rejestracja w Cloud Print).

  1. Rozpocznij proces anonimowej rejestracji.
  2. Klient rozpoczyna ten proces, wywołując interfejs API /privet/register. Urządzenie może wtedy czekać na potwierdzenie użytkownika.
  3. Pobierz token roszczenia.

Klient wysyła zapytania, aby sprawdzić, kiedy urządzenie będzie gotowe do dalszego działania. Gdy urządzenie jest gotowe, wysyła żądanie do serwera, aby pobrać token rejestracji i adres URL rejestracji. Otrzymany token i adres URL POWINNY zostać zwrócone klientowi. Jeśli podczas tego etapu urządzenie otrzyma kolejną prośbę o rozpoczęcie rejestracji, powinno:

  • Jeśli jest to ten sam użytkownik, który rozpoczął rejestrację, odrzuć wszystkie poprzednie dane (jeśli takie istnieją) i rozpocznij nowy proces rejestracji.
  • Jeśli to inny użytkownik, zwróć błąd device_busy i 30-sekundowy limit czasu.

Przejdź przez proces rejestracji.

Po przejęciu urządzenia klient powinien powiadomić je o zakończeniu rejestracji. Po zakończeniu procesu rejestracji urządzenie powinno wysłać komunikat o aktualizacji, w tym nowo uzyskany identyfikator urządzenia.

Uwaga: gdy urządzenie przetwarza wywołanie interfejsu API /privet/register, nie można jednocześnie przetwarzać żadnych innych wywołań interfejsu API /privet/register. Urządzenie MUSI zwrócić błąd device_busy i przekroczyć 30-sekundowy limit czasu.

Zdecydowanie zalecamy potwierdzenie rejestracji przez użytkownika na urządzeniu. Jeśli ta funkcja jest zaimplementowana, urządzenie MUSI poczekać na potwierdzenie użytkownika PO otrzymaniu wywołania interfejsu API /privet/register?action=start. Klient będzie wywoływać interfejs API /privet/register?action=getClaimToken, aby sprawdzić, kiedy użytkownik potwierdzi rejestrację i kiedy będzie dostępny token roszczenia. Jeśli użytkownik anuluje rejestrację na urządzeniu (np. naciśnie przycisk Anuluj), musi zostać zwrócony błąd user_cancel. Jeśli użytkownik nie potwierdzi rejestracji w określonym czasie, MUSI zostać zwrócony błąd confirmation_timeout. Więcej informacji znajdziesz w sekcji dotyczącej wartości domyślnych.

4.3.1. Dane wejściowe

Interfejs API /privet/register ma te parametry wejściowe:
NazwaWartość
działanieMoże przyjmować jedną z tych wartości:
start – rozpoczęcie procesu rejestracji
getClaimToken – pobranie tokena roszczenia dla urządzenia
cancel – anulowanie procesu rejestracji
complete – zakończenie procesu rejestracji
użytkownikAdres e-mail użytkownika, który przejmie to urządzenie.

Urządzenie MUSI sprawdzać, czy adres e-mail we wszystkich działaniach (rozpoczęcie, getClaimToken, anulowanie, zakończenie) jest zgodny.

4.3.2. Powrót

Interfejs API /privet/register zwraca te dane:
Nazwa wartościTyp wartościOpis
działanieciąg znakówTakie samo działanie jak w parametrze wejściowym.
użytkownikciąg tekstowy (opcjonalnie)Ten sam użytkownik co w parametrze wejściowym (może go brakować, jeśli został pominięty w danych wejściowych).
tokenciąg tekstowy (opcjonalnie)Token rejestracji (obowiązkowy w przypadku odpowiedzi „getClaimToken”, pomijany w przypadku „start”, „complete” i „cancel”).
claim_urlciąg tekstowy (opcjonalnie)Adres URL rejestracji (obowiązkowy w przypadku odpowiedzi „getClaimToken”, pomijany w przypadku odpowiedzi „start”, „complete”, „cancel”). W przypadku drukarek w chmurze musi to być adres „complete_invite_url” otrzymany z serwera.
automated_claim_urlciąg tekstowy (opcjonalnie)Adres URL rejestracji (obowiązkowy w przypadku odpowiedzi „getClaimToken”, pomijany w przypadku odpowiedzi „start”, „complete”, „cancel”). W przypadku drukarek w chmurze musi to być adres URL „automated_invite_url” otrzymany z serwera.
device_idciąg tekstowy (opcjonalnie)Nowy identyfikator urządzenia (pominięty w przypadku odpowiedzi „start”, obowiązkowy w przypadku odpowiedzi „complete”).

Urządzenie MUSI zwracać swój identyfikator w odpowiedzi interfejsu /privet/info API TYLKO po zakończeniu rejestracji.

Przykład 1:

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

Przykład 2:

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

Przykład 3:

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

4.3.3. Błędy

Interfejs /privet/register API może zwrócić te błędy (szczegóły znajdziesz w sekcji Błędy):
BłądOpis
device_busyUrządzenie jest zajęte i nie może wykonać żądanego działania. Spróbuj ponownie po przekroczeniu limitu czasu.
pending_user_actionW odpowiedzi na „getClaimToken” ten błąd oznacza, że urządzenie nadal oczekuje na potwierdzenie przez użytkownika, a żądanie „getClaimToken” należy ponowić po upływie limitu czasu.
user_cancelUżytkownik wyraźnie anulował proces rejestracji na urządzeniu.
confirmation_timeoutUpłynął czas na potwierdzenie przez użytkownika.
invalid_actionWywołano nieprawidłową akcję. Na przykład, jeśli klient wywołał działanie=complete przed działaniem=start i działaniem=getClaimToken.
invalid_paramsW żądaniu podano nieprawidłowe parametry. (Nieznane parametry należy bezpiecznie ignorować ze względu na przyszłą zgodność). Na przykład zwróć tę wartość, jeśli klient wywołał działanie=nieznane lub użytkownik=.
device_config_errorData/godzina (lub inne ustawienia) na urządzeniu jest nieprawidłowa. Użytkownik musi przejść na wewnętrzną stronę urządzenia i skonfigurować jego ustawienia.
offlineUrządzenie jest obecnie w trybie offline i nie może komunikować się z serwerem.
server_errorBłąd serwera podczas procesu rejestracji.
invalid_x_privet_tokenW żądaniu brakuje nagłówka X-Privet-Token lub jest on nieprawidłowy.

Po pomyślnym zakończeniu rejestracji urządzenie MUSI przestać udostępniać interfejs API /privet/register. Jeśli urządzenie nie udostępnia interfejsu API /privet/register, MUSI zwrócić błąd HTTP 404. Dlatego jeśli urządzenie jest już zarejestrowane, wywołanie tego interfejsu API MUSI zwrócić kod stanu 404. Jeśli brakuje nagłówka X-Privet-Token, urządzenie MUSI zwrócić błąd HTTP 400.

4.4. Interfejs API /privet/accesstoken

Interfejs API /privet/accesstoken jest OPCJONALNY. Jest to żądanie HTTP GET. Interfejs API /privet/accesstoken MUSI sprawdzać, czy nagłówek „X-Privet-Token” jest prawidłowy. Urządzenie MUSI implementować ten interfejs API pod adresem URL „/privet/accesstoken”:
GET /privet/accesstoken HTTP/1.1

Gdy urządzenie otrzyma wywołanie interfejsu API /accesstoken, powinno wywołać serwer, aby pobrać token dostępu dla danego użytkownika, i zwrócić go do klienta. Klient użyje następnie tokena dostępu, aby uzyskać dostęp do tego urządzenia przez chmurę.

Urządzenia Cloud Print MUSZĄ wywoływać ten interfejs API:

/cloudprint/proximitytoken
i przekaż parametry „printerid=<printer_id>” i „user” z lokalnego interfejsu API. Jeśli operacja się uda, odpowiedź serwera będzie zawierać ten obiekt:
"proximity_token": {
        "user": "user@domain.com",
        "token": "AAA111222333444555666777",
        "expires_in": 600
}
Urządzenia Cloud Print MUSZĄ przekazywać wartość obiektu „proximity_token” w odpowiedzi do lokalnych wywołań interfejsu API /privet/accesstoken. Bardziej korzystne (przyszłościowe) jest, jeśli urządzenie może przekazywać WSZYSTKIE parametry (w tym te, które nie są opisane w tej specyfikacji).

4.4.1. Dane wejściowe

Interfejs API /privet/accesstoken ma te parametry wejściowe:
NazwaWartość
użytkownikAdres e-mail użytkownika, który zamierzał użyć tego tokena dostępu. Może być pusta w żądaniu.

4.4.2. Powrót

Interfejs API /privet/accesstoken zwraca te dane:
Nazwa wartościTyp wartościOpis
tokenciąg znakówToken dostępu zwrócony przez serwer
użytkownikciąg znakówTen sam użytkownik co w parametrze wejściowym.
expires_inintLiczba sekund do wygaśnięcia tego tokena. otrzymane z serwera i przekazane w tej odpowiedzi.

Przykład:

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

4.4.3. Błędy

Interfejs /privet/accesstoken API może zwrócić te błędy (szczegóły znajdziesz w sekcji Błędy):
BłądOpis
offlineUrządzenie jest obecnie w trybie offline i nie może komunikować się z serwerem.
access_deniedNiewystarczające uprawnienia. Odmowa dostępu. Urządzenie powinno zwracać ten błąd, gdy serwer wyraźnie odrzuci żądanie.
invalid_paramsW żądaniu podano nieprawidłowe parametry. (Nieznane parametry należy bezpiecznie ignorować ze względu na przyszłą zgodność). Na przykład jeśli klient wywołał adres /accesstoken?user= lub /accesstoken.
server_errorBłąd serwera.
invalid_x_privet_tokenW żądaniu token X-Privet-Token jest nieprawidłowy lub pusty.

Jeśli urządzenie nie udostępnia interfejsu API /privet/accesstoken, MUSI zwrócić błąd HTTP 404. Jeśli brakuje nagłówka X-Privet-Token, urządzenie MUSI zwrócić błąd HTTP 400.

4.5. Interfejs API /privet/capabilities

Interfejs API /privet/capabilities jest OPCJONALNY. Jest to żądanie HTTP GET. Interfejs API /privet/capabilities MUSI sprawdzać, czy nagłówek „X-Privet-Token” jest prawidłowy. Urządzenie MUSI implementować ten interfejs API pod adresem URL „/privet/capabilities”:
GET /privet/capabilities HTTP/1.1
Gdy urządzenie otrzyma wywołanie interfejsu API /capabilities, powinno skontaktować się z serwerem, aby uzyskać zaktualizowane możliwości. Jeśli na przykład drukarka obsługuje wysyłanie zadania drukowania (otrzymanego lokalnie) do siebie za pomocą usługi Cloud Print, powinna zwracać możliwości, które zwracałaby usługa Cloud Print. W tym przypadku Cloud Print może zmienić oryginalne możliwości drukarki, dodając nowe funkcje, które może wykonać przed wysłaniem zadania do drukarki. Najczęstszym przypadkiem jest lista obsługiwanych typów dokumentów. Jeśli drukarka jest offline, powinna zwrócić typy dokumentów, które obsługuje. Jeśli jednak drukarka jest online i zarejestrowana w Cloud Print, MUSI zwrócić „*/*” jako jeden z obsługiwanych typów. W takim przypadku usługa Cloud Print przeprowadzi niezbędną konwersję. W przypadku drukowania offline drukarka MUSI obsługiwać co najmniej format „image/pwg-raster”.

4.5.1. Dane wejściowe

Interfejs API /privet/capabilities ma te parametry wejściowe:
NazwaWartość
offline(opcjonalnie) Może mieć tylko wartość „offline=1”. W takim przypadku urządzenie powinno zwrócić możliwości korzystania z niego w trybie offline (jeśli różnią się od możliwości w trybie online).

4.5.2. Powrót

Interfejs API /privet/capabilities zwraca możliwości urządzenia w formacie JSON opisu urządzenia w chmurze (CDD) (szczegółowe informacje znajdziesz w dokumencie CDD). Drukarki MUSZĄ zwracać co najmniej listę obsługiwanych typów. Na przykład drukarka gotowa do pracy w chmurze, która jest obecnie online, może zwrócić (co najmniej) taki wynik:
{
        "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": "*/*" }
                ]
        }
}
Gdy urządzenie jest odłączone od serwera, może zwrócić:
{
        "version": "1.0",
        "printer": {
                "supported_content_type": [
                        {
                                "content_type": "application/pdf",
                                "min_version": "1.4"
                        },
                        { "content_type": "image/pwg-raster" },
                        { "content_type": "image/jpeg" }
                ]
        }
}

Uwaga: drukarki określają priorytet obsługiwanych typów treści za pomocą kolejności. Na przykład w powyższych przykładach drukarka określa, że preferuje dane w formacie „application/pdf” od formatów „image/pwg-raster” i „image/jpeg”. Klienci powinni w miarę możliwości uwzględniać priorytetyzację drukarki (szczegóły znajdziesz w dokumencie CDD).

4.5.3. Błędy

Interfejs /privet/capabilities API może zwracać te błędy (szczegóły znajdziesz w sekcji Błędy):
BłądOpis
invalid_x_privet_tokenW żądaniu brakuje nagłówka X-Privet-Token lub jest on nieprawidłowy.

Jeśli urządzenie nie udostępnia interfejsu API /privet/capabilities, MUSI zwrócić błąd HTTP 404. Jeśli brakuje nagłówka X-Privet-Token, urządzenie MUSI zwrócić błąd HTTP 400.

4.6. Błędy

Błędy są zwracane z powyższych interfejsów API w tym formacie:
Nazwa wartościTyp wartościOpis
błądciąg znakówTyp błędu (zdefiniowany dla każdego interfejsu API)
opisciąg tekstowy (opcjonalnie)Zrozumiały dla człowieka opis błędu.
server_apiciąg tekstowy (opcjonalnie)W przypadku błędu serwera to pole zawiera interfejs API serwera, który uległ awarii.
server_codeint (opcjonalnie)W przypadku błędu serwera to pole zawiera kod błędu zwrócony przez serwer.
server_http_codeint (opcjonalnie)W przypadku błędu HTTP serwera to pole zawiera kod błędu HTTP zwrócony przez serwer.
czas oczekiwaniaint (opcjonalnie)Liczba sekund, przez które klient ma czekać przed ponowną próbą (tylko w przypadku błędów, które można naprawić). Klient MUSI losowo wybrać rzeczywisty czas oczekiwania z tego zakresu, tak aby był o 20% większy.

Wszystkie interfejsy API MUSZĄ zwracać błąd HTTP 400, jeśli brakuje nagłówka X-Privet-Token.

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

Przykład 1:

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

Przykład 2:

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

5. Printer API

Jednym z typów urządzeń obsługiwanych przez ten protokół jest drukarka. Urządzenia obsługujące ten typ MOGĄ implementować niektóre funkcje specyficzne dla drukarek. Najlepiej, aby drukowanie na drukarkach działających w chmurze odbywało się za pomocą serwera Cloud Print:

W niektórych przypadkach klient może potrzebować wysłać dokument lokalnie. Może być potrzebny, gdy klient nie ma identyfikatora Google lub nie może komunikować się z serwerem Cloud Print. W takim przypadku zadanie drukowania zostanie przesłane lokalnie do drukarki. Drukarka będzie z kolei korzystać z usługi Cloud Print do kolejkowania i konwersji zadań. Drukarka ponownie opublikuje zadanie przesłane lokalnie w usłudze Cloud Print, a następnie wyśle żądanie jego wykonania, ponieważ zostało ono przesłane przez chmurę. Ten proces zapewni elastyczność w zakresie warunków korzystania z usługi (konwersji) oraz zarządzania zadaniami drukowania i ich śledzenia.

Usługa Cloud Print implementuje konwersję, więc drukarka POWINNA reklamować obsługę wszystkich formatów wejściowych („*/*”) na liście obsługiwanych typów treści:

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

W niektórych przypadkach pożądane jest rozwiązanie całkowicie offline. Drukarki obsługują ograniczoną liczbę formatów wejściowych, więc klient musi przekonwertować dokumenty na kilka formatów natywnie obsługiwanych przez drukarkę.

Ta specyfikacja WYMAGA, aby wszystkie drukarki obsługiwały co najmniej format PWG Raster („image/pwg-raster”) w przypadku drukowania offline. Drukarka może obsługiwać inne formaty (np. JPEG), a jeśli klient je obsługuje, może wysyłać dokumenty w tym formacie. Drukarka MUSI udostępniać obsługiwane typy za pomocą interfejsu API /capabilities, np.:

{
        "version": "1.0",
        "printer": {
                "supported_content_type": [
                        { "content_type": "image/pwg-raster" },
                        { "content_type": "image/jpeg" }
                ]
        }
}
Klient może rozpocząć drukowanie w sieci lokalnej na 2 sposoby.

Proste drukowanie – klient wysyła dokument przez sieć lokalną do interfejsu API /submitdoc (bez określania parametru job_id). Przesłany dokument zostanie wydrukowany przy użyciu domyślnych ustawień biletu drukowania i nie są potrzebne żadne stany zadania drukowania. Jeśli drukarka obsługuje TYLKO ten typ drukowania, MUSI reklamować TYLKO interfejs API /submitdoc w odpowiedzi interfejsu API /privet/info.

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

Drukowanie zaawansowane – klient powinien najpierw utworzyć zadanie drukowania na drukarce, wywołując interfejs API /privet/printer/createjob z prawidłowym biletem zadania CJT w żądaniu. Drukarka MUSI zapisać bilet wydruku w pamięci i zwrócić identyfikator zadania do klienta. Następnie klient wywoła interfejs API /printer/submitdoc i określi wcześniej otrzymany job_id. W tym momencie drukarka rozpocznie drukowanie. Klient będzie odpytywać drukarkę o stan zadania drukowania, wywołując interfejs API /privet/printer/jobstate.

W środowisku z wieloma klientami nie ma gwarancji, jak ten interfejs API jest wywoływany. Jeden klient może wywołać /createjob między wywołaniami /createjob->/submitdoc innego klienta. Aby wyeliminować możliwe zakleszczenia i zwiększyć użyteczność, zalecamy utworzenie na drukarce małej kolejki oczekujących zadań drukowania (co najmniej 3–5):

  • /createjob zajmuje pierwsze dostępne miejsce w kolejce.
  • Czas życia zadania (w kolejce) wynosi co najmniej 5 minut.
  • Jeśli wszystkie miejsca w kolejce są zajęte, najstarsze zadanie drukowania, które nie zostało jeszcze wydrukowane, zostanie usunięte, a na jego miejsce zostanie wstawione nowe.
  • Jeśli na urządzeniu jest obecnie drukowane zadanie (drukowanie proste lub zaawansowane), /submitdoc powinno zwrócić stan zajętości i zaproponować limit czasu na ponowienie próby tego zadania drukowania.
  • Jeśli /submitdoc odnosi się do zadania, które zostało usunięte z kolejki (z powodu zastąpienia lub przekroczenia limitu czasu), drukarka powinna zwrócić błąd invalid_print_job, a klient ponowi próbę od kroku /createjob. Klient MUSI odczekać losowy okres do 5 sekund, zanim spróbuje ponownie.

Jeśli ograniczenia pamięci uniemożliwiają przechowywanie na urządzeniu wielu oczekujących zadań, kolejka może zawierać tylko 1 zadanie drukowania. Nadal powinien on być zgodny z protokołem opisanym powyżej. Po zakończeniu zadania lub niepowodzeniu z powodu błędu drukarka powinna przechowywać informacje o stanie zadania przez co najmniej 5 minut. Rozmiar kolejki do przechowywania stanów ukończonych zadań powinien wynosić co najmniej 10. Jeśli trzeba zapisać więcej stanów zadań, najstarszy z nich może zostać usunięty z kolejki przed upływem 5-minutowego limitu czasu.

Uwaga: na razie klienci będą odpytywać o stan zadania. W przyszłości możemy wymagać, aby drukarka wysyłała powiadomienie DNS TXT, gdy zmieni się stan DOWOLNEGO zadania drukowania.

5.1. /privet/printer/createjob API

Interfejs API /privet/printer/createjob jest OPCJONALNY (patrz sekcja Proste drukowanie powyżej). Jest to żądanie HTTP POST. Interfejs API /privet/printer/createjob MUSI sprawdzać, czy nagłówek „X-Privet-Token” jest prawidłowy. Urządzenie MUSI implementować ten interfejs API pod adresem URL „/privet/printer/createjob”:

POST /privet/printer/createjob HTTP/1.1
Po otrzymaniu wywołania interfejsu API /privet/printer/createjob drukarka MUSI utworzyć nowy identyfikator zadania drukowania, zapisać otrzymany bilet drukowania w formacie CJT i zwrócić identyfikator zadania drukowania do klienta.

5.1.1. Dane wejściowe

Interfejs API /privet/printer/createjob nie ma parametrów wejściowych w adresie URL. Treść żądania powinna zawierać dane zlecenia drukowania w formacie CJT.

5.1.2. Powrót

Interfejs API /privet/printer/createjob zwraca te dane:
Nazwa wartościTyp wartościOpis
job_idciąg znakówIdentyfikator nowo utworzonego zadania drukowania.
expires_inintLiczba sekund, przez które to zadanie drukowania jest ważne.

Przykład:

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

5.1.3. Błędy

Interfejs /privet/printer/createjob API może zwracać te błędy (szczegółowe informacje znajdziesz w sekcji Błędy):
BłądOpis
invalid_ticketPrzesłany bilet drukowania jest nieprawidłowy.
printer_busyDrukarka jest zajęta i nie może obecnie przetworzyć żądania /createjob. Spróbuj ponownie po przekroczeniu limitu czasu.
printer_errorDrukarka jest w stanie błędu i wymaga interakcji użytkownika, aby go naprawić. Opis powinien zawierać bardziej szczegółowe wyjaśnienie (np. „Zacięcie papieru w podajniku 1”).
invalid_x_privet_tokenW żądaniu brakuje nagłówka X-Privet-Token lub jest on nieprawidłowy.

Jeśli urządzenie nie udostępnia interfejsu /privet/printer/createjob, MUSI zwrócić błąd HTTP 404. Jeśli brakuje nagłówka X-Privet-Token, urządzenie MUSI zwrócić błąd HTTP 400.

5.2. /privet/printer/submitdoc API

Interfejs /privet/printer/submitdoc API jest WYMAGANY do wdrożenia drukowania w sieci lokalnej (offline lub przekazywania do Cloud Print). Jest to żądanie POST HTTP. Interfejs API /privet/printer/submitdoc MUSI sprawdzać, czy nagłówek „X-Privet-Token” jest prawidłowy. Urządzenie MUSI implementować ten interfejs API pod adresem URL „/privet/printer/submitdoc”:
POST /privet/printer/submitdoc HTTP/1.1
Po otrzymaniu wywołania interfejsu API /privet/printer/submitdoc drukarka powinna rozpocząć drukowanie. Jeśli nie może rozpocząć drukowania, MUSI zwrócić błąd printer_busy i zalecany czas oczekiwania, po którym klient może ponownie spróbować.

Jeśli drukarka nie jest w stanie pomieścić wszystkich danych w wewnętrznym buforze, POWINNA używać mechanizmów TCP, aby spowolnić przesyłanie danych do momentu wydrukowania części dokumentu i ponownego udostępnienia części bufora. (Na przykład drukarka może ustawić windowsize=0 w warstwach TCP, co spowoduje, że klient będzie czekać).

Przesłanie dokumentu do drukarki może zająć sporo czasu. Klient powinien mieć możliwość sprawdzenia stanu drukarki i zadania (drukowanie zaawansowane) podczas drukowania. Aby to zrobić, drukarka MUSI zezwalać klientowi na wywoływanie interfejsów API /privet/info i /privet/printer/jobstate podczas przetwarzania wywołań interfejsu API /privet/printer/submitdoc. Zalecamy, aby wszyscy klienci rozpoczynali nowy wątek w celu wykonania wywołania interfejsu API /privet/printer/submitdoc, aby główny wątek mógł używać interfejsów API /privet/info i /privet/printer/jobstate do sprawdzania stanu drukarki i zadań.

Uwaga: po zakończeniu lub przerwaniu lokalnego zadania drukowania zdecydowanie zalecamy (w przyszłej wersji tej specyfikacji będzie to wymagane) zgłoszenie stanu końcowego zadania do interfejsu /cloudprint/submit w celu rozliczenia i poprawy komfortu użytkownika. Wymagane są parametry „printerid”, „title”, „contentType” i „final_semantic_state” (w formacie PrintJobState) oraz parametry „tag” (powtarzany parametr) i „ticket” (bilet zadania w formacie CloudJobTicket). Pamiętaj, że podany stan PrintJobState musi być ostateczny, tzn. jego typ musi mieć wartość DONE lub ABORTED, a w przypadku wartości ABORTED należy podać przyczynę (szczegółowe informacje znajdziesz w sekcji JobState). Pamiętaj też, że to użycie interfejsu /cloudprint/submit do zgłaszania lokalnych zadań drukowania nie jest wymienione w jego specyfikacji, ponieważ ta sekcja ma opisywać główne zastosowanie interfejsu: przesyłanie zadania drukowania z dokumentem do wydrukowania podanym w parametrze „content”.

5.2.1. Dane wejściowe

Interfejs API /privet/printer/submitdoc ma te parametry wejściowe:
NazwaWartość
job_id(opcjonalnie) Identyfikator zadania drukowania. Można pominąć w przypadku prostego drukowania (patrz wyżej). Musi być zgodny z wartością zwróconą przez drukarkę.
user_name(opcjonalnie) Nazwa użytkownika czytelna dla człowieka. Nie jest to ostateczna wartość i należy jej używać tylko w przypadku adnotacji dotyczących zadań drukowania. Jeśli zadanie zostanie ponownie opublikowane w usłudze Cloud Print, ten ciąg znaków powinien zostać dołączony do zadania Cloud Print.
client_name(opcjonalnie) Nazwa aplikacji klienckiej, która wysyła to żądanie. Tylko do wyświetlania. Jeśli zadanie zostanie ponownie opublikowane w usłudze Cloud Print, ten ciąg znaków powinien zostać dołączony do zadania Cloud Print.
job_name(opcjonalnie) Nazwa zadania drukowania, które ma zostać zarejestrowane. Jeśli zadanie zostanie ponownie opublikowane w usłudze Cloud Print, ten ciąg znaków powinien zostać dołączony do zadania Cloud Print.
offline(opcjonalnie) Może mieć tylko wartość „offline=1”. W takim przypadku drukarka powinna spróbować drukować tylko w trybie offline (bez ponownego wysyłania do serwera Cloud Print).

Treść żądania powinna zawierać prawidłowy dokument do wydrukowania. Pole „Content-Length” powinno zawierać prawidłową długość żądania. Nagłówek „Content-Type” powinien być ustawiony na typ MIME dokumentu i pasować do jednego z typów w CDD (chyba że CDD określa „*/*”).

Zdecydowanie zalecamy, aby klienci podawali w tej prośbie prawidłową nazwę użytkownika (lub adres e-mail), nazwę klienta i nazwę zadania. Te pola są używane tylko w interfejsach, aby zwiększyć wygodę użytkowników.

5.2.2. Powrót

Interfejs API /privet/printer/submitdoc zwraca te dane:
Nazwa wartościTyp wartościOpis
job_idciąg znakówIdentyfikator nowo utworzonego zadania drukowania (proste drukowanie) lub identyfikator zadania podany w żądaniu (zaawansowane drukowanie).
expires_inintLiczba sekund, przez które to zadanie drukowania jest ważne.
job_typeciąg znakówTyp treści przesłanego dokumentu.
job_sizeint 64-bitowyRozmiar danych wydruku w bajtach.
job_nameciąg znaków(opcjonalnie) Taka sama nazwa zadania jak w danych wejściowych (jeśli występuje).

Przykład:

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

5.2.3. Błędy

Interfejs API /privet/printer/submitdoc może zwracać te błędy (szczegółowe informacje znajdziesz w sekcji Błędy):
BłądOpis
invalid_print_jobW żądaniu podano nieprawidłowy lub wygasły identyfikator zadania. Ponów próbę po przekroczeniu limitu czasu.
invalid_document_typeDrukarka nie obsługuje typu MIME dokumentu.
invalid_documentPrzesłany dokument jest nieprawidłowy.
document_too_largeDokument przekracza maksymalny dozwolony rozmiar.
printer_busyDrukarka jest zajęta i nie może obecnie przetworzyć dokumentu. Spróbuj ponownie po przekroczeniu limitu czasu.
printer_errorDrukarka jest w stanie błędu i wymaga interakcji użytkownika, aby go naprawić. Opis powinien zawierać bardziej szczegółowe wyjaśnienie (np. „Zacięcie papieru w podajniku 1”).
invalid_paramsW żądaniu podano nieprawidłowe parametry. (Nieznane parametry należy bezpiecznie ignorować ze względu na przyszłą zgodność)
user_cancelUżytkownik anulował proces drukowania na urządzeniu.
server_errorNie udało się opublikować dokumentu w Cloud Print.
invalid_x_privet_tokenW żądaniu brakuje nagłówka X-Privet-Token lub jest on nieprawidłowy.

Jeśli urządzenie nie udostępnia adresu /privet/printer/submitdoc, MUSI zwrócić błąd HTTP 404. Jeśli brakuje nagłówka X-Privet-Token, urządzenie MUSI zwrócić błąd HTTP 400.

Uwaga: interfejs API /privet/printer/submitdoc może wymagać specjalnej obsługi po stronie drukarki (ze względu na duży rozmiar dołączonego ładunku). W niektórych przypadkach (zależnych od implementacji serwera HTTP drukarki i platformy) drukarka może zamknąć gniazdo PRZED zwróceniem błędu HTTP. W innych przypadkach drukarka może zwrócić błąd 503 (zamiast błędu Privet). Drukarki POWINNY w miarę możliwości zwracać wartość Privet. Każdy klient implementujący specyfikację Privet powinien jednak obsługiwać zamknięcie gniazda (bez błędu HTTP) i błędy HTTP 503 w przypadku interfejsu API /privet/printer/submitdoc. W takim przypadku klient powinien traktować to jako błąd prywatny „printer_busy” z parametrem „timeout” ustawionym na 15 sekund. Aby uniknąć nieskończonych ponownych prób, klient może przestać ponawiać próby po rozsądnej liczbie prób (np. 3).

5.3. /privet/printer/jobstate API

Interfejs /privet/printer/jobstate API jest OPCJONALNY (patrz Proste drukowanie powyżej). Jest to żądanie HTTP GET. Interfejs API /privet/printer/jobstate MUSI sprawdzać, czy nagłówek „X-Privet-Token” jest prawidłowy. Urządzenie MUSI implementować ten interfejs API pod adresem URL „/privet/printer/jobstate”:
GET /privet/printer/jobstate HTTP/1.1
Po otrzymaniu wywołania interfejsu API /privet/printer/jobstate drukarka powinna zwrócić stan żądanego zadania drukowania lub błąd invalid_print_job.

5.3.1. Dane wejściowe

Interfejs API /privet/printer/jobstate ma te parametry wejściowe:
NazwaWartość
job_idIdentyfikator zadania drukowania, dla którego chcesz zwrócić stan.

5.3.2. Powrót

Interfejs API /privet/printer/jobstate zwraca te dane:
Nazwa wartościTyp wartościOpis
job_idciąg znakówIdentyfikator zadania drukowania, którego dotyczą informacje o stanie.
stanciąg znakówdraft – zadanie drukowania zostało utworzone na urządzeniu (nie otrzymano jeszcze wywołań /privet/printer/submitdoc).
queued – zadanie drukowania zostało odebrane i umieszczone w kolejce, ale drukowanie jeszcze się nie rozpoczęło.
in_progress – zadanie drukowania jest w trakcie drukowania.
zatrzymano – zadanie drukowania zostało wstrzymane, ale można je ponownie uruchomić ręcznie lub automatycznie.
done – zadanie drukowania zostało wykonane.
Przerwano – nie udało się wykonać zadania drukowania.
opisciąg znaków(opcjonalnie) Opis stanu zadania drukowania zrozumiały dla człowieka. Powinny zawierać dodatkowe informacje, jeśli state jest stopped lub aborted. Pole semantic_state zwykle zawiera lepszy i bardziej znaczący opis dla klienta.
expires_inintLiczba sekund, przez które to zadanie drukowania jest ważne.
job_typeciąg znaków(Opcjonalnie) Typ treści przesłanego dokumentu.
job_sizeint 64-bitowy(opcjonalnie) Rozmiar danych wydruku w bajtach.
job_nameciąg znaków(opcjonalnie) Taka sama nazwa zadania jak w danych wejściowych (jeśli występuje).
server_job_idciąg znaków(opcjonalnie) Identyfikator zadania zwrócony przez serwer (jeśli zadanie zostało opublikowane w usłudze Cloud Print). Pominięte w przypadku drukowania offline.
semantic_stateJSON(opcjonalnie) Stan semantyczny zadania w formacie PrintJobState.

Przykład (drukowanie przez raportowanie za pomocą 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"
}

Przykład (błąd drukowania offline):

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

Przykład (zadanie drukowania przerwane przez użytkownika):

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

Przykład (zadanie drukowania zostało zatrzymane z powodu braku papieru). Zwróć uwagę na odniesienie do stanu urządzenia. Klient musi wywołać interfejs API /privet/info, aby uzyskać więcej informacji o stanie urządzenia:

{
        "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. Błędy

Interfejs /privet/printer/jobstate API może zwrócić te błędy (szczegóły znajdziesz w sekcji Błędy):
BłądOpis
invalid_print_jobŻądanie zawiera nieprawidłowy lub wygasły identyfikator zadania.
server_errorNie udało się uzyskać stanu zadania drukowania (w przypadku zadań drukowania opublikowanych w Cloud Print).
invalid_x_privet_tokenW żądaniu brakuje nagłówka X-Privet-Token lub jest on nieprawidłowy.

Jeśli urządzenie nie udostępnia adresu /privet/printer/jobstate, MUSI zwrócić błąd HTTP 404. Jeśli brakuje nagłówka X-Privet-Token, urządzenie MUSI zwrócić błąd HTTP 400.

6. Dodatek

6.1. Domyślne działanie i ustawienia

W tej sekcji wyjaśnimy domyślne zachowanie, którego oczekujemy od WSZYSTKICH urządzeń zgodnych z Privet.
  • Urządzenia po wyjęciu z pudełka powinny obsługiwać tylko interfejsy API /privet/info/privet/register. Wszystkie inne interfejsy API (np. /privet/accesstoken, drukowanie lokalne) powinny być wyłączone.
  • Rejestracja wymaga fizycznego kontaktu z urządzeniem.
    • Użytkownik MUSI wykonać fizyczne działanie na urządzeniu (np. nacisnąć przycisk), aby potwierdzić dostęp do urządzenia.
    • Gdy użytkownik wykona opisaną powyżej czynność, drukarka powinna wysłać żądanie /cloudprint/register. Nie powinien wysyłać tego żądania, dopóki nie zostanie podjęte działanie (patrz diagram sekwencji 1).
    • Jeśli urządzenie przetwarza żądanie /privet/register (np. oczekuje na działanie opisane powyżej), musi odrzucić wszystkie inne żądania /privet/register. W takim przypadku urządzenie MUSI zwrócić błąd device_busy.
    • Urządzenie powinno przekroczyć limit czasu dla każdego żądania /register, które nie otrzyma opisanego powyżej działania fizycznego w ciągu 60 sekund. W takim przypadku urządzenie MUSI zwrócić błąd confirmation_timeout.
    • Opcjonalne: zalecane, ale nie wymagane. Poniższe elementy mogą poprawić wygodę użytkowników:
      • Drukarka może migać światłem lub wyświetlać komunikat na ekranie, aby poinformować użytkownika, że musi podjąć działanie w celu potwierdzenia rejestracji.
      • Na ekranie drukarki może pojawić się komunikat „Rejestracja w Google Cloud Print dla użytkownika „abc@def.com” – naciśnij OK, aby kontynuować”, gdzie abc@def.com to parametr użytkownika z wywołania interfejsu API /register. Dzięki temu użytkownik będzie miał pewność, że:
        • potwierdzają swoją prośbę o rejestrację;
        • co się dzieje, jeśli nie wywołał(-a) prośby.
      • Oprócz fizycznego działania potwierdzającego na drukarce (np. „Naciśnij przycisk OK”), drukarka może też udostępnić użytkownikowi przycisk anulowania żądania (np. „Naciśnij Anuluj, aby odrzucić”). Umożliwi to użytkownikom, którzy nie zainicjowali prośby o rejestrację, anulowanie jej przed upływem 60-sekundowego limitu czasu. W takim przypadku urządzenie MUSI zwrócić błąd user_cancel.
  • Przeniesienia własności:
    • Urządzenie może zostać wyraźnie usunięte z usługi w chmurze.
      • Jeśli urządzenie otrzyma odpowiedź o sukcesie, ale w wyniku wywołania /cloudprint/printer (w przypadku GCP) nie otrzyma opisu urządzenia, MUSI wrócić do trybu domyślnego (fabrycznego).
      • Jeśli dane logowania urządzenia przestaną działać (wyraźnie z powodu odpowiedzi serwera „nieprawidłowe dane logowania”), urządzenie MUSI wrócić do domyślnego trybu (po wyjęciu z pudełka).
    • Lokalne przywrócenie ustawień fabrycznych MUSI wyczyścić dane logowania urządzenia i przywrócić je do stanu domyślnego.
    • Opcjonalnie: urządzenie może udostępniać element menu umożliwiający wyczyszczenie danych logowania i przejście do trybu domyślnego.
  • Urządzenia obsługujące powiadomienia XMPP MUSZĄ mieć możliwość pingowania serwera. Limit czasu pingowania MUSI być kontrolowany przez serwer za pomocą parametru „local_settings”.
  • Aby zapewnić synchronizację, urządzenie może wysyłać pingi do serwera (interfejs API /cloudprint/printer w przypadku GCP, a także pingi XMPP) nie częściej niż raz dziennie (co 24 godziny). Zalecamy losowe określanie okna sprawdzania w przedziale 24–32 godzin.
  • Opcjonalnie: w przypadku urządzeń Cloud Print zalecamy, ale nie wymagamy, aby użytkownik miał możliwość ręcznego (za pomocą przycisku) sprawdzania, czy na urządzeniu nie ma nowych zadań drukowania. Niektóre drukarki mają już tę funkcję.
  • Opcjonalnie. Drukarki dla firm mogą mieć opcję całkowitego wyłączenia lokalnego wykrywania. W takim przypadku urządzenie MUSI zaktualizować te ustawienia lokalne na serwerze. Nowe ustawienia lokalne MUSZĄ być puste (ustawienie „local_discovery” na „false” oznacza, że można je ponownie włączyć w usłudze GCP).

6.1.2 Domyślny diagram rejestracji

6.2. Ataki XSSI i XSRF oraz zapobieganie im

W tej sekcji wyjaśnimy, jak urządzenie może być narażone na ataki typu XSSI i XSRF oraz jak się przed nimi chronić (w tym techniki generowania tokenów).
Więcej informacji znajdziesz tutaj: http://googleonlinesecurity.blogspot.com/2011/05/website-security-for-webmasters.html
Ataki XSSI i XSRF są zwykle możliwe, gdy witryna korzysta z mechanizmów uwierzytelniania za pomocą plików cookie. Usługa Cloud Print Google nie używa plików cookie, ale takie ataki są nadal możliwe. Dostęp przez sieć lokalną z założenia domyślnie ufa żądaniom.

6.2.1. XSSI

Złośliwa witryna może odgadnąć adres IP i numer portu urządzenia zgodnego z Privet i spróbować wywołać interfejs Privet API za pomocą „src=<nazwa interfejsu API>” w tagu <script>:
<script type="text/javascript" src="http://192.168.1.42:8080/privet/info"></script>
Bez ochrony złośliwe witryny mogłyby wykonywać wywołania interfejsu API i uzyskiwać dostęp do wyników.
Aby zapobiec tego typu atakom, WSZYSTKIE wywołania interfejsu API Privet MUSZĄ wymagać nagłówka „X-Privet-Token” w żądaniu. Tagi skryptu „src=<api>” nie mogą dodawać nagłówków, co skutecznie chroni przed tego typu atakami.

6.2.2. XSRF

http://en.wikipedia.org/wiki/Cross-site_request_forgery
Złośliwa strona internetowa może odgadnąć adres IP i numer portu urządzenia zgodnego z Privet i spróbować wywołać interfejs Privet API za pomocą elementu <iframe>, formularzy lub innego mechanizmu ładowania między witrynami. Osoby atakujące nie będą miały dostępu do wyników żądania, ale jeśli żądanie spowoduje wykonanie działania (np. drukowania), będą mogły je wywołać.

Aby zapobiec temu atakowi, wymagamy następującej ochrony:

  • Pozostawienie interfejsu API /privet/info otwartego na XSRF
  • Interfejs API /privet/info NIE MOŻE wykonywać żadnych działań na urządzeniu.
  • Użyj interfejsu API /privet/info, aby otrzymać x-privet-token
  • Wszystkie inne interfejsy API MUSZĄ sprawdzać, czy w nagłówku „X-Privet-Token” znajduje się prawidłowy token x-privet-token.
  • x-privet-token powinien być ważny tylko przez 24 godziny.

Nawet jeśli atakujący zdoła wykonać wywołanie interfejsu API /privet/info, nie będzie mógł odczytać tokena x-privet-token z odpowiedzi, a tym samym nie będzie mógł wywołać żadnego innego interfejsu API.

Zdecydowanie zalecamy wygenerowanie tokena XSRF za pomocą tego algorytmu:

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

Elementy generowania tokena XSRF:

  • DELIMITER to znak specjalny, zwykle „:”.
  • issue_timecounter to liczba sekund od jakiegoś zdarzenia (epoki sygnatury czasowej) lub czasu uruchomienia urządzenia (w przypadku liczników procesora). Wartość issue_timecounter stale rośnie, gdy urządzenie jest włączone i działa (patrz weryfikacja tokena poniżej).
  • SHA1 – funkcja skrótu wykorzystująca algorytm SHA1.
  • base64 – kodowanie base64
  • device_secret – hasło specyficzne dla urządzenia. Obiekt tajny urządzenia MUSI być aktualizowany przy każdym ponownym uruchomieniu.

Zalecane sposoby generowania klucza tajnego urządzenia:

  • Generowanie nowego identyfikatora UUID przy każdym ponownym uruchomieniu
  • Generuj 64-bitową liczbę losową przy każdym ponownym uruchomieniu

Urządzenie nie musi przechowywać wszystkich wydanych tokenów XSRF. Gdy urządzenie musi sprawdzić ważność tokena XSRF, powinno go zdekodować w formacie base64. Pobierz issue_timecounter z drugiej połowy (tekst jawny) i spróbuj wygenerować skrót SHA1 z device_secret + DELIMITER + issue_timecounter, gdzie issue_timecounter pochodzi z tokena. Jeśli nowo wygenerowany SHA1 pasuje do tego w tokenie, urządzenie musi teraz sprawdzić, czy issue_timecounter mieści się w okresie ważności (24 godziny) od bieżącego licznika czasu. W tym celu urządzenie pobiera bieżący licznik czasu (np. licznik procesora) i odejmuje od niego wartość issue_timecounter. Wynikiem MUSI być liczba sekund od wydania tokena.

Ważne: jest to zalecany sposób wdrażania ochrony przed XSRF. Klienci specyfikacji Privet nie powinni próbować zrozumieć tokena XSRF, ale traktować go jako czarną skrzynkę. Na rysunku 6.2.3 przedstawiono zalecany sposób implementacji nagłówka X-Privet-Token i weryfikacji typowego żądania.

6.2.3 Schemat sekwencji generowania i weryfikacji tokena X-Privet

6.3. Diagramy przepływu pracy

W tej sekcji przedstawimy proces w różnych przypadkach.

6.3.1. Proces konfiguracji drukarki po wyjęciu z pudełka

6.3.2. Uruchomienie zarejestrowanej drukarki

6.3.3 Przepływ pracy związany z obsługą powiadomień XMPP

6.3.4. Sprawdzanie ustawień drukarki