Privet הוא Cloud Device Local Discovery API שמשמש שירותי ענן. המסמך הזה מחולק לקטעים הבאים:
- מבוא: מבוא ל-Privet
- Discovery: local discovery mechanisms
- הודעות: הודעות על גילוי מקומי
- API: Privet APIs for general cloud devices
- Printer API: ממשקי Privet API שמשמשים מדפסות
- נספח: דיאגרמות משלימות
1. מבוא
למכשירים שמחוברים ל-Cloud יש הרבה יתרונות. הם יכולים להשתמש בשירותי המרה אונליין, לארח תורים של משימות בזמן שהמכשיר אופליין, ולהיות נגישים מכל מקום בעולם. עם זאת, אם למשתמש מסוים יש גישה למכשירים רבים בענן, אנחנו צריכים לספק שיטה למציאת המכשיר הקרוב ביותר על סמך המיקום. מטרת פרוטוקול Privet היא לשלב את הגמישות של מכשירי ענן עם מנגנון מתאים לחיפוש מקומי, כדי שמכשירים יוכלו להתגלות בקלות בסביבות חדשות.
מטרות הפרוטוקול הזה הן:- הפיכת מכשירים בענן לזמינים לחיפוש מקומי
- רישום מכשירים בענן בשירות ענן
- לשייך מכשירים רשומים לייצוג שלהם בענן
- הפעלת פונקציונליות אופליין
- לפשט את ההטמעה כדי שמכשירים קטנים יוכלו להשתמש בה
פרוטוקול Privet מורכב מ-2 חלקים עיקריים: גילוי ו-API. האיתור משמש למציאת המכשיר ברשת המקומית, וממשק ה-API משמש לקבלת מידע על המכשיר ולביצוע פעולות מסוימות. במאמר הזה, המונח 'מכשיר' מתייחס למכשיר שמחובר לענן ומיישם את פרוטוקול Privet.
2. Discovery
הגילוי הוא פרוטוקול מבוסס Zeroconf (mDNS + DNS-SD). המכשיר חייב להטמיע כתובות IPv4 Link-Local. המכשיר חייב לעמוד בדרישות של מפרטי mDNS ו-DNS-SD.
- http://www.rfc-editor.org/rfc/rfc3927.txt (IPv4 Link-local)
- http://www.rfc-editor.org/rfc/rfc4862.txt (IPv6 Link-local)
- http://www.rfc-editor.org/rfc/rfc6762.txt (mDNS)
- http://www.rfc-editor.org/rfc/rfc6763.txt (DNS-SD)
המכשיר חייב לבצע פתרון של ניגודי שמות בהתאם למפרטים שלמעלה.
2.1. סוג השירות
זיהוי שירותים ב-DNS משתמש בפורמט הבא לסוגי שירותים: _applicationprotocol._transportprotocol. במקרה של פרוטוקול Privet, סוג השירות של DNS-SD צריך להיות: _privet._tcp
המכשיר יכול להטמיע גם סוגים אחרים של שירותים. מומלץ להשתמש באותו שם של מופע שירות לכל סוגי השירותים שמיושמים במכשיר. לדוגמה: מדפסת יכולה להטמיע את השירותים Printer XYZ._privet._tcp ו-Printer XYZ._printer._tcp. היא תפשט את תהליך ההגדרה עבור המשתמש. עם זאת, לקוחות Privet יחפשו רק את '_privet._tcp'.
בנוסף לסוג השירות הראשי, המכשיר חייב לפרסם את רשומות ה-PTR עבור סוגי המשנה המתאימים (ראו מפרט DNS-SD: '7.1. ספירה סלקטיבית של מופעים (סוגי משנה)'). הפורמט צריך להיות: _<subtype>._sub._privet._tcp
בשלב הזה, סוג המשנה היחיד של מכשיר שנתמך הוא מדפסת. לכן, כל המדפסות חייבות לפרסם שתי רשומות PTR:
- _privet._tcp.local.
- _printer._sub._privet._tcp.local.
2.2. רשומת TXT
ב-DNS Service Discovery מוגדרים שדות להוספת מידע אופציונלי על שירות ברשומות ה-TXT. רשומת TXT מורכבת מצמדי מפתח/ערך. כל צמד מפתח/ערך מתחיל מבייט האורך ואחריו עד 255 בייטים של טקסט. המפתח הוא הטקסט שלפני התו הראשון של '=' והערך הוא הטקסט שאחרי התו הראשון של '=' ועד הסוף. המפרט מאפשר להשאיר את הרשומה ללא ערך. במקרה כזה, לא יופיע התו '=' או שלא יופיע טקסט אחרי התו '='. (ראו מפרט DNS-SD: 6.1. כללי פורמט כלליים לרשומות TXT של DNS" לפורמט של רשומת TXT של DNS וגם ל "6.2. DNS-SD TXT Record Size" (גודל רשומת ה-TXT) לאורך המומלץ).
כדי להשתמש ב-Privet, המכשיר צריך לשלוח את צמדי המפתח/ערך הבאים ברשומת ה-TXT. מחרוזות של מפתח/ערך לא תלויות באותיות רישיות. לדוגמה, 'CS=online' ו-'cs=ONLINE' זהים. המידע ברשומת ה-TXT חייב להיות זהה למידע שאפשר לגשת אליו דרך info API (ראו סעיף 4.1). API section).
מומלץ שגודל רשומת ה-TXT יהיה קטן מ-512 בייטים.
2.2.1. txtvers
הגרסה של מבנה ה-TXT. הרשומה txtvers חייבת להיות הרשומה הראשונה במבנה ה-TXT. בשלב הזה, רק גרסה 1 נתמכת.
txtvers=1
2.2.2. ty
מספק שם של המכשיר שקריא למשתמש. לדוגמה:
ty=Google Cloud Ready Printer Model XYZ
2.2.3 הערה (אופציונלי)
מספק שם של המכשיר שקריא למשתמש. לדוגמה:
note=1st floor lobby printer
הערה: זהו מפתח אופציונלי ואפשר לדלג עליו. עם זאת, אם הוא קיים, המשתמש צריך להיות מסוגל לשנות את הערך הזה. חובה להשתמש באותו תיאור כשרושמים את המכשיר.
2.2.4 url
כתובת ה-URL של השרת שאליו המכשיר מחובר (כולל הפרוטוקול). לדוגמה:
url=https://www.google.com/cloudprint
2.2.5 type
רשימה של סוגי משנה של מכשירים שנתמכים במכשיר הזה, מופרדים באמצעות פסיקים. הפורמט הוא: "type=_subtype1,_subtype2". נכון לעכשיו, סוג המשנה היחיד של מכשיר שנתמך הוא מדפסת.
type=printer
כל סוג משנה שמופיע ברשימה צריך להיות מפורסם באמצעות רשומת PTR תואמת. לכל סוג משנה נתמך של שירות צריך להיות פריט תואם. שם סוג המשנה של השירות (<subtype>._sub._privet._tcp) צריך להיות שווה לסוג המכשיר כאן.
2.2.6. id
מזהה המכשיר. אם המכשיר עדיין לא נרשם, המפתח הזה צריך להיות קיים, אבל הערך צריך להיות ריק. לדוגמה:
id=11111111-2222-3333-4444-555555555555 id=
2.2.7. cs
מציין את מצב החיבור הנוכחי של המכשיר. במפרט הזה מוגדרים ארבעה ערכים אפשריים.
- הסטטוס 'אונליין' מציין שהמכשיר מחובר כרגע לענן.
- המצב 'אופליין' מציין שהמכשיר זמין ברשת המקומית, אבל הוא לא יכול לתקשר עם השרת.
- הסטטוס 'מתחבר' מציין שהמכשיר מבצע את רצף ההפעלה שלו ועדיין לא מחובר לאינטרנט באופן מלא.
- הערך 'לא הוגדר' מציין שעדיין לא הוגדרה גישה לאינטרנט במכשיר. הערך הזה לא נמצא בשימוש כרגע, אבל יכול להיות שהוא יהיה שימושי בגרסאות עתידיות של המפרט.
- cs=online
- cs=offline
- cs=connecting
אם המכשיר נרשם בענן, הוא צריך לבדוק את הקישוריות לשרת בזמן ההפעלה כדי לזהות את מצב החיבור שלו (לדוגמה, קריאה ל-API של הענן כדי לקבל את הגדרות המכשיר). יכול להיות שהמכשיר ישתמש במצב החיבור של ערוץ ההתראות שלו (למשל XMPP) כדי לדווח על הערך הזה. מכשירים שלא רשומים עשויים לשלוח פינג לדומיין בהפעלה כדי לזהות את מצב החיבור שלהם (לדוגמה, פינג לכתובת www.google.com למכשירים של Cloud Print).
3. עדכונים
בזמן הפעלה, כיבוי או שינוי מצב של המכשיר, המכשיר חייב לבצע את שלב ההודעה כפי שמתואר במפרט של mDNS. מומלץ לשלוח את ההודעה המתאימה לפחות פעמיים, עם מרווח של שנייה אחת לפחות בין השליחות.
3.1. הפעלה
בזמן הפעלת המכשיר, הוא חייב לבצע את שלבי הבדיקה וההודעה כפי שמתואר במפרט של mDNS. במקרה כזה, צריך לשלוח רשומות SRV, PTR ו-TXT. מומלץ לקבץ את כל הרשומות בתגובת DNS אחת, אם אפשר. אם לא, מומלץ להשתמש בסדר הבא: רשומות SRV, PTR ו-TXT.
3.2. כיבוי
בזמן כיבוי המכשיר, המכשיר צריך לנסות להודיע לכל הצדדים המעוניינים על הכיבוי על ידי שליחת 'חבילת פרידה' עם TTL=0 (כפי שמתואר במסמכי ה-mDNS).
3.3. עדכון
אם חל שינוי במידע שמתואר ב-TXT, המכשיר חייב לשלוח הודעת עדכון. במקרה כזה, מספיק לשלוח רק את רשומת ה-TXT החדשה. לדוגמה, אחרי שמכשיר נרשם, הוא חייב לשלוח הודעת עדכון שכוללת את מזהה המכשיר החדש.
4. API
אחרי שמגלים מכשיר בענן, התקשורת של הלקוח עם המכשיר מופעלת ישירות ברשת המקומית. כל ממשקי ה-API מבוססים על HTTP 1.1. פורמטים של נתונים מבוססים על JSON. בקשות API יכולות להיות בקשות GET או בקשות POST.
כל בקשה חייבת להכיל כותרת תקינה של X-Privet-Token. הבקשה היחידה שיכולה לכלול כותרת ריקה של X-Privet-Token היא הבקשה /privet/info (חשוב לציין שהכותרת עדיין חייבת להיות נוכחת). אם הכותרת X-Privet-Token חסרה, המכשיר חייב להגיב עם שגיאת HTTP 400 הבאה:
HTTP/1.1 400 Missing X-Privet-Token header.
אם הכותרת X-Privet-Token ריקה או לא חוקית, המכשיר חייב להשיב עם השגיאה invalid_x_privet_token (ראו פרטים בקטע 'שגיאות'). החריג היחיד הוא API מסוג /info. מידע נוסף על הסיבות לכך ועל האופן שבו צריך ליצור אסימונים מופיע בנספח א': התקפות XSSI ו-XSRF ומניעתן.
אם ה-API המבוקש לא קיים או לא נתמך, המכשיר חייב להחזיר שגיאת HTTP 404.
4.1. זמינות API
לפני חשיפת API כלשהו (כולל API של /info), המכשיר חייב ליצור קשר עם השרת כדי לבדוק את ההגדרות המקומיות. ההגדרות המקומיות חייבות להישמר בין הפעלות מחדש. אם השרת לא זמין, צריך להשתמש בהגדרות המקומיות האחרונות הידועות. אם המכשיר לא רשום עדיין, הוא צריך לפעול לפי הגדרות ברירת המחדל.
כדי שמכשירי Cloud Print יירשמו, יקבלו ויעדכנו את ההגדרות המקומיות, הם צריכים לפעול לפי השלבים הבאים.
4.1.1. הרשמה
כשמכשיר נרשם, הוא חייב לציין את הפרמטר local_settings באופן הבא:
{ "current": { "local_discovery": true, "access_token_enabled": true, "printer/local_printing_enabled": true, "printer/conversion_printing_enabled": true, "xmpp_timeout_value": 300 } }
שם הערך | סוג הערך | תיאור |
---|---|---|
local_discovery | בוליאני | מציין אם מותר להשתמש בפונקציונליות של חיפוש מקומי. אם הערך הוא false, צריך להשבית את כל ה-API המקומי (כולל /info) ואת גילוי DNS-SD. כברירת מחדל, מכשירים חדשים שנרשמים צריכים להעביר את הערך true. |
access_token_enabled | boolean (אופציונלי) | מציין אם ממשק ה-API /accesstoken צריך להיות חשוף ברשת המקומית. ברירת המחדל היא true. |
printer/local_printing_enabled | boolean (אופציונלי) | מציין אם פונקציונליות של הדפסה מקומית (/printer/createjob, /printer/submitdoc, /printer/jobstate) צריכה להיות חשופה ברשת המקומית. ברירת המחדל היא true. |
printer/conversion_printing_enabled | boolean (אופציונלי) | מציין אם הדפסה מקומית יכולה לשלוח עבודות לשרת לצורך המרה. ההגדרה הזו רלוונטית רק אם הדפסה מקומית מופעלת. |
xmpp_timeout_value | int (אופציונלי) | מציין את מספר השניות בין פינגים של ערוץ XMPP. ערך ברירת המחדל הוא 300 (5 דקות) או יותר. |
חשוב: אם לא מצוין ערך אופציונלי, המשמעות היא שהמכשיר לא תומך בפונקציונליות המתאימה.
4.1.2. הפעלה
בזמן הפעלת המכשיר, הוא אמור ליצור קשר עם השרת כדי לבדוק אילו ממשקי API זמינים לחשיפה ברשת המקומית. למדפסות שמחוברות ל-Cloud Print, צריך להתקשר אל:
/cloudprint/printer?printerid=<printer_id>
/cloudprint/list
עדיף להשתמש ב-/cloudprint/printer במקום ב- /cloudprint/list, אבל שניהם יעבדו.
ה-API הזה מחזיר את הפרמטרים הנוכחיים של המכשיר, כולל ההגדרות של ה-API המקומי. התשובה מהשרת תהיה בפורמט הבא:
"local_settings": { "current": { "local_discovery": true, "access_token_enabled": true, "printer/local_printing_enabled": true, "printer/conversion_printing_enabled": true, "xmpp_timeout_value": 300 }, "pending": { "local_discovery": true, "access_token_enabled": true, "printer/local_printing_enabled": false, "printer/conversion_printing_enabled": false, "xmpp_timeout_value": 500 } }
האובייקט current מציין את ההגדרות שבתוקף כרגע.
אובייקט 'בהמתנה' מציין הגדרות שצריך להחיל על המכשיר (יכול להיות שהאובייקט הזה לא קיים).
אחרי שהמכשיר מזהה הגדרות במצב 'בהמתנה', הוא חייב לעדכן את הסטטוס שלו (ראו בהמשך).
4.1.3. עדכון
אם צריך לעדכן את ההגדרות, תישלח למכשיר הודעה ב-XMPP. ההתראה תהיה בפורמט הבא:
<device_id>/update_settings
כשמתקבלת התראה כזו, המכשיר חייב לשלוח שאילתה לשרת כדי לקבל את ההגדרות העדכניות. מכשירי Cloud Print חייבים להשתמש ב:
/cloudprint/printer?printerid=<printer_id>
אחרי שהמכשיר רואה את הקטע 'בהמתנה' כתוצאה מ-API /cloudprint/printer (בזמן ההפעלה או בגלל ההתראה), הוא חייב לעדכן את המצב הפנימי שלו כדי לזכור את ההגדרות החדשות. הוא חייב לקרוא ל-API של השרת כדי לאשר את ההגדרות החדשות. במקרה של מדפסות Cloud, המכשיר חייב להפעיל את Cloudprint/update API ולהשתמש בפרמטר local_settings כמו במהלך הרישום.
כשמתחברים מחדש לערוץ XMPP, המכשיר חייב להתקשר ל-API /cloudprint/printer כדי לבדוק אם ההגדרות המקומיות השתנו מאז הפעם האחרונה.
4.1.3.1. הגדרות מקומיות בהמתנה
הפרמטר local_settings שהמכשיר משתמש בו כדי לקרוא ל-API של השרת, אסור שיכיל את הקטע pending.
4.1.3.2. הגדרות מקומיות נוכחיות
רק המכשיר יכול לשנות את הקטע 'current' של 'local_settings'. כל השאר ישנו את הקטע 'בהמתנה' ויחכו עד שהשינויים יועברו לקטע 'נוכחי' על ידי המכשיר.
4.1.4. אופליין
אם אי אפשר ליצור קשר עם השרת במהלך ההפעלה, אחרי קבלת ההתראה, המכשיר חייב להשתמש בהגדרות המקומיות האחרונות הידועות.
4.1.5. מחיקת המכשיר מהשירות
אם המכשיר נמחק מהשירות (לדוגמה, GCP), תישלח למכשיר הודעה ב-XMPP. ההתראה תהיה בפורמט הבא:
<device_id>/delete
כשמתקבלת התראה כזו, המכשיר חייב להתחבר לשרת כדי לבדוק את הסטטוס שלו. מכשירי Cloud Print חייבים להשתמש ב:
/cloudprint/printer?printerid=<printer_id>
המכשיר חייב לקבל תשובת HTTP מוצלחת עם success=false וללא תיאור של המכשיר או המדפסת. המשמעות היא שהמכשיר הוסר מהשרת, והמכשיר חייב למחוק את פרטי הכניסה שלו ולעבור למצב של הגדרות מקוריות.
בכל פעם שהמכשיר מקבל תשובה שמציינת שהוא נמחק כתוצאה מ-API של /cloudprint/printer (הפעלה, התראה על עדכון הגדרות, פינג יומי), הוא חייב למחוק את האישורים שלו ולעבור למצב ברירת מחדל.
4.2. /privet/info API
ממשק ה-API של המידע הוא חובה וצריך להטמיע אותו בכל מכשיר. זו בקשת HTTP GET לכתובת ה-URL "/privet/info": GET /privet/info HTTP/1.1
ממשק ה-API של המידע מחזיר מידע בסיסי על מכשיר ועל הפונקציונליות שהוא תומך בה. אסור שה-API הזה ישנה את סטטוס המכשיר או יבצע פעולה כלשהי, כי הוא פגיע למתקפות XSRF. זה ה-API היחיד שמותר לו להכיל כותרת ריקה של X-Privet-Token. הלקוחות צריכים לקרוא ל-API /privet/info עם הכותרת X-Privet-Token שהוגדרה ל-X-Privet-Token: ""
ה-API של המידע חייב להחזיר נתונים שתואמים לנתונים שזמינים ברשומת ה-TXT במהלך הגילוי.
4.2.1. קלט
ל-API /privet/info אין פרמטרים של קלט.
4.2.2. חזרה
API /privet/info מחזיר מידע בסיסי על המכשיר ועל הפונקציונליות הנתמכת.
העמודה TXT מציינת את השדה המתאים ברשומת ה-TXT של DNS-SD.
שם הערך | סוג הערך | תיאור | TXT |
---|---|---|---|
גרסה | מחרוזת | הגרסה הכי גבוהה (major.minor) של ה-API שנתמכת, כרגע 1.0 | |
שם | מחרוזת | שם המכשיר שקריא לאנשים. | ty |
תיאור | מחרוזת | (אופציונלי) תיאור המכשיר. צריך להיות ניתן לשינוי על ידי המשתמש. | הערה, פתקית |
כתובת אתר | מחרוזת | כתובת ה-URL של השרת שאליו המכשיר הזה מתקשר. כתובת ה-URL חייבת לכלול את הפרוטוקול, למשל: https://www.google.com/cloudprint. | כתובת אתר |
סוג | רשימת מחרוזות | רשימה של סוגי המכשירים הנתמכים. | סוג |
id [מזהה] | מחרוזת | מזהה המכשיר, ריק אם המכשיר עדיין לא רשום. | id [מזהה] |
device_state | מחרוזת | מצב המכשיר. idle פירושו שהמכשיר מוכן. processing פירושו שהמכשיר עסוק והפונקציונליות שלו עשויה להיות מוגבלת למשך זמן מסוים. stopped פירושו שהמכשיר לא פועל ונדרשת התערבות של המשתמש. | |
connection_state | מחרוזת | מצב החיבור לשרת (base_url)
online – החיבור זמין offline – אין חיבור connecting – מתבצעים שלבי הפעלה not-configured – החיבור עדיין לא הוגדר מכשיר רשום עשוי לדווח על מצב החיבור שלו על סמך מצב ערוץ ההתראות (למשל, מצב החיבור של XMPP). | cs |
יצרן | מחרוזת | שם יצרן המכשיר | |
מודל | מחרוזת | דגם המכשיר | |
serial_number | מחרוזת | מזהה ייחודי של המכשיר. במפרט הזה, הערך הזה חייב להיות UUID. (GCP 1.1 spec)
(אופציונלי) מומלץ מאוד להשתמש באותו מזהה של מספר סידורי בכל מקום, כדי שלקוחות שונים יוכלו לזהות את אותו מכשיר. לדוגמה, מדפסות שמטמיעות IPP עשויות להשתמש במזהה המספר הסידורי הזה בשדה printer-device-id. | |
קושחה | מחרוזת | גרסת הקושחה של המכשיר | |
זמן פעולה תקינה | int | מספר השניות מאז הפעלת המכשיר. | |
setup_url | מחרוזת | (אופציונלי) כתובת ה-URL (כולל הפרוטוקול) של הדף עם הוראות ההגדרה | |
support_url | מחרוזת | (אופציונלי) כתובת ה-URL (כולל הפרוטוקול) של הדף עם מידע על תמיכה ושאלות נפוצות | |
update_url | מחרוזת | (אופציונלי) כתובת URL (כולל פרוטוקול) של הדף עם הוראות לעדכון קושחה | |
x-privet-token | מחרוזת | הערך של הכותרת X-Privet-Token שצריך להעביר לכל ממשקי ה-API כדי למנוע תקיפות XSSI ו-XSRF. פרטים נוספים מופיעים בסעיף 6.1. | |
api | תיאור של ממשקי API | רשימה של ממשקי API נתמכים (מתוארים בהמשך) | |
semantic_state | JSON | (אופציונלי) המצב הסמנטי של המכשיר בפורמט CloudDeviceState. |
api – רשימת JSON שמכילה את רשימת ממשקי ה-API שזמינים ברשת המקומית. הערה יכול להיות שלא כל ממשקי ה-API יהיו זמינים בו-זמנית ברשת המקומית. לדוגמה, מכשיר חדש שמחובר צריך לתמוך רק ב-API של /register:
"api": [ "/privet/register", ]
"api": [ "/privet/accesstoken", "/privet/capabilities", "/privet/printer/submitdoc", ]
בשלב הזה, ממשקי ה-API הבאים זמינים:
- /privet/register – API לרישום מכשירים ברשת המקומית. (פרטים נוספים זמינים ב-API של /privet/register). ממשק ה-API הזה חייב להיות מוסתר אחרי שהמכשיר נרשם בהצלחה בענן.
- /privet/accesstoken – API לבקשת טוקן גישה מהמכשיר (פרטים נוספים זמינים במאמר בנושא /privet/accesstoken API).
- /privet/capabilities – API לאחזור יכולות המכשיר (פרטים נוספים זמינים במאמר בנושא /privet/capabilities API).
- /privet/printer/* – API שספציפי לסוג המכשיר 'מדפסת'. פרטים נוספים זמינים במאמר בנושא ממשקי API ספציפיים למדפסות.
{ "version": "1.0", "name": "Gene’s printer", "description": "Printer connected through Chrome connector", "url": "https://www.google.com/cloudprint", "type": [ "printer" ], "id": "11111111-2222-3333-4444-555555555555", "device_state": "idle", "connection_state": "online", "manufacturer": "Google", "model": "Google Chrome", "serial_number": "1111-22222-33333-4444", "firmware": "24.0.1312.52", "uptime": 600, "setup_url": "http://support.google.com/cloudprint/answer/1686197/?hl=en", "support_url": "http://support.google.com/cloudprint/?hl=en", "update_url": "http://support.google.com/cloudprint/?hl=en", "x-privet-token": "AIp06DjQd80yMoGYuGmT_VDAApuBZbInsQ:1358377509659", "api": [ "/privet/accesstoken", "/privet/capabilities", "/privet/printer/submitdoc", ] }
{ "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. שגיאות
ה-API /privet/info צריך להחזיר שגיאה רק אם חסר הכותר X-Privet-Token. השגיאה חייבת להיות HTTP 400:
HTTP/1.1 400 Missing X-Privet-Token header.
4.3. /privet/register API
/privet/register API הוא אופציונלי. זו בקשת HTTP POST. API /privet/register חייב לבדוק אם יש כותרת X-Privet-Token תקינה. המכשיר חייב להטמיע את ה-API הזה בכתובת ה-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
המכשיר צריך לחשוף את ה-API /privet/register רק כשהוא מאפשר רישום אנונימי באותו רגע. לדוגמה:
- כשהמכשיר מופעל (או אחרי לחיצה על לחצן מיוחד במכשיר) והוא עדיין לא רשום, הוא צריך לחשוף את ה-API /privet/register כדי לאפשר למשתמש מהרשת המקומית לתבוע בעלות על המדפסת.
- אחרי שההרשמה מסתיימת, המכשיר אמור להפסיק לחשוף את ה-API /privet/register כדי למנוע ממשתמש אחר ברשת המקומית לתבוע בעלות על המכשיר.
- יכול להיות שבמכשירים מסוימים יש דרכים שונות לרשום מכשירים, ולא צריך לחשוף את ה-API של /privet/register בכלל (לדוגמה, מחבר Chrome Cloud Print).
תהליך הרישום מורכב מ-3 שלבים (ראו רישום אנונימי ל-Cloud Print).
- מתחילים בתהליך הרישום האנונימי.
- לקוח מתחיל את התהליך הזה על ידי קריאה ל-API /privet/register. יכול להיות שהמכשיר ימתין לאישור המשתמש בשלב הזה.
- קבלת טוקן תלונה.
הלקוח שולח בקשות חוזרות כדי לברר מתי המכשיר מוכן להמשך. כשהמכשיר מוכן, הוא שולח בקשה לשרת כדי לאחזר את טוקן הרישום ואת כתובת הרישום. הטוקן וכתובת ה-URL שהתקבלו צריכים להיות מוחזרים ללקוח. במהלך השלב הזה, אם המכשיר מקבל שיחה נוספת כדי לאתחל את הרישום, הוא צריך:
- אם זה אותו משתמש שהתחיל את תהליך ההרשמה – צריך להשליך את כל הנתונים הקודמים (אם יש כאלה) ולהתחיל תהליך הרשמה חדש.
- אם זה משתמש אחר – מחזירים את השגיאה device_busy ופסק זמן של 30 שניות.
משלימים את תהליך ההרשמה.
אחרי שהלקוח משייך את המכשיר לחשבון שלו, הוא צריך להודיע למכשיר להשלים את ההרשמה. אחרי שתהליך ההרשמה מסתיים, המכשיר אמור לשלוח הודעת עדכון, כולל מזהה המכשיר החדש.
הערה: כשהמכשיר מעבד קריאה ל-API /privet/register, אי אפשר לעבד במקביל קריאות אחרות ל-API /privet/register. המכשיר חייב להחזיר את השגיאה device_busy ואת פסק הזמן של 30 שניות. timeout.
מומלץ מאוד לבקש אישור מהמשתמשים לרישום במכשיר. אם מפעילים את התכונה הזו, המכשיר חייב להמתין לאישור המשתמש אחרי שהוא מקבל קריאה ל-API /privet/register?action=start. הלקוח יקרא ל-API /privet/register?action=getClaimToken כדי לגלות מתי אישור המשתמש הושלם ואסימון התביעה זמין. אם המשתמש מבטל את ההרשמה במכשיר (למשל, לוחץ על לחצן הביטול), צריך להחזיר את השגיאה user_cancel. אם המשתמש לא אישר את ההרשמה בתוך פרק זמן מסוים, חובה להחזיר את השגיאה confirmation_timeout. פרטים נוספים זמינים בקטע בנושא הגדרות ברירת מחדל.
4.3.1. קלט
ל-API /privet/register יש את פרמטרי הקלט הבאים:שם | ערך |
---|---|
פעולה | יכול להיות אחד מהערכים הבאים:
start – כדי להתחיל את תהליך ההרשמה getClaimToken – כדי לאחזר את אסימון התביעה של המכשיר cancel – כדי לבטל את תהליך ההרשמה complete – כדי להשלים את תהליך ההרשמה |
משתמש | כתובת האימייל של המשתמש שיקשר את המכשיר לחשבון שלו. |
המכשיר חייב לוודא שכתובת האימייל מכל הפעולות (התחלה, getClaimToken, ביטול, השלמה) זהה.
4.3.2. חזרה
API /privet/register מחזיר את הנתונים הבאים:שם הערך | סוג ערך | תיאור |
---|---|---|
פעולה | מחרוזת | אותה פעולה כמו בפרמטר הקלט. |
משתמש | מחרוזת (אופציונלי) | אותו משתמש כמו בפרמטר הקלט (יכול להיות שחסר, אם הוא לא נכלל בקלט). |
token | מחרוזת (אופציונלי) | אסימון רישום (חובה בתגובה של getClaimToken, לא מופיע בתגובות של start, complete ו-cancel). |
claim_url | מחרוזת (אופציונלי) | כתובת URL להרשמה (חובה בתגובה של getClaimToken, לא מופיעה בתגובות של start, complete ו-cancel). במקרה של מדפסות Cloud, צריך להשתמש בערך complete_invite_url שמתקבל מהשרת. |
automated_claim_url | מחרוזת (אופציונלי) | כתובת URL להרשמה (חובה בתגובה של getClaimToken, לא מופיעה בתגובות של start, complete ו-cancel). במקרה של מדפסות בענן, צריך להשתמש בכתובת ה-URL של ההזמנה האוטומטית שהתקבלה מהשרת. |
device_id | מחרוזת (אופציונלי) | מזהה מכשיר חדש (לא מופיע בתגובה מסוג 'התחלה', חובה בתגובה מסוג 'השלמה'). |
המכשיר חייב להחזיר את מזהה המכשיר בתגובה של /privet/info API רק אחרי שההרשמה הושלמה.
דוגמה 1:
{ "action": "start", "user": "user@domain.com", }
דוגמה 2:
{ "action": "getClaimToken", "user": "user@domain.com", "token": "AAA111222333444555666777", "claim_url": "https://domain.com/SoMeUrL", }
דוגמה 3:
{ "action": "complete", "user": "user@domain.com", "device_id": "11111111-2222-3333-4444-555555555555", }
4.3.3. שגיאות
יכול להיות שהשגיאות הבאות יוחזרו על ידי API /privet/register (פרטים נוספים זמינים בקטע 'שגיאות'):שגיאה | תיאור |
---|---|
device_busy | המכשיר עסוק ואי אפשר לבצע את הפעולה המבוקשת. ניסיון חוזר אחרי פסק זמן. |
pending_user_action | בתגובה ל-getClaimToken, השגיאה הזו מציינת שהמכשיר עדיין ממתין לאישור המשתמש, וצריך לנסות שוב את הבקשה getClaimToken אחרי פסק זמן. |
user_cancel | המשתמש ביטל באופן מפורש את תהליך ההרשמה מהמכשיר. |
confirmation_timeout | הזמן שהוקצב לאישור המשתמש פג. |
invalid_action | הופעלה פעולה לא תקינה. לדוגמה, אם הלקוח קרא לפעולה=השלמה לפני הקריאה לפעולה=התחלה ולפעולה=getClaimToken. |
invalid_params | צוינו פרמטרים לא תקינים בבקשה. (צריך להתעלם בבטחה מפרמטרים לא ידועים כדי לשמור על תאימות בעתיד). לדוגמה, מחזירים את הערך הזה אם הלקוח התקשר לפעולה=לא ידוע או למשתמש=. |
device_config_error | התאריך והשעה (או הגדרות אחרות) שגויים בצד המכשיר. המשתמש צריך להיכנס (לאתר הפנימי של המכשיר) ולהגדיר את הגדרות המכשיר. |
לא מקוון | המכשיר לא מחובר לאינטרנט כרגע ולא יכול לתקשר עם השרת. |
server_error | אירעה שגיאת שרת במהלך תהליך ההרשמה. |
invalid_x_privet_token | הערך של X-Privet-Token בבקשה לא תקין או ריק. |
המכשיר חייב להפסיק לחשוף את ה-API /privet/register אחרי שההרשמה הושלמה בהצלחה. אם המכשיר לא חושף את ה-API /privet/register, הוא חייב להחזיר שגיאת HTTP 404. לכן, אם מכשיר כבר רשום, קריאה ל-API הזה חייבת להחזיר 404. אם הכותרת X-Privet-Token חסרה, המכשיר חייב להחזיר שגיאת HTTP 400.
4.4. /privet/accesstoken API
ממשק ה-API /privet/accesstoken הוא אופציונלי. זוהי בקשת HTTP GET. /privet/accesstoken API חייב לבדוק אם יש כותרת X-Privet-Token תקפה. המכשיר חייב להטמיע את ה-API הזה בכתובת ה-URL /privet/accesstoken:GET /privet/accesstoken HTTP/1.1
כשהמכשיר מקבל את קריאת ה-API /accesstoken, הוא צריך לקרוא לשרת כדי לאחזר את אסימון הגישה של המשתמש שצוין ולהחזיר את האסימון ללקוח. לאחר מכן הלקוח ישתמש באסימון הגישה כדי לגשת למכשיר דרך הענן.
מכשירי Cloud Print חייבים להפעיל את ה-API הבא:
/cloudprint/proximitytoken
"proximity_token": { "user": "user@domain.com", "token": "AAA111222333444555666777", "expires_in": 600 }
4.4.1. קלט
ל-API /privet/accesstoken יש את פרמטרי הקלט הבאים:שם | ערך |
---|---|
משתמש | כתובת האימייל של המשתמש שהתכוון להשתמש בטוקן הגישה הזה. יכול להיות ריק בבקשה. |
4.4.2. חזרה
API /privet/accesstoken מחזיר את הנתונים הבאים:שם הערך | סוג ערך | תיאור |
---|---|---|
token | מחרוזת | טוקן הגישה שהוחזר על ידי השרת |
משתמש | מחרוזת | אותו משתמש כמו בפרמטר הקלט. |
expires_in | int | מספר השניות עד שתוקף האסימון יפוג. התקבל מהשרת והועבר בתגובה הזו. |
דוגמה:
{ "token": "AAA111222333444555666777", "user": "user@domain.com", "expires_in": 600 }
4.4.3. שגיאות
יכול להיות שה-API /privet/accesstoken יחזיר את השגיאות הבאות (פרטים נוספים זמינים בקטע 'שגיאות'):שגיאה | תיאור |
---|---|
לא מקוון | המכשיר לא מקוון כרגע ואין לו אפשרות לתקשר עם השרת. |
access_denied | אין מספיק הרשאות. הגישה נדחתה. המכשיר צריך להחזיר את השגיאה הזו כשהשרת דוחה באופן מפורש את הבקשה. |
invalid_params | צוינו פרמטרים לא תקינים בבקשה. (צריך להתעלם בבטחה מפרמטרים לא ידועים כדי לשמור על תאימות בעתיד). לדוגמה, אם הלקוח קרא ל-/accesstoken?user= או ל- /accesstoken. |
server_error | שגיאה בחיבור לשרת. |
invalid_x_privet_token | הערך של X-Privet-Token בבקשה לא תקין או ריק. |
אם המכשיר לא חושף את ה-API /privet/accesstoken, הוא חייב להחזיר שגיאת HTTP 404. אם הכותרת X-Privet-Token חסרה, המכשיר חייב להחזיר שגיאת HTTP 400.
4.5. /privet/capabilities API
API /privet/capabilities הוא אופציונלי. זוהי בקשת HTTP GET. API /privet/capabilities חייב לבדוק אם יש כותרת תקפה של X-Privet-Token. המכשיר חייב להטמיע את ה-API הזה בכתובת ה-URL /privet/capabilities:GET /privet/capabilities HTTP/1.1
4.5.1. קלט
ל-API /privet/capabilities יש את פרמטרי הקלט הבאים:שם | ערך |
---|---|
לא מקוון | (אופציונלי) הערך יכול להיות רק offline=1. במקרה כזה, המכשיר צריך להחזיר יכולות לשימוש אופליין (אם הן שונות מהיכולות של שימוש אונליין). |
4.5.2. חזרה
API /privet/capabilities מחזיר את יכולות המכשיר בפורמט JSON של Cloud Device Description (CDD) (פרטים נוספים מופיעים במסמך CDD). מדפסות חייבות להחזיר לפחות רשימה של סוגים נתמכים כאן. לדוגמה, מדפסה שמוכנה ל-Cloud שנמצאת כרגע במצב אונליין עשויה להחזיר משהו כזה (לפחות):{ "version": "1.0", "printer": { "supported_content_type": [ { "content_type": "application/pdf", "min_version": "1.4" }, { "content_type": "image/pwg-raster" }, { "content_type": "image/jpeg" }, { "content_type": "*/*" } ] } }
{ "version": "1.0", "printer": { "supported_content_type": [ { "content_type": "application/pdf", "min_version": "1.4" }, { "content_type": "image/pwg-raster" }, { "content_type": "image/jpeg" } ] } }
הערה: מדפסות Express תומכות בסדר עדיפות של סוגי תוכן. לדוגמה, בדוגמאות שלמעלה, המדפסת מציינת שהיא מעדיפה נתונים מסוג application/pdf על פני image/pwg-raster ו-image/jpeg. אם אפשר, הלקוחות צריכים להתחשב בעדיפות של המדפסת (פרטים מופיעים במסמך CDD).
4.5.3. שגיאות
יכול להיות שהשגיאות הבאות יוחזרו על ידי Privet/capabilities API (פרטים נוספים זמינים בקטע 'שגיאות'):שגיאה | תיאור |
---|---|
invalid_x_privet_token | הערך של X-Privet-Token בבקשה לא תקין או ריק. |
אם המכשיר לא חושף את ה-API /privet/capabilities, הוא חייב להחזיר שגיאת HTTP 404. אם הכותרת X-Privet-Token חסרה, המכשיר חייב להחזיר שגיאת HTTP 400.
4.6. שגיאות
השגיאות מוחזרות מממשקי ה-API שלמעלה בפורמט הבא:שם הערך | סוג ערך | תיאור |
---|---|---|
error | מחרוזת | סוג השגיאה (מוגדר לכל API) |
תיאור | מחרוזת (אופציונלי) | תיאור השגיאה שקריא לאנשים. |
server_api | מחרוזת (אופציונלי) | במקרה של שגיאת שרת, השדה הזה מכיל את ה-API של השרת שנכשל. |
server_code | int (אופציונלי) | במקרה של שגיאת שרת, השדה הזה מכיל את קוד השגיאה שהשרת החזיר. |
server_http_code | int (אופציונלי) | במקרה של שגיאת HTTP בשרת, השדה הזה מכיל את קוד שגיאת ה-HTTP שהשרת החזיר. |
פסק זמן | int (אופציונלי) | מספר השניות שהלקוח ימתין לפני ניסיון חוזר (רק לשגיאות שניתן לתקן). הלקוח חייב להקצות ערך אקראי לזמן הקצוב לתפוגה מתוך הערך הזה, כך שהערך יהיה גדול ב-20% מהערך הזה. |
כל ממשקי ה-API חייבים להחזיר שגיאת HTTP 400 אם חסר הכותר X-Privet-Token.
HTTP/1.1 400 חסרה כותרת X-Privet-Token.
דוגמה 1:
{ "error": "server_error", "description": "Service unavailable", "server_api": "/submit", "server_http_code": 503 }
דוגמה 2:
{ "error": "printer_busy", "description": "Printer is currently printing other job", "timeout": 15 }
5. Printer API
אחד מסוגי המכשירים שהפרוטוקול הזה תומך בהם הוא מדפסת. מכשירים שתומכים בסוג הזה עשויים להטמיע פונקציונליות ספציפית למדפסות. ההדפסה למדפסות שמותאמות לענן אמורה להתבצע דרך שרת Cloud Print:

במקרים מסוימים, יכול להיות שלקוח יצטרך לשלוח מסמך באופן מקומי. יכול להיות שיהיה צורך בכך אם ללקוח אין מזהה Google או שהוא לא יכול לתקשר עם שרת Cloud Print. במקרה כזה, משימת ההדפסה תישלח באופן מקומי למדפסת. המדפסת, בתורה, תשתמש בשירות Cloud Print כדי להוסיף את העבודות לתור ולהמיר אותן. המדפסת תפרסם מחדש את העבודה שנשלחה באופן מקומי לשירות Cloud Print ואז תבקש אותה, כי היא נשלחה דרך הענן. התהליך הזה יספק חוויית משתמש גמישה מבחינת שירות (המרות) וניהול/מעקב של עבודות הדפסה.

מכיוון ששירות Cloud Print מבצע המרה, המדפסת צריכה לפרסם תמיכה בכל פורמטי הקלט (*/*) ברשימת סוגי התוכן הנתמכים:
{ "version": "1.0", "printer": { "supported_content_type": [ { "content_type": "image/pwg-raster" }, { "content_type": "*/*" } ] } }
במקרים מסוימים, הפתרון הרצוי הוא פתרון שפועל לגמרי אופליין. המדפסות תומכות במספר מוגבל של פורמטים של קלט, ולכן הלקוח יצטרך להמיר את המסמכים לכמה פורמטים של מדפסות שנתמכים באופן מקורי.

לפי המפרט הזה, כל המדפסות צריכות לתמוך לפחות בפורמט PWG Raster ("image/pwg-raster") במקרה של הדפסה אופליין. מדפסת עשויה לתמוך בפורמטים אחרים (לדוגמה, JPEG), ואם לקוח תומך בפורמט הזה, הוא עשוי לשלוח מסמכים בפורמט הזה. המדפסת חייבת לחשוף סוגים נתמכים דרך API /capabilities, לדוגמה:
{ "version": "1.0", "printer": { "supported_content_type": [ { "content_type": "image/pwg-raster" }, { "content_type": "image/jpeg" } ] } }
הדפסה פשוטה – הלקוח שולח את המסמך ברשת המקומית אל API /submitdoc (בלי לציין את הפרמטר job_id). המסמך שנשלח יודפס באמצעות הגדרות ברירת המחדל של כרטיס ההדפסה, ולא נדרשים סטטוסים של משימות הדפסה. אם המדפסת תומכת רק בסוג ההדפסה הזה, היא חייבת לפרסם רק את API /submitdoc בתגובת API /privet/info.
"api": [ "/privet/accesstoken", "/privet/capabilities", "/privet/printer/submitdoc", ]
הדפסה מתקדמת – הלקוח צריך קודם ליצור עבודת הדפסה במדפסת על ידי קריאה ל-API /privet/printer/createjob עם כרטיס עבודה תקף של CJT בבקשה. המדפסת חייבת לאחסן את כרטיס ההדפסה בזיכרון ולהחזיר job_id ללקוח. לאחר מכן הלקוח ישלח קריאה ל-API /printer/submitdoc ויציין את job_id שהתקבל קודם. בשלב הזה המדפסת תתחיל להדפיס. הלקוח יבצע סקר למדפסת כדי לקבל את הסטטוס של עבודת ההדפסה על ידי קריאה ל-API /privet/printer/jobstate.
בסביבה מרובת לקוחות, אין ערובה לכך שתתבצע קריאה לממשק ה-API הזה. יכול להיות שלקוח אחד יתקשר אל /createjob בין השיחות של לקוח אחר אל /createjob->/submitdoc. כדי למנוע מצבים אפשריים של קיפאון ולשפר את השימושיות, מומלץ להגדיר תור קטן של משימות הדפסה בהמתנה במדפסת (לפחות 3-5):
- /createjob מקבל את המקום הראשון בתור.
- משך החיים של העבודה (בתור) הוא 5 דקות לפחות.
- אם כל המקומות בתור תפוסים, המשימה הכי ישנה שלא מודפסת תוסר ותוצב במקומה משימה חדשה.
- אם יש משימת הדפסה שמתבצעת כרגע במכשיר (הדפסה פשוטה או מתקדמת), הפקודה /submitdoc צריכה להחזיר את הסטטוס busy ולהציע פסק זמן לניסיון חוזר של משימת ההדפסה הזו.
- אם /submitdoc מתייחס לעבודה שהוסרה מהתור (עקב החלפה או פסק זמן), המדפסת צריכה להחזיר שגיאה invalid_print_job והלקוח ינסה שוב את התהליך מהשלב /createjob. הלקוח חייב להמתין פרק זמן אקראי של עד 5 שניות לפני ניסיון חוזר.
אם מגבלות הזיכרון מונעות אחסון של כמה עבודות בהמתנה במכשיר, יכול להיות שתור ההדפסה יכלול רק עבודה אחת. היא עדיין צריכה לפעול לפי אותו פרוטוקול שצוין למעלה. אחרי שמשימה מסתיימת או נכשלת עם שגיאה, המדפסת צריכה לאחסן מידע על סטטוס המשימה למשך 5 דקות לפחות. גודל התור לאחסון סטטוסים של משימות שהושלמו צריך להיות לפחות 10. אם יש עוד סטטוסים של משרות שצריך לאחסן, יכול להיות שהסטטוס הכי ישן יוסר מהתור לפני פסק הזמן של 5 דקות.
הערה: בשלב הזה, הלקוחות יבדקו את סטטוס העבודה. יכול להיות שבעתיד נדרוש מהמדפסת לשלוח התראה על שינוי ברשומת TXT של DNS כשסטטוס של משימת הדפסה משתנה.
5.1. /privet/printer/createjob API
API /privet/printer/createjob הוא אופציונלי (ראו את הקטע 'הדפסה פשוטה' למעלה). זו בקשת HTTP POST. API /privet/printer/createjob חייב לבדוק אם יש כותרת תקפה של X-Privet-Token. המכשיר חייב להטמיע את ה-API הזה בכתובת ה-URL /privet/printer/createjob:
POST /privet/printer/createjob HTTP/1.1
5.1.1. קלט
ל-API /privet/printer/createjob אין פרמטרים של קלט בכתובת ה-URL. גוף הבקשה צריך להכיל את נתוני כרטיס העבודה להדפסה בפורמט CJT.5.1.2. חזרה
API /privet/printer/createjob מחזיר את הנתונים הבאים:שם הערך | סוג ערך | תיאור |
---|---|---|
job_id | מחרוזת | המזהה של משימת ההדפסה שנוצרה. |
expires_in | int | מספר השניות שבהן עבודת ההדפסה הזו תקפה. |
דוגמה:
{ "job_id": "123", "expires_in": 600 }
5.1.3. שגיאות
יכול להיות שה-API /privet/printer/createjob יחזיר את השגיאות הבאות (פרטים נוספים זמינים בקטע 'שגיאות'):שגיאה | תיאור |
---|---|
invalid_ticket | כרטיס ההדפסה שנשלח לא תקין. |
printer_busy | המדפסת עסוקה ואי אפשר כרגע לעבד /ליצור משימה. ניסיון חוזר אחרי פסק זמן. |
printer_error | המצב של המדפסת הוא שגיאה ונדרשת אינטראקציה של המשתמש כדי לפתור אותה. התיאור צריך לכלול הסבר מפורט יותר (לדוגמה: "דף נתקע במגש 1"). |
invalid_x_privet_token | הערך של X-Privet-Token בבקשה לא תקין או ריק. |
אם המכשיר לא חושף את הנתיב /privet/printer/createjob, הוא חייב להחזיר שגיאת HTTP 404. אם הכותרת X-Privet-Token חסרה, המכשיר חייב להחזיר שגיאת HTTP 400.
5.2. /privet/printer/submitdoc API
חובה להטמיע את /privet/printer/submitdoc API כדי להדפיס ברשת מקומית (אופליין או פרסום מחדש ב-Cloud Print). זו בקשת HTTP POST. API /privet/printer/submitdoc חייב לבדוק אם יש כותרת תקפה של X-Privet-Token. המכשיר חייב להטמיע את ה-API הזה בכתובת ה-URL /privet/printer/submitdoc:POST /privet/printer/submitdoc HTTP/1.1
אם המדפסת לא יכולה להכיל את כל הנתונים במאגר הפנימי שלה, היא צריכה להשתמש במנגנוני TCP כדי להאט את העברת הנתונים עד שהיא מדפיסה חלק מהמסמך, וכך חלק מהמאגר יהיה זמין שוב. (לדוגמה, יכול להיות שהמדפסת תגדיר windowsize=0 בשכבות TCP, מה שיגרום ללקוח להמתין).
יכול להיות שיעבור זמן רב עד שהמסמך יישלח למדפסת. הלקוח צריך להיות מסוגל לבדוק את מצב המדפסת והעבודה (הדפסה מתקדמת) בזמן שההדפסה מתבצעת. כדי לעשות זאת, המדפסת צריכה לאפשר ללקוח לקרוא ל-API /privet/info ול-API /privet/printer/jobstate בזמן העיבוד של קריאות ל-API /privet/printer/submitdoc. מומלץ שכל הלקוחות יתחילו שרשור חדש כדי להפעיל את הקריאה ל-API /privet/printer/submitdoc, כדי שהשרשור הראשי יוכל להשתמש בממשקי ה-API /privet/info ו- /privet/printer/jobstate כדי לבדוק את מצבי המדפסת והעבודה.
הערה: אחרי השלמה או ביטול של עבודת הדפסה מקומית, מומלץ מאוד (ובגרסה עתידית של המפרט הזה זה יהיה חובה) לדווח על המצב הסופי של העבודה לממשק /cloudprint/submit למטרות דיווח ושיפור חוויית המשתמש. הפרמטרים הנדרשים הם printerid, title, contentType ו-final_semantic_state (בפורמט PrintJobState). הפרמטרים האופציונליים הם tag (פרמטר שחוזר על עצמו) ו-ticket (הכרטיס של העבודה בפורמט CloudJobTicket). חשוב לציין שמצב עבודת ההדפסה שסופק חייב להיות סופי, כלומר הסוג שלו חייב להיות DONE או ABORTED, ובמקרה שהוא ABORTED, צריך לספק סיבה (פרטים מופיעים ב-JobState). חשוב גם לציין שהשימוש הזה בממשק /cloudprint/submit כדי לדווח על עבודות הדפסה מקומיות לא מוזכר במפרט שלו, כי המטרה של הקטע הזה היא לתאר את השימוש העיקרי בממשק: שליחת עבודת הדפסה עם המסמך להדפסה שמוגדר בפרמטר content.
5.2.1. קלט
ל-API /privet/printer/submitdoc יש את פרמטרי הקלט הבאים:שם | ערך |
---|---|
job_id | (אופציונלי) מזהה עבודת ההדפסה. יכול להיות שיושמט במקרה פשוט של הדפסה (ראו למעלה). הערך חייב להיות זהה לערך שמוחזר על ידי המדפסת. |
user_name | (אופציונלי) שם משתמש שקריא לבני אדם. ההגדרה הזו לא סופית, וצריך להשתמש בה רק להערות במשימות הדפסה. אם העבודה נשלחת מחדש לשירות Cloud Print, המחרוזת הזו צריכה להיות מצורפת לעבודה ב-Cloud Print. |
client_name | (אופציונלי) שם אפליקציית הלקוח ששולחת את הבקשה הזו. למטרות תצוגה בלבד. אם העבודה נשלחת מחדש לשירות Cloud Print, המחרוזת הזו צריכה להיות מצורפת לעבודה ב-Cloud Print. |
job_name | (אופציונלי) שם משימת ההדפסה שרוצים לתעד. אם המשרה מתפרסמת מחדש בשירות Cloud Print, המחרוזת הזו צריכה להיות מצורפת למשרה ב-Cloud Print. |
לא מקוון | (אופציונלי) הערך יכול להיות רק offline=1. במקרה כזה, המדפסת צריכה לנסות להדפיס רק במצב אופליין (לא לפרסם מחדש בשרת של Cloud Print). |
גוף הבקשה צריך להכיל מסמך תקין להדפסה. השדה Content-Length צריך לכלול את האורך הנכון של הבקשה. הכותרת Content-Type צריכה להיות מוגדרת לסוג ה-MIME של המסמך ולהתאים לאחד מהסוגים ב-CDD (אלא אם ב-CDD מצוין '*/*').
מומלץ מאוד ללקוחות לספק עם הבקשה הזו שם משתמש (או כתובת אימייל) תקין, שם לקוח ושם משרה. השדות האלה משמשים רק בממשקי משתמש כדי לשפר את חוויית המשתמש.
5.2.2. חזרה
API /privet/printer/submitdoc מחזיר את הנתונים הבאים:שם הערך | סוג ערך | תיאור |
---|---|---|
job_id | מחרוזת | המזהה של משימת ההדפסה החדשה שנוצרה (הדפסה פשוטה) או job_id שצוין בבקשה (הדפסה מתקדמת). |
expires_in | int | מספר השניות שבהן עבודת ההדפסה הזו תקפה. |
job_type | מחרוזת | סוג התוכן של המסמך שנשלח. |
job_size | int 64 bit | גודל נתוני ההדפסה בבייטים. |
job_name | מחרוזת | (אופציונלי) שם המשרה זהה לזה שמופיע בקלט (אם יש כזה). |
דוגמה:
{ "job_id": "123", "expires_in": 500, "job_type": "application/pdf", "job_size": 123456, "job_name": "My PDF document" }
5.2.3. שגיאות
יכול להיות שה-API /privet/printer/submitdoc יחזיר את השגיאות הבאות (פרטים בקטע 'שגיאות'):שגיאה | תיאור |
---|---|
invalid_print_job | בבקשה צוין מזהה משימה לא תקין או שתוקף המזהה פג. ניסיון חוזר אחרי פסק זמן. |
invalid_document_type | המדפסת לא תומכת בסוג ה-MIME של המסמך. |
invalid_document | המסמך שנשלח לא תקין. |
document_too_large | המסמך חורג מהגודל המקסימלי המותר. |
printer_busy | המדפסת עסוקה ואי אפשר לעבד את המסמך כרגע. ניסיון חוזר אחרי פסק זמן. |
printer_error | המצב של המדפסת הוא שגיאה ונדרשת אינטראקציה של המשתמש כדי לפתור אותה. התיאור צריך לכלול הסבר מפורט יותר (לדוגמה: "דף נתקע במגש 1"). |
invalid_params | צוינו פרמטרים לא תקינים בבקשה. (Unknown parameters should be safely ignored for future compatibility) |
user_cancel | המשתמש ביטל באופן מפורש את תהליך ההדפסה מהמכשיר. |
server_error | הפרסום של המסמך ב-Cloud Print נכשל. |
invalid_x_privet_token | הערך של X-Privet-Token בבקשה לא תקין או ריק. |
אם המכשיר לא חושף את הנתיב /privet/printer/submitdoc, הוא חייב להחזיר שגיאת HTTP 404. אם הכותרת X-Privet-Token חסרה, המכשיר חייב להחזיר שגיאת HTTP 400.
הערה: יכול להיות שיהיה צורך בטיפול מיוחד ב-API /privet/printer/submitdoc בצד המדפסת (בגלל המטען הייעודי (payload) הגדול שמצורף). במקרים מסוימים (תלוי בהטמעה ובפלטפורמה של שרת ה-HTTP של המדפסת), המדפסת עשויה לסגור את השקע לפני שהיא מחזירה שגיאת HTTP. במקרים אחרים, המדפסת עשויה להחזיר שגיאה 503 (במקום שגיאת Privet). מדפסות צריכות לנסות ככל האפשר להחזיר את Privet. עם זאת, כל לקוח שמטמיע את מפרט Privet צריך להיות מסוגל לטפל במקרים של סגירת שקע (ללא שגיאת HTTP) ובמקרים של שגיאת HTTP 503 עבור ה-API /privet/printer/submitdoc. במקרה הזה, הלקוח צריך לטפל בזה כשגיאת Privet 'printer_busy' עם הגדרה של 'timeout' ל-15 שניות. כדי להימנע מניסיונות חוזרים אינסופיים, הלקוח עשוי להפסיק לנסות שוב אחרי מספר סביר של ניסיונות (למשל, 3).
5.3. /privet/printer/jobstate API
API /privet/printer/jobstate הוא אופציונלי (ראו את הקטע 'הדפסה פשוטה' למעלה). זוהי בקשת HTTP GET. API /privet/printer/jobstate חייב לבדוק אם יש כותרת תקפה של X-Privet-Token. המכשיר חייב להטמיע את ה-API הזה בכתובת ה-URL /privet/printer/jobstate:GET /privet/printer/jobstate HTTP/1.1
5.3.1. קלט
ל-API /privet/printer/jobstate יש את פרמטרי הקלט הבאים:שם | ערך |
---|---|
job_id | מזהה משימת ההדפסה שרוצים לקבל את הסטטוס שלה. |
5.3.2. חזרה
/privet/printer/jobstate API מחזיר את הנתונים הבאים:שם הערך | סוג ערך | תיאור |
---|---|---|
job_id | מחרוזת | מזהה משימת ההדפסה שהמידע על הסטטוס שלה מתייחס אליה. |
הסמוי הסופי | מחרוזת | draft – משימת ההדפסה נוצרה במכשיר (עדיין לא התקבלו קריאות של /privet/printer/submitdoc).
queued – עבודת ההדפסה התקבלה והוכנסה לתור, אבל ההדפסה עדיין לא התחילה. in_progress – משימת ההדפסה נמצאת בתהליך הדפסה. stopped – עבודת ההדפסה הופסקה, אבל אפשר להפעיל אותה מחדש באופן ידני או אוטומטי. done – עבודת ההדפסה הסתיימה. בוטלה – משימת ההדפסה נכשלה. |
תיאור | מחרוזת | (אופציונלי) תיאור קריא (לבני אדם) של סטטוס משימת ההדפסה. צריך לכלול מידע נוסף אם המצב< הוא stopped או aborted. בדרך כלל, השדה semantic_state מספק ללקוח תיאור טוב ומשמעותי יותר. |
expires_in | int | מספר השניות שבהן עבודת ההדפסה הזו תקפה. |
job_type | מחרוזת | (אופציונלי) סוג התוכן של המסמך שנשלח. |
job_size | int 64 bit | (אופציונלי) גודל נתוני ההדפסה בבייטים. |
job_name | מחרוזת | (אופציונלי) שם המשרה זהה לזה שמופיע בקלט (אם יש כזה). |
server_job_id | מחרוזת | (אופציונלי) מזהה המשימה שמוחזר מהשרת (אם המשימה פורסמה בשירות Cloud Print). הושמט להדפסה במצב אופליין. |
semantic_state | JSON | (אופציונלי) המצב הסמנטי של העבודה בפורמט PrintJobState. |
דוגמה (הדפסה באמצעות דיווח דרך Cloud Print):
{ "job_id": "123", "state": "in_progress", "expires_in": 100, "job_type": "application/pdf", "job_size": 123456, "job_name": "My PDF document", "server_job_id": "1111-2222-3333-4444" }
דוגמה (שגיאה בהדפסה במצב אופליין):
{ "job_id": "123", "state": "stopped", "description": "Out of paper", "expires_in": 100, "job_type": "application/pdf", "job_size": 123456, "job_name": "My PDF document" }
דוגמה (משימת הדפסה שבוטלה על ידי המשתמש):
{ "job_id": "123", "state": "aborted", "description": "User action", "expires_in": 100, "job_type": "application/pdf", "job_size": 123456, "job_name": "My PDF document", "semantic_state": { "version": "1.0", "state": { "type": "ABORTED", "user_action_cause": {"action_code": "CANCELLED"} }, "pages_printed": 7 } }
דוגמה (משימת הדפסה שהופסקה כי הנייר נגמר). שימו לב לאזכור של מצב המכשיר. הלקוח יצטרך לשלוח קריאה ל-API /privet/info כדי לקבל פרטים נוספים על מצב המכשיר:
{ "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. שגיאות
יכול להיות שהשגיאות הבאות יוחזרו על ידי API /privet/printer/jobstate (פרטים נוספים זמינים בקטע 'שגיאות'):שגיאה | תיאור |
---|---|
invalid_print_job | בבקשה צוין מזהה משימה לא תקין או שתוקף המזהה פג. |
server_error | קבלת הסטטוס של משימת הדפסה (למשימות הדפסה שפורסמו ב-Cloud Print) נכשלה. |
invalid_x_privet_token | הערך של X-Privet-Token בבקשה לא תקין או ריק. |
אם המכשיר לא חושף את הנתיב /privet/printer/jobstate, הוא חייב להחזיר שגיאת HTTP 404. אם הכותרת X-Privet-Token חסרה, המכשיר חייב להחזיר שגיאת HTTP 400.
6. נספח
6.1. התנהגות והגדרות ברירת מחדל
בקטע הזה מוסבר על התנהגות ברירת המחדל שאנחנו מצפים מכל המכשירים שתואמים ל-Privet.- מכשירים מוכנים לשימוש צריכים לתמוך רק בממשקי ה-API /privet/info ו-/privet/register. צריך להשבית את כל שאר ממשקי ה-API (למשל, /privet/accesstoken, הדפסה מקומית).
- ההרשמה דורשת אינטראקציה פיזית עם המכשיר.
- המשתמשים צריכים לבצע פעולה פיזית במכשיר (למשל, לחיצה על לחצן) כדי לאשר את הגישה שלהם למכשיר.
- אחרי שהמשתמש מבצע את הפעולה שצוינה למעלה, המדפסת צריכה לשלוח את הבקשה /cloudprint/register. הבקשה הזו לא תישלח עד שהפעולה תתבצע (ראו דיאגרמת רצף 1).
- אם המכשיר מעבד בקשת /privet/register (לדוגמה, ממתין לפעולה שצוינה למעלה), הוא צריך לדחות את כל בקשות /privet/register האחרות. במקרה כזה, המכשיר חייב להחזיר את השגיאה device_busy.
- המכשיר צריך להפסיק את הפעולה של כל בקשת /register שלא מתקבלת בה פעולה פיזית שצוינה למעלה תוך 60 שניות. במקרה כזה, המכשיר חייב להחזיר את השגיאה confirmation_timeout.
- אופציונלי: מומלץ אבל לא חובה, הפעולות הבאות עשויות לשפר את חוויית המשתמש:
- יכול להיות שבמדפסת יהבהב אור או שיוצג מסך כדי לציין שהמשתמש צריך לבצע פעולה כדי לאשר את ההרשמה.
- יכול להיות שיוצג במסך המדפסת 'המדפסת נרשמת ל-Google Cloud Print עבור המשתמש abc@def.com – יש ללחוץ על אישור כדי להמשיך', כאשר abc@def.com הוא פרמטר המשתמש מקריאת ה-API של /register. כך יהיה ברור יותר למשתמש ש:
- הם מאשרים את בקשת ההרשמה שלהם
- מה קורה אם הוא לא יזם את הבקשה.
- בנוסף לפעולה פיזית לאישור מהמדפסת (למשל, 'לחץ על הלחצן OK'), מדפסת עשויה גם להציע למשתמש לחצן לביטול הבקשה (לדוגמה, 'יש ללחוץ על ביטול כדי לדחות'). כך משתמשים שלא הפעילו את בקשת ההרשמה יוכלו לבטל אותה לפני שחלף הזמן הקצוב של 60 שניות. במקרה כזה, המכשיר חייב להחזיר את השגיאה user_cancel.
- העברות בעלות:
- יכול להיות שהמכשיר נמחק באופן מפורש משירות הענן.
- אם המכשיר מקבל אישור שהפעולה בוצעה בהצלחה, אבל לא מקבל תיאור של המכשיר כתוצאה מקריאה ל-/cloudprint/printer (ב-GCP), הוא חייב לחזור למצב ברירת המחדל (מצב מוכן לשימוש).
- אם פרטי הכניסה של המכשיר כבר לא פועלים (באופן מפורש בגלל תגובה של השרת עם הערך invalid credentials), המכשיר חייב לחזור למצב ברירת המחדל (מצב מוכן לשימוש).
- איפוס מקומי להגדרות המקוריות חייב למחוק את פרטי הכניסה של המכשיר ולהגדיר אותו למצב ברירת מחדל.
- אופציונלי: יכול להיות שבמכשיר תהיה אפשרות בתפריט למחיקת פרטי הכניסה ולהעברה למצב ברירת מחדל.
- מכשירים שתומכים בהתראות XMPP חייבים לכלול את היכולת לשלוח פינג לשרת. חובה שהשרת יוכל לשלוט בערך הזמן הקצוב לתפוגה של הפינג באמצעות local_settings.
- המכשיר עשוי לשלוח פינג לשרת באופן מפורש (/cloudprint/printer API for GCP, בנוסף לפינגים של XMPP) לא יותר מפעם אחת ביום (24 שעות) כדי לוודא שהם מסונכרנים. מומלץ להקצות חלון אקראי לבדיקה בטווח של 24 עד 32 שעות.
- אופציונלי: במכשירי Cloud Print, מומלץ אבל לא חובה להוסיף דרך ידנית (לחצן) כדי לאפשר למשתמש להתחיל בדיקה של משימות הדפסה חדשות מהמכשיר. חלק מהמדפסות כבר כוללות את האפשרות הזו.
- אופציונלי. יכול להיות שבמדפסות לארגונים תהיה אפשרות להשבית לחלוטין את הגילוי המקומי. במקרה כזה, המכשיר חייב לעדכן את ההגדרות המקומיות האלה בשרת. ההגדרות המקומיות החדשות צריכות להיות ריקות (הגדרה של local_discovery כ-false, כלומר אפשר להפעיל אותה מחדש משירות GCP).
6.1.2 תרשים ברירת המחדל של הרישום

6.2. תקיפות XSSI ו-XSRF ומניעתן
בקטע הזה נסביר על האפשרות של התקפות XSSI ו-XSRF על המכשיר ואיך להגן מפניהן (כולל טכניקות ליצירת טוקנים).פרטים נוספים זמינים כאן: http://googleonlinesecurity.blogspot.com/2011/05/website-security-for-webmasters.html
בדרך כלל, תקיפות XSSI ו-XSRF אפשריות כשאתר משתמש במנגנוני אימות של קובצי Cookie. Google לא משתמשת בקובצי Cookie בשירות Cloud Print שלה, אבל עדיין אפשר לבצע התקפות כאלה. הגישה לרשת המקומית, מעצם טבעה, נותנת אמון מרומז לבקשות.
6.2.1. XSSI
יכול להיות שאתר זדוני ינחש את כתובת ה-IP ואת מספר היציאה של מכשיר שתואם ל-Privet, וינסה להפעיל את Privet API באמצעות src=<api name> בתוך תג <script>:<script type="text/javascript" src="http://192.168.1.42:8080/privet/info"></script>
כדי למנוע סוג כזה של מתקפה, כל הקריאות ל-Privet API חייבות לדרוש את הכותרת X-Privet-Token בבקשה. תגי סקריפט מסוג src=<api> לא יכולים להוסיף כותרות, ולכן הם מגנים מפני סוג המתקפה הזה.
6.2.2. XSRF
http://en.wikipedia.org/wiki/Cross-site_request_forgeryיכול להיות שאתר זדוני ינסה לנחש את כתובת ה-IP ואת מספר היציאה של מכשיר שתואם ל-Privet, וינסה לשלוח קריאה ל-Privet API באמצעות iframe, טפסים או מנגנון טעינה אחר של אתרים שונים. התוקפים לא יוכלו לגשת לתוצאות הבקשה, אבל אם הבקשה תבצע פעולה (למשל הדפסה), הם יוכלו להפעיל אותה.
כדי למנוע את ההתקפה הזו, אנחנו צריכים את ההגנה הבאה:
- השארת API פתוח ל-XSRF
- API /privet/info לא יכול לבצע פעולות במכשיר
- שימוש ב-API /privet/info כדי לקבל x-privet-token
- כל שאר ממשקי ה-API חייבים לבדוק אם יש טוקן x-privet-token תקין בכותרת X-Privet-Token.
- הטוקן x-privet-token צריך להיות תקף ל-24 שעות בלבד.
גם אם תוקף יצליח להפעיל את API /privet/info, הוא לא יוכל לקרוא את x-privet-token מהתגובה ולכן לא יוכל להפעיל אף API אחר.
מומלץ מאוד ליצור את אסימון ה-XSRF באמצעות האלגוריתם הבא:
XSRF_token = base64( SHA1(device_secret + DELIMITER + issue_timecounter) + DELIMITER + issue_timecounter )
אלמנטים ליצירת טוקן XSRF:
- DELIMITER הוא תו מיוחד, בדרך כלל ':'
- issue_timecounter הוא מספר השניות שעברו מאז אירוע מסוים (תקופה לאורך זמן לסימן זמן) או מאז זמן האתחול של המכשיר (למדדי CPU). הערך של issue_timecounter עולה כל הזמן כשהמכשיר פועל (ראו אימות טוקן בהמשך).
- SHA1 – פונקציית גיבוב באמצעות אלגוריתם SHA1
- base64 – קידוד base64
- device_secret – סוד שספציפי למכשיר. חובה לעדכן את הסוד של המכשיר בכל הפעלה מחדש.
דרכים מומלצות ליצירת סוד המכשיר:
- יצירת מזהה ייחודי אוניברסלי (UUID) חדש בכל הפעלה מחדש
- יצירת מספר אקראי של 64 ביט בכל הפעלה מחדש
המכשיר לא נדרש לאחסן את כל טוקני ה-XSRF שהוא הנפיק. כשהמכשיר צריך לאמת את התוקף של אסימון XSRF, הוא צריך לבצע פענוח Base64 של האסימון. מקבלים את issue_timecounter מהחלק השני (טקסט גלוי), ומנסים ליצור גיבוב SHA1 של device_secret + DELIMITER + issue_timecounter, כאשר issue_timecounter הוא מהטוקן. אם ה-SHA1 החדש שנוצר זהה ל-SHA1 באסימון, המכשיר צריך לבדוק אם issue_timecounter נמצא בטווח התוקף (24 שעות) של מונה הזמן הנוכחי. לשם כך, המכשיר לוקח את מונה הזמן הנוכחי (לדוגמה, מונה המעבד) ומחסר ממנו את issue_timecounter. התוצאה חייבת להיות מספר השניות מאז הנפקת האסימון.
חשוב: זו הדרך המומלצת להטמעת הגנה מפני XSRF. לקוחות של מפרט Privet לא צריכים לנסות להבין את טוקן ה-XSRF, אלא להתייחס אליו כאל קופסה שחורה. איור 6.2.3 מציג דרך מומלצת להטמעה של X-Privet-Token ולאימות של בקשה טיפוסית.
6.2.3 תרשים רצף של יצירה ואימות של טוקן X-Privet

6.3. דיאגרמות של תהליכי עבודה
בסעיף הזה נציג תרחיש לדוגמה של תהליך עבודה במקרים שונים.6.3.1. תהליך העבודה של מדפסת חדשה

6.3.2. הפעלה של מדפסת רשומה

6.3.3 תהליך העבודה של טיפול בהתראות XMPP

6.3.4. בדיקת תהליך העבודה של הגדרות המדפסת
