Trusty API का रेफ़रंस

Trusty, दो तरह के ऐप्लिकेशन और सेवाओं को डेवलप करने के लिए एपीआई उपलब्ध कराता है:

  • TEE प्रोसेसर पर काम करने वाले भरोसेमंद ऐप्लिकेशन और सेवाएं
  • सामान्य और गैर-भरोसेमंद ऐप्लिकेशन, जो मुख्य प्रोसेसर पर चलते हैं और भरोसेमंद ऐप्लिकेशन की दी गई सेवाओं का इस्तेमाल करते हैं

Trusty एपीआई, आम तौर पर Trusty इंटर-प्रोसेस कम्यूनिकेशन (आईपीसी) सिस्टम के बारे में बताता है. इसमें, असुरक्षित दुनिया के साथ होने वाले कम्यूनिकेशन भी शामिल हैं. मुख्य प्रोसेसर पर चलने वाला सॉफ़्टवेयर, भरोसेमंद ऐप्लिकेशन और सेवाओं से कनेक्ट करने के लिए, Trusty API का इस्तेमाल कर सकता है. साथ ही, आईपी पर नेटवर्क सेवा की तरह ही, उनसे मनमुताबिक मैसेज भी शेयर कर सकता है. ऐप्लिकेशन-लेवल प्रोटोकॉल का इस्तेमाल करके, ऐप्लिकेशन यह तय करता है कि इन मैसेज का डेटा फ़ॉर्मैट और सेमेटिक्स क्या होगा. मैसेज की भरोसेमंद डिलीवरी के लिए, मुख्य प्रोसेसर पर चलने वाले ड्राइवर के तौर पर मौजूद Trusty इन्फ़्रास्ट्रक्चर की गारंटी दी जाती है. साथ ही, यह पूरी तरह से असाइनोक्रोनस (एक साथ काम न करने वाला) होता है.

पोर्ट और चैनल

भरोसेमंद ऐप्लिकेशन, सेवा के एंडपॉइंट को नाम वाले पाथ के तौर पर दिखाने के लिए, पोर्ट का इस्तेमाल करते हैं. क्लाइंट इस पाथ से कनेक्ट होते हैं. इससे क्लाइंट के लिए, स्ट्रिंग पर आधारित एक आसान सेवा आईडी मिलता है. नाम रखने का तरीका, रिवर्स-डीएनएस-स्टाइल के हिसाब से होना चाहिए, जैसे कि com.google.servicename.

जब कोई क्लाइंट किसी पोर्ट से कनेक्ट होता है, तो उसे किसी सेवा के साथ इंटरैक्ट करने के लिए एक चैनल मिलता है. सेवा को इनकमिंग कनेक्शन स्वीकार करना चाहिए. ऐसा करने पर, उसे भी एक चैनल मिलता है. असल में, पोर्ट का इस्तेमाल सेवाओं को खोजने के लिए किया जाता है . इसके बाद, कनेक्ट किए गए चैनलों (जैसे, कनेक्शन इंस्टेंस हो सकते हैं). जब कोई क्लाइंट किसी पोर्ट से कनेक्ट होता है, तो एक सममित, दोतरफ़ा कनेक्शन बनता है. इस फ़ुल-डुपलेक्स पाथ का इस्तेमाल करके, क्लाइंट और सर्वर तब तक मनमुताबिक मैसेज एक्सचेंज कर सकते हैं, जब तक कि कोई भी पक्ष कनेक्शन को बंद करने का फ़ैसला न ले ले.

सिर्फ़ सुरक्षित पक्ष के भरोसेमंद ऐप्लिकेशन या Trusty kernel मॉड्यूल ही पोर्ट बना सकते हैं. सामान्य दुनिया में, सुरक्षित नहीं वाले साइड पर चलने वाले ऐप्लिकेशन, सिर्फ़ सुरक्षित साइड से पब्लिश की गई सेवाओं से कनेक्ट कर सकते हैं.

ज़रूरतों के हिसाब से, भरोसेमंद ऐप्लिकेशन एक ही समय पर क्लाइंट और सर्वर, दोनों हो सकता है. भरोसेमंद ऐप्लिकेशन, किसी सेवा को (सर्वर के तौर पर) पब्लिश करता है. ऐसे में, हो सकता है कि उसे अन्य सेवाओं से (क्लाइंट के तौर पर) कनेक्ट करना पड़े.

Handle API

हैंडल, बिना साइन वाले पूर्णांक होते हैं. ये पोर्ट और चैनल जैसे रिसॉर्स को दिखाते हैं. ये UNIX में फ़ाइल डिस्क्रिप्टर की तरह ही होते हैं. हैंडल बनाने के बाद, उन्हें ऐप्लिकेशन के हिसाब से हैंडल टेबल में रखा जाता है. इनका रेफ़रंस बाद में दिया जा सकता है.

कॉलर, set_cookie() तरीके का इस्तेमाल करके, निजी डेटा को हैंडल से जोड़ सकता है.

Handle API में मौजूद तरीके

हैंडल सिर्फ़ किसी ऐप्लिकेशन के कॉन्टेक्स्ट में मान्य होते हैं. किसी ऐप्लिकेशन को, हैंडल की वैल्यू दूसरे ऐप्लिकेशन को तब तक नहीं देनी चाहिए, जब तक इसके लिए साफ़ तौर पर न कहा गया हो. हैंडल की वैल्यू का विश्लेषण सिर्फ़ INVALID_IPC_HANDLE #define, के साथ तुलना करके किया जाना चाहिए. ऐप्लिकेशन, हैंडल के अमान्य या सेट न होने के संकेत के तौर पर इसका इस्तेमाल कर सकता है.

कॉल करने वाले व्यक्ति के दिए गए निजी डेटा को किसी खास हैंडल से जोड़ता है.

long set_cookie(uint32_t handle, void *cookie)

[in] handle: एपीआई कॉल में से किसी एक से मिला कोई भी हैंडल

[in] cookie: Trusty ऐप्लिकेशन में, उपयोगकर्ता के स्पेस में मौजूद डेटा का पॉइंटर

[retval]: NO_ERROR सफल होने पर, < 0 गड़बड़ी का कोड

यह कॉल, इवेंट को हैंडल करने के लिए तब काम आता है, जब वे हैंडल बनाने के बाद किसी बाद के समय पर होते हैं. इवेंट हैंडल करने की सुविधा, हैंडल और उसकी कुकी को इवेंट हैंडलर को वापस भेजती है.

wait() कॉल का इस्तेमाल करके, हैंडल के लिए इवेंट का इंतज़ार किया जा सकता है.

wait()

यह किसी दिए गए हैंडल पर, तय समयावधि के लिए इवेंट होने का इंतज़ार करता है.

long wait(uint32_t handle_id, uevent_t *event, unsigned long timeout_msecs)

[in] handle_id: एपीआई कॉल में से किसी एक से मिला कोई भी हैंडल

[out] event: इस हैंडल पर हुए इवेंट को दिखाने वाले स्ट्रक्चर का पॉइंटर

[in] timeout_msecs: मिलीसेकंड में टाइम आउट की वैल्यू; -1 वैल्यू का मतलब है कि टाइम आउट अनलिमिटेड है

[retval]: NO_ERROR अगर तय किए गए टाइम आउट इंटरवल के अंदर कोई मान्य इवेंट हुआ है; ERR_TIMED_OUT अगर तय किया गया टाइम आउट बीत गया है, लेकिन कोई इवेंट नहीं हुआ है; < 0 अन्य गड़बड़ियों के लिए

सफल होने पर (retval == NO_ERROR), wait() कॉल, किसी तय uevent_t स्ट्रक्चर में, हुए इवेंट की जानकारी भरता है.

typedef struct uevent {
    uint32_t handle; /* handle this event is related to */
    uint32_t event;  /* combination of IPC_HANDLE_POLL_XXX flags */
    void    *cookie; /* cookie associated with this handle */
} uevent_t;

event फ़ील्ड में इन वैल्यू का कॉम्बिनेशन होता है:

enum {
  IPC_HANDLE_POLL_NONE    = 0x0,
  IPC_HANDLE_POLL_READY   = 0x1,
  IPC_HANDLE_POLL_ERROR   = 0x2,
  IPC_HANDLE_POLL_HUP     = 0x4,
  IPC_HANDLE_POLL_MSG     = 0x8,
  IPC_HANDLE_POLL_SEND_UNBLOCKED = 0x10,
   more values[TBD]
};

IPC_HANDLE_POLL_NONE - असल में कोई इवेंट लंबित नहीं है, कॉल करने वाले को इंतज़ार फिर से शुरू करना चाहिए

IPC_HANDLE_POLL_ERROR - कोई अंदरूनी गड़बड़ी हुई है, जिसकी जानकारी नहीं दी गई है

IPC_HANDLE_POLL_READY - यह हैंडल टाइप पर निर्भर करता है. जैसे:

  • पोर्ट के लिए, यह वैल्यू बताती है कि कोई कनेक्शन बाकी है
  • चैनलों के लिए, यह वैल्यू बताती है कि एक साथ काम न करने वाला कनेक्शन (connect() देखें) सेट अप किया गया था

नीचे दिए गए इवेंट सिर्फ़ चैनलों के लिए काम के हैं:

  • IPC_HANDLE_POLL_HUP - यह बताता है कि किसी चैनल को किसी दूसरे चैनल ने बंद कर दिया है
  • IPC_HANDLE_POLL_MSG - इससे पता चलता है कि इस चैनल के लिए कोई मैसेज स्वीकार करना बाकी है
  • IPC_HANDLE_POLL_SEND_UNBLOCKED - इससे पता चलता है कि पहले मैसेज भेजने से ब्लॉक किया गया कॉलर, फिर से मैसेज भेजने की कोशिश कर सकता है. ज़्यादा जानकारी के लिए, send_msg() का ब्यौरा देखें

इवेंट हैंडलर को तय किए गए इवेंट के कॉम्बिनेशन को हैंडल करने के लिए तैयार होना चाहिए, क्योंकि एक ही समय पर कई बिट सेट किए जा सकते हैं. उदाहरण के लिए, किसी चैनल के लिए, ऐसे मैसेज हो सकते हैं जिन्हें पढ़ा नहीं गया है. साथ ही, हो सकता है कि किसी पीयर ने चैनल से कनेक्शन बंद कर दिया हो.

ज़्यादातर इवेंट स्टिक होते हैं. ये तब तक बने रहते हैं, जब तक कि बुनियादी शर्तें पूरी होती हैं. उदाहरण के लिए, जब तक सभी मैसेज मिल जाते हैं और कनेक्ट करने के बाकी अनुरोधों को मैनेज कर लिया जाता है. हालांकि, IPC_HANDLE_POLL_SEND_UNBLOCKED इवेंट के लिए ऐसा नहीं होता. इसे पढ़ने के बाद मिटा दिया जाता है और ऐप्लिकेशन के पास इसे मैनेज करने का सिर्फ़ एक मौका होता है.

close() तरीके को कॉल करके, हैंडल को मिटाया जा सकता है.

close()

यह फ़ंक्शन, दिए गए हैंडल से जुड़े संसाधन को मिटा देता है और उसे हैंडल टेबल से हटा देता है.

long close(uint32_t handle_id);

[in] handle_id: हटाने के लिए हैंडल

[retval]: अगर फ़ंक्शन सही तरीके से काम करता है, तो 0 दिखेगा. अगर नहीं, तो कोई गड़बड़ी दिखेगी

Server API

सर्वर, अपनी सेवा के एंड-पॉइंट दिखाने के लिए, एक या उससे ज़्यादा नाम वाले पोर्ट बनाता है. हर पोर्ट को हैंडल से दिखाया जाता है.

Server API में मौजूद तरीके

port_create()

नाम वाला सेवा पोर्ट बनाता है.

long port_create (const char *path, uint num_recv_bufs, size_t recv_buf_size,
uint32_t flags)

[in] path: पोर्ट का स्ट्रिंग नाम (जैसा कि ऊपर बताया गया है). यह नाम, पूरे सिस्टम में यूनीक होना चाहिए. डुप्लीकेट नाम बनाने की कोशिश करने पर, गड़बड़ी का मैसेज दिखता है.

[in] num_recv_bufs: इस पोर्ट पर मौजूद चैनल, क्लाइंट के साथ डेटा एक्सचेंज करने के लिए, पहले से ज़्यादा से ज़्यादा कितने बफ़र असाइन कर सकता है. दोनों दिशाओं में जाने वाले डेटा के लिए, बफ़र की गिनती अलग-अलग की जाती है. इसलिए, यहां एक बताने का मतलब है कि एक भेजने और एक पाने वाले बफ़र पहले से तय किए गए हैं. आम तौर पर, ज़रूरी बफ़र की संख्या, क्लाइंट और सर्वर के बीच के प्रोटोकॉल के समझौते के लेवल पर निर्भर करती है. बहुत सिंक्रोनस प्रोटोकॉल (मैसेज भेजें, दूसरा मैसेज भेजने से पहले जवाब पाएं) के मामले में, यह संख्या एक भी हो सकती है. हालांकि, अगर क्लाइंट को जवाब मिलने से पहले एक से ज़्यादा मैसेज भेजने की उम्मीद है, तो मैसेज की संख्या ज़्यादा हो सकती है.उदाहरण के लिए, एक मैसेज प्रॉलोग के तौर पर और दूसरा असली निर्देश के तौर पर. हर चैनल के लिए, बफ़र सेट तय किए जाते हैं. इसलिए, दो अलग-अलग कनेक्शन (चैनल) के लिए, अलग-अलग बफ़र सेट होंगे.

[in] recv_buf_size: ऊपर दिए गए बफ़र सेट में, हर बफ़र का ज़्यादा से ज़्यादा साइज़. यह वैल्यू प्रोटोकॉल पर निर्भर करती है. साथ ही, यह उस मैसेज के साइज़ को सीमित करती है जिसे पीयर के साथ शेयर किया जा सकता है

[in] flags: फ़्लैग का ऐसा कॉम्बिनेशन जो पोर्ट के काम करने के तरीके के बारे में बताता है

यह वैल्यू, इन वैल्यू का कॉम्बिनेशन होनी चाहिए:

IPC_PORT_ALLOW_TA_CONNECT - अन्य सुरक्षित ऐप्लिकेशन से कनेक्ट करने की अनुमति देता है

IPC_PORT_ALLOW_NS_CONNECT - असुरक्षित नेटवर्क से कनेक्शन की अनुमति देता है

[retval]: अगर वैल्यू शून्य से बड़ी है, तो बनाए गए पोर्ट का हैंडल. अगर वैल्यू शून्य से कम है, तो कोई गड़बड़ी

इसके बाद, सर्वर wait() कॉल का इस्तेमाल करके, आने वाले कनेक्शन के लिए पोर्ट हैंडल की सूची को पोल करता है. uevent_t स्ट्रक्चर के event फ़ील्ड में IPC_HANDLE_POLL_READY बिट सेट करके, कनेक्शन का अनुरोध मिलने पर, सर्वर को accept() को कॉल करके कनेक्शन पूरा करना चाहिए और एक चैनल बनाना चाहिए. इस चैनल को किसी दूसरे हैंडल से दिखाया जाता है. इसके बाद, आने वाले मैसेज के लिए इस चैनल को पोल किया जा सकता है.

accept()

इनकमिंग कनेक्शन स्वीकार करता है और चैनल का हैंडल पाता है.

long accept(uint32_t handle_id, uuid_t *peer_uuid);

[in] handle_id: उस पोर्ट को दिखाने वाला हैंडल जिससे क्लाइंट कनेक्ट है

[out] peer_uuid: uuid_t स्ट्रक्चर का पॉइंटर, जिसे कनेक्ट करने वाले क्लाइंट ऐप्लिकेशन के यूयूआईडी से भरा जाएगा. अगर कनेक्शन असुरक्षित दुनिया से शुरू हुआ है, तो इसे सभी शून्य पर सेट किया जाता है

[retval]: किसी चैनल का हैंडल (अगर यह शून्य से बड़ी वैल्यू है), जिस पर सर्वर, क्लाइंट के साथ मैसेज एक्सचेंज कर सकता है (अन्यथा गड़बड़ी का कोड)

Client API

इस सेक्शन में, क्लाइंट एपीआई के तरीके शामिल हैं.

क्लाइंट एपीआई में मौजूद तरीके

connect()

नाम से तय किए गए पोर्ट से कनेक्शन शुरू करता है.

long connect(const char *path, uint flags);

[hi] path: भरोसेमंद ऐप्लिकेशन के पब्लिश किए गए पोर्ट का नाम

[in] flags: अतिरिक्त और वैकल्पिक व्यवहार के बारे में बताता है

[retval]: उस चैनल का हैंडल जिस पर सर्वर के साथ मैसेज शेयर किए जा सकते हैं. अगर यह वैल्यू अमान्य है, तो गड़बड़ी का मैसेज दिखेगा

अगर कोई flags नहीं दिया गया है (flags पैरामीटर 0 पर सेट है), तो connect() को कॉल करने पर, किसी तय पोर्ट से सिंक्रोनस कनेक्शन शुरू होता है. अगर पोर्ट मौजूद नहीं है, तो यह तुरंत गड़बड़ी दिखाता है और तब तक ब्लॉक बना रहता है, जब तक कि सर्वर किसी दूसरे कनेक्शन को स्वीकार नहीं कर लेता.

इस व्यवहार को बदला जा सकता है. इसके लिए, दो वैल्यू का कॉम्बिनेशन तय करना होगा. इन वैल्यू के बारे में यहां बताया गया है:

enum {
IPC_CONNECT_WAIT_FOR_PORT = 0x1,
IPC_CONNECT_ASYNC = 0x2,
};

IPC_CONNECT_WAIT_FOR_PORT - अगर तय किया गया पोर्ट, प्रोसेस के दौरान तुरंत मौजूद नहीं होता है, तो connect() कॉल को इंतज़ार करने के लिए मजबूर करता है.

IPC_CONNECT_ASYNC - अगर सेट किया जाता है, तो असाइनमेंट के साथ-साथ कनेक्शन भी शुरू हो जाता है. किसी ऐप्लिकेशन को सामान्य काम शुरू करने से पहले, uevent_t स्ट्रक्चर के इवेंट फ़ील्ड में सेट किए गए IPC_HANDLE_POLL_READY बिट से दिखाए गए कनेक्शन पूरा होने के इवेंट के लिए, wait() को कॉल करके, दिखाए गए हैंडल के लिए पोल करना होगा.

Messaging API

Messaging API कॉल की मदद से, पहले से सेट किए गए कनेक्शन (चैनल) पर मैसेज भेजे और पढ़े जा सकते हैं. सर्वर और क्लाइंट के लिए, Messaging API कॉल एक जैसे होते हैं.

क्लाइंट को connect() कॉल करके, चैनल का हैंडल मिलता है. साथ ही, सर्वर को ऊपर बताए गए accept() कॉल से चैनल का हैंडल मिलता है.

भरोसेमंद मैसेज का स्ट्रक्चर

यहां दिखाए गए उदाहरण में बताया गया है कि Trusty API के ज़रिए भेजे गए मैसेज का स्ट्रक्चर बहुत कम होता है. इसलिए, असली कॉन्टेंट के सेमेटिक्स पर सहमति बनाने की ज़िम्मेदारी सर्वर और क्लाइंट की होती है:

/*
 *  IPC message
 */
typedef struct iovec {
        void   *base;
        size_t  len;
} iovec_t;

typedef struct ipc_msg {
        uint     num_iov; /* number of iovs in this message */
        iovec_t  *iov;    /* pointer to iov array */

        uint     num_handles; /* reserved, currently not supported */
        handle_t *handles;    /* reserved, currently not supported */
} ipc_msg_t;

किसी मैसेज में एक या एक से ज़्यादा ऐसे बफ़र हो सकते हैं जो एक-दूसरे से जुड़े न हों. इन्हें iovec_t स्ट्रक्चर के कलेक्शन से दिखाया जाता है. Trusty, iov कलेक्शन का इस्तेमाल करके, इन ब्लॉक में स्कैटर-इकट्ठा करने वाली कार्रवाइयां करता है. iov कलेक्शन की मदद से, बफ़र में मौजूद कॉन्टेंट के बारे में पूरी तरह से मनमुताबिक जानकारी दी जा सकती है.

Messaging API में मौजूद तरीके

send_msg()

किसी चैनल पर मैसेज भेजता है.

long send_msg(uint32_t handle, ipc_msg_t *msg);

[in] handle: उस चैनल का हैंडल जिस पर मैसेज भेजना है

[in] msg: मैसेज की जानकारी देने वाले ipc_msg_t structure का पॉइंटर

[retval]: सफल होने पर भेजे गए बाइट की कुल संख्या; अगर सफल नहीं होता है, तो गड़बड़ी का मैसेज

अगर क्लाइंट (या सर्वर) चैनल पर मैसेज भेजने की कोशिश कर रहा है और डेस्टिनेशन पीयर मैसेज की सूची में कोई जगह नहीं है, तो चैनल 'मैसेज भेजने पर रोक' स्थिति में जा सकता है. ऐसा, सिंक किए गए अनुरोध/जवाब वाले सामान्य प्रोटोकॉल के लिए कभी नहीं होना चाहिए. हालांकि, यह ज़्यादा मुश्किल मामलों में हो सकता है. इस स्थिति का पता, ERR_NOT_ENOUGH_BUFFER गड़बड़ी कोड दिखाकर लगाया जाता है. ऐसे मामले में, कॉलर को तब तक इंतज़ार करना होगा, जब तक कि पियर अपनी रिसीव सूची में कुछ जगह खाली न कर दे. ऐसा, मैसेज को मैनेज करके और उन्हें हटाकर किया जाता है. इसकी जानकारी, wait() कॉल से मिले uevent_t स्ट्रक्चर के event फ़ील्ड में सेट किए गए IPC_HANDLE_POLL_SEND_UNBLOCKED बिट से मिलती है.

get_msg()

आने वाले मैसेज की सूची में अगले मैसेज की मेटा-जानकारी मिलती है

पर जाएं.

long get_msg(uint32_t handle, ipc_msg_info_t *msg_info);

[in] handle: उस चैनल का हैंडल जिस पर नया मैसेज वापस पाना है

[out] msg_info: मैसेज की जानकारी का स्ट्रक्चर यहां बताया गया है:

typedef struct ipc_msg_info {
        size_t    len;  /* total message length */
        uint32_t  id;   /* message id */
} ipc_msg_info_t;

हर मैसेज को बाकी बचे मैसेज के सेट में एक यूनीक आईडी असाइन किया जाता है. साथ ही, हर मैसेज की कुल लंबाई भरी जाती है. अगर प्रोटोकॉल के हिसाब से कॉन्फ़िगर किया गया है और अनुमति दी गई है, तो किसी चैनल के लिए एक साथ कई मैसेज खुले हो सकते हैं.

[retval]: NO_ERROR सफल होने पर; अन्यथा गड़बड़ी का कोड

read_msg()

दिए गए आईडी वाले मैसेज का कॉन्टेंट पढ़ता है. यह कॉन्टेंट, दिए गए ऑफ़सेट से शुरू होता है.

long read_msg(uint32_t handle, uint32_t msg_id, uint32_t offset, ipc_msg_t
*msg);

[in] handle: उस चैनल का हैंडल जिसका मैसेज पढ़ना है

[in] msg_id: पढ़े जाने वाले मैसेज का आईडी

[in] offset: मैसेज में वह ऑफ़सेट जहां से पढ़ना शुरू करना है

[out] msg: ipc_msg_t स्ट्रक्चर का पॉइंटर, जिसमें इनकमिंग मैसेज का डेटा स्टोर करने के लिए बफ़र का एक सेट बताया गया है

[retval]: msg बफ़र में सेव किए गए बाइट की कुल संख्या, अगर फ़ंक्शन सही तरीके से काम करता है, तो यह संख्या दिखेगी. अगर फ़ंक्शन काम नहीं करता है, तो गड़बड़ी की जानकारी दिखेगी

read_msg तरीके को ज़रूरत के हिसाब से, अलग-अलग (ज़रूरी नहीं कि क्रम में) ऑफ़सेट से कई बार कॉल किया जा सकता है.

put_msg()

किसी खास आईडी वाले मैसेज को हटाता है.

long put_msg(uint32_t handle, uint32_t msg_id);

[hi] handle: उस चैनल का हैंडल जिस पर मैसेज आया है

[in] msg_id: उस मैसेज का आईडी जिसे हटाया जा रहा है

[retval]: NO_ERROR सफल होने पर; अन्यथा कोई गड़बड़ी

मैसेज को मिटाने और उससे जुड़े बफ़र को खाली करने के बाद, मैसेज का कॉन्टेंट ऐक्सेस नहीं किया जा सकता.

File Descriptor API

फ़ाइल की जानकारी देने वाले एपीआई में read(), write(), और ioctl() कॉल शामिल हैं. ये सभी कॉल, फ़ाइल डिस्क्रिप्टर के पहले से तय (स्टैटिक) सेट पर काम कर सकते हैं. आम तौर पर, इन फ़ाइल डिस्क्रिप्टर को छोटे नंबर से दिखाया जाता है. फ़िलहाल, फ़ाइल डिस्क्रिप्टर स्पेस और आईपीसी हैंडल स्पेस अलग-अलग होते हैं. Trusty में मौजूद File Descriptor API, फ़ाइल डिस्क्रिप्टर पर आधारित पारंपरिक एपीआई से मिलता-जुलता है.

डिफ़ॉल्ट रूप से, पहले से तय किए गए तीन (स्टैंडर्ड और अच्छी तरह से जाने-पहचाने) फ़ाइल डिस्क्रिप्टर होते हैं:

  • 0 - स्टैंडर्ड इनपुट. स्टैंडर्ड इनपुट fd का डिफ़ॉल्ट तौर पर लागू होना कोई काम का नहीं है. ऐसा इसलिए, क्योंकि भरोसेमंद ऐप्लिकेशन में इंटरैक्टिव कंसोल नहीं होना चाहिए. इसलिए, fd 0 पर ioctl() को पढ़ने, लिखने या उसे शुरू करने पर, ERR_NOT_SUPPORTED गड़बड़ी का मैसेज दिखना चाहिए.
  • 1 - स्टैंडर्ड आउटपुट. स्टैंडर्ड आउटपुट में लिखे गए डेटा को UART और/या ऐसे मेमोरी लॉग पर भेजा जा सकता है जो प्लैटफ़ॉर्म और कॉन्फ़िगरेशन के आधार पर, सुरक्षित नहीं है. यह डेटा, LK डीबग लेवल पर निर्भर करता है. गैर-गंभीर डीबग लॉग और मैसेज, स्टैंडर्ड आउटपुट में दिखने चाहिए. read() और ioctl() के तरीकों का कोई असर नहीं होता. साथ ही, इनसे ERR_NOT_SUPPORTED गड़बड़ी का मैसेज मिलना चाहिए.
  • 2 - स्टैंडर्ड गड़बड़ी. स्टैंडर्ड गड़बड़ी में लिखे गए डेटा को, प्लैटफ़ॉर्म और कॉन्फ़िगरेशन के आधार पर, गैर-सुरक्षित साइड पर उपलब्ध UART या मेमोरी लॉग पर भेजा जाना चाहिए. हमारा सुझाव है कि स्टैंडर्ड गड़बड़ी के लिए सिर्फ़ गंभीर मैसेज लिखें, क्योंकि इस स्ट्रीम को अनथ्रॉटल किए जाने की संभावना बहुत ज़्यादा होती है. read() और ioctl() तरीके काम नहीं करते और इनसे ERR_NOT_SUPPORTED गड़बड़ी दिखनी चाहिए.

फ़ाइल डिस्क्रिप्टर के इस सेट को ज़्यादा fds लागू करने के लिए बड़ा किया जा सकता है (प्लैटफ़ॉर्म के हिसाब से एक्सटेंशन लागू करने के लिए). हालांकि, फ़ाइल डिस्क्रिप्टर को बड़ा करते समय सावधानी बरतने की ज़रूरत है. फ़ाइल डिस्क्रिप्टर को बड़ा करने से, अक्सर समस्याएं आ सकती हैं. इसलिए, आम तौर पर इसका सुझाव नहीं दिया जाता.

File Descriptor API में मौजूद तरीके

read()

किसी फ़ाइल डिस्क्रिप्टर से count बाइट तक का डेटा पढ़ने की कोशिश करता है.

long read(uint32_t fd, void *buf, uint32_t count);

[in] fd: वह फ़ाइल डिस्क्रिप्टर जिससे पढ़ना है

[out] buf: डेटा सेव करने के लिए बफ़र का पॉइंटर

[in] count: पढ़ने के लिए ज़्यादा से ज़्यादा बाइट

[retval]: पढ़े गए बाइट की संख्या दिखाता है. अगर कोई गड़बड़ी होती है, तो नेगेटिव वैल्यू दिखती है

write()

फ़ाइल के ब्यौरे में count बाइट तक का डेटा लिखता है.

long write(uint32_t fd, void *buf, uint32_t count);

[in] fd: वह फ़ाइल जिस पर डेटा लिखना है

[out] buf: लिखे जाने वाले डेटा का पॉइंटर

[in] count: लिखने के लिए बाइट की ज़्यादा से ज़्यादा संख्या

[retval]: लिखे गए बाइट की संख्या दिखाता है. अगर कोई गड़बड़ी होती है, तो नेगेटिव वैल्यू दिखती है

ioctl()

किसी फ़ाइल डिस्क्रिप्टर के लिए, ioctl कमांड को लागू करता है.

long ioctl(uint32_t fd, uint32_t cmd, void *args);

[in] fd: फ़ाइल का ब्यौरा, जिस पर ioctl() को लागू करना है

[in] cmd: ioctl निर्देश

[इन/आउट] args: ioctl() आर्ग्युमेंट का पॉइंटर

अन्य एपीआई

Miscellaneous API में मौजूद तरीके

gettime()

सिस्टम का मौजूदा समय (नैनोसेकंड में) दिखाता है.

long gettime(uint32_t clock_id, uint32_t flags, int64_t *time);

[in] clock_id: प्लैटफ़ॉर्म पर निर्भर करता है; डिफ़ॉल्ट के तौर पर शून्य पास करें

[in] flags: रिज़र्व किया गया, शून्य होना चाहिए

[out] time: int64_t वैल्यू का पॉइंटर, जिसमें मौजूदा समय सेव करना है

[retval]: NO_ERROR सफल होने पर; अन्यथा कोई गड़बड़ी

nanosleep()

कॉल करने वाले ऐप्लिकेशन को तय समय के लिए निलंबित कर देता है और उस समयसीमा के बाद उसे फिर से शुरू कर देता है.

long nanosleep(uint32_t clock_id, uint32_t flags, uint64_t sleep_time)

[in] clock_id: रिज़र्व किया गया, शून्य होना चाहिए

[in] flags: रिज़र्व किया गया, शून्य होना चाहिए

[in] sleep_time: नींद में बीता कुल समय, नैनोसेकंड में

[retval]: NO_ERROR सफल होने पर; अन्यथा कोई गड़बड़ी

भरोसेमंद ऐप्लिकेशन सर्वर का उदाहरण

यहां दिए गए सैंपल ऐप्लिकेशन में, ऊपर दिए गए एपीआई के इस्तेमाल के बारे में बताया गया है. सैंपल, "इको" सेवा बनाता है, जो कई इनकमिंग कनेक्शन को मैनेज करता है. साथ ही, कॉल करने वाले व्यक्ति को वे सभी मैसेज दिखाता है जो उसे सुरक्षित या असुरक्षित साइड से मिले क्लाइंट से मिलते हैं.

#include <uapi/err.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <trusty_ipc.h>
#define LOG_TAG "echo_srv"
#define TLOGE(fmt, ...) \
    fprintf(stderr, "%s: %d: " fmt, LOG_TAG, __LINE__, ##__VA_ARGS__)

# define MAX_ECHO_MSG_SIZE 64

static
const char * srv_name = "com.android.echo.srv.echo";

static uint8_t msg_buf[MAX_ECHO_MSG_SIZE];

/*
 *  Message handler
 */
static int handle_msg(handle_t chan) {
  int rc;
  struct iovec iov;
  ipc_msg_t msg;
  ipc_msg_info_t msg_inf;

  iov.iov_base = msg_buf;
  iov.iov_len = sizeof(msg_buf);

  msg.num_iov = 1;
  msg.iov = &iov;
  msg.num_handles = 0;
  msg.handles = NULL;

  /* get message info */
  rc = get_msg(chan, &msg_inf);
  if (rc == ERR_NO_MSG)
    return NO_ERROR; /* no new messages */

  if (rc != NO_ERROR) {
    TLOGE("failed (%d) to get_msg for chan (%d)\n",
      rc, chan);
    return rc;
  }

  /* read msg content */
  rc = read_msg(chan, msg_inf.id, 0, &msg);
  if (rc < 0) {
    TLOGE("failed (%d) to read_msg for chan (%d)\n",
      rc, chan);
    return rc;
  }

  /* update number of bytes received */
  iov.iov_len = (size_t) rc;

  /* send message back to the caller */
  rc = send_msg(chan, &msg);
  if (rc < 0) {
    TLOGE("failed (%d) to send_msg for chan (%d)\n",
      rc, chan);
    return rc;
  }

  /* retire message */
  rc = put_msg(chan, msg_inf.id);
  if (rc != NO_ERROR) {
    TLOGE("failed (%d) to put_msg for chan (%d)\n",
      rc, chan);
    return rc;
  }

  return NO_ERROR;
}

/*
 *  Channel event handler
 */
static void handle_channel_event(const uevent_t * ev) {
  int rc;

  if (ev->event & IPC_HANDLE_POLL_MSG) {
    rc = handle_msg(ev->handle);
    if (rc != NO_ERROR) {
      /* report an error and close channel */
      TLOGE("failed (%d) to handle event on channel %d\n",
        rc, ev->handle);
      close(ev->handle);
    }
    return;
  }
  if (ev->event & IPC_HANDLE_POLL_HUP) {
    /* closed by peer. */
    close(ev->handle);
    return;
  }
}

/*
 *  Port event handler
 */
static void handle_port_event(const uevent_t * ev) {
  uuid_t peer_uuid;

  if ((ev->event & IPC_HANDLE_POLL_ERROR) ||
    (ev->event & IPC_HANDLE_POLL_HUP) ||
    (ev->event & IPC_HANDLE_POLL_MSG) ||
    (ev->event & IPC_HANDLE_POLL_SEND_UNBLOCKED)) {
    /* should never happen with port handles */
    TLOGE("error event (0x%x) for port (%d)\n",
      ev->event, ev->handle);
    abort();
  }
  if (ev->event & IPC_HANDLE_POLL_READY) {
    /* incoming connection: accept it */
    int rc = accept(ev->handle, &peer_uuid);
    if (rc < 0) {
      TLOGE("failed (%d) to accept on port %d\n",
        rc, ev->handle);
      return;
    }
    handle_t chan = rc;
    while (true){
      struct uevent cev;

      rc = wait(chan, &cev, INFINITE_TIME);
      if (rc < 0) {
        TLOGE("wait returned (%d)\n", rc);
        abort();
      }
      handle_channel_event(&cev);
      if (cev.event & IPC_HANDLE_POLL_HUP) {
        return;
      }
    }
  }
}


/*
 *  Main app entry point
 */
int main(void) {
  int rc;
  handle_t port;

  /* Initialize service */
  rc = port_create(srv_name, 1, MAX_ECHO_MSG_SIZE,
    IPC_PORT_ALLOW_NS_CONNECT |
    IPC_PORT_ALLOW_TA_CONNECT);
  if (rc < 0) {
    TLOGE("Failed (%d) to create port %s\n",
      rc, srv_name);
    abort();
  }
  port = (handle_t) rc;

  /* enter main event loop */
  while (true) {
    uevent_t ev;

    ev.handle = INVALID_IPC_HANDLE;
    ev.event = 0;
    ev.cookie = NULL;

    /* wait forever */
    rc = wait(port, &ev, INFINITE_TIME);
    if (rc == NO_ERROR) {
      /* got an event */
      handle_port_event(&ev);
    } else {
      TLOGE("wait returned (%d)\n", rc);
      abort();
    }
  }
  return 0;
}

run_end_to_end_msg_test() तरीका, "echo" सेवा को 10,000 मैसेज भेजता है और जवाबों को मैनेज करता है.

static int run_echo_test(void)
{
  int rc;
  handle_t chan;
  uevent_t uevt;
  uint8_t tx_buf[64];
  uint8_t rx_buf[64];
  ipc_msg_info_t inf;
  ipc_msg_t   tx_msg;
  iovec_t     tx_iov;
  ipc_msg_t   rx_msg;
  iovec_t     rx_iov;

  /* prepare tx message buffer */
  tx_iov.base = tx_buf;
  tx_iov.len  = sizeof(tx_buf);
  tx_msg.num_iov = 1;
  tx_msg.iov     = &tx_iov;
  tx_msg.num_handles = 0;
  tx_msg.handles = NULL;

  memset (tx_buf, 0x55, sizeof(tx_buf));

  /* prepare rx message buffer */
  rx_iov.base = rx_buf;
  rx_iov.len  = sizeof(rx_buf);
  rx_msg.num_iov = 1;
  rx_msg.iov     = &rx_iov;
  rx_msg.num_handles = 0;
  rx_msg.handles = NULL;

  /* open connection to echo service */
  rc = sync_connect(srv_name, 1000);
  if(rc < 0)
    return rc;

  /* got channel */
  chan = (handle_t)rc;

  /* send/receive 10000 messages asynchronously. */
  uint tx_cnt = 10000;
  uint rx_cnt = 10000;

  while (tx_cnt || rx_cnt) {
    /* send messages until all buffers are full */
while (tx_cnt) {
    rc = send_msg(chan, &tx_msg);
      if (rc == ERR_NOT_ENOUGH_BUFFER)
      break;  /* no more space */
    if (rc != 64) {
      if (rc > 0) {
        /* incomplete send */
        rc = ERR_NOT_VALID;
}
      goto abort_test;
}
    tx_cnt--;
  }

  /* wait for reply msg or room */
  rc = wait(chan, &uevt, 1000);
  if (rc != NO_ERROR)
    goto abort_test;

  /* drain all messages */
  while (rx_cnt) {
    /* get a reply */
      rc = get_msg(chan, &inf);
    if (rc == ERR_NO_MSG)
        break;  /* no more messages  */
  if (rc != NO_ERROR)
goto abort_test;

  /* read reply data */
    rc = read_msg(chan, inf.id, 0, &rx_msg);
  if (rc != 64) {
    /* unexpected reply length */
    rc = ERR_NOT_VALID;
    goto abort_test;
}

  /* discard reply */
  rc = put_msg(chan, inf.id);
  if (rc != NO_ERROR)
    goto abort_test;
  rx_cnt--;
  }
}

abort_test:
  close(chan);
  return rc;
}

दुनिया भर के ऐसे एपीआई और ऐप्लिकेशन जो सुरक्षित नहीं हैं

भरोसेमंद सेवाओं का एक सेट, सुरक्षित साइड से पब्लिश किया जाता है और IPC_PORT_ALLOW_NS_CONNECT एट्रिब्यूट के साथ मार्क किया जाता है. इसे, सुरक्षित साइड पर चल रहे कर्नेल और यूज़र स्पेस प्रोग्राम ऐक्सेस कर सकते हैं.

सुरक्षित नहीं वाले हिस्से (कर्नल और यूज़र स्पेस) का एक्ज़ीक्यूशन एनवायरमेंट, सुरक्षित हिस्से के एक्ज़ीक्यूशन एनवायरमेंट से काफ़ी अलग होता है. इसलिए, दोनों एनवायरमेंट के लिए एक लाइब्रेरी के बजाय, एपीआई के दो अलग-अलग सेट होते हैं. क्लाइंट एपीआई, कर्नेल में ट्रस्टी-आईपीसी कर्नेल ड्राइवर से मिलता है. साथ ही, यह एक वर्ण डिवाइस नोड को रजिस्टर करता है. उपयोगकर्ता स्पेस प्रोसेस इसका इस्तेमाल, सुरक्षित साइड पर चल रही सेवाओं के साथ कम्यूनिकेट करने के लिए कर सकती हैं.

User space Trusty IPC Client API

यूज़र स्पेस Trusty IPC क्लाइंट एपीआई लाइब्रेरी, डिवाइस नोड fd के ऊपर एक पतली लेयर होती है.

यूज़र स्पेस प्रोग्राम, tipc_connect() को कॉल करके कम्यूनिकेशन सेशन शुरू करता है. इससे, किसी खास भरोसेमंद सेवा से कनेक्शन शुरू होता है. अंदरूनी तौर पर, tipc_connect() कॉल, फ़ाइल डिस्क्रिप्टर पाने के लिए किसी डिवाइस नोड को खोलता है. साथ ही, TIPC_IOC_CONNECT ioctl() कॉल को argp पैरामीटर के साथ शुरू करता है. यह पैरामीटर, उस स्ट्रिंग पर ले जाता है जिसमें उस सेवा का नाम होता है जिससे कनेक्ट करना है.

#define TIPC_IOC_MAGIC  'r'
#define TIPC_IOC_CONNECT  _IOW(TIPC_IOC_MAGIC, 0x80, char *)

फ़ाइल डिस्क्रिप्टर का इस्तेमाल सिर्फ़ उस सेवा के साथ बातचीत करने के लिए किया जा सकता है जिसके लिए इसे बनाया गया था. जब कनेक्शन की ज़रूरत न हो, तब tipc_close() को कॉल करके फ़ाइल डिस्क्रिप्टर को बंद कर देना चाहिए.

tipc_connect() कॉल से मिला फ़ाइल डिस्क्रिप्टर, एक सामान्य वर्ण डिवाइस नोड की तरह काम करता है. फ़ाइल डिस्क्रिप्टर:

  • ज़रूरत पड़ने पर, इसे ब्लॉक न करने वाले मोड पर स्विच किया जा सकता है
  • दूसरे पक्ष को मैसेज भेजने के लिए, स्टैंडर्ड write() कॉल का इस्तेमाल करके लिखा जा सकता है
  • आम फ़ाइल डिस्क्रिप्टर के तौर पर, इनबाउंड मैसेज की उपलब्धता के लिए, poll() कॉल या select() कॉल का इस्तेमाल करके, पूलिंग की जा सकती है
  • इनकमिंग मैसेज वापस पाने के लिए पढ़ा जा सकता है

कॉल करने वाला व्यक्ति, तय किए गए fd के लिए लिखने का कॉल करके, Trusty सेवा को मैसेज भेजता है. ऊपर दिए गए write() कॉल में भेजा गया सारा डेटा, ट्रस्टी-आईपीसी ड्राइवर की मदद से मैसेज में बदल जाता है. मैसेज को सुरक्षित साइड पर डिलीवर किया जाता है, जहां Trusty kernel में IPC सबसिस्टम से डेटा मैनेज किया जाता है. साथ ही, उसे सही डेस्टिनेशन पर भेजा जाता है और किसी चैनल हैंडल पर IPC_HANDLE_POLL_MSG इवेंट के तौर पर ऐप्लिकेशन इवेंट लूप में डिलीवर किया जाता है. सेवा के हिसाब से, ट्रस्टी सेवा एक या उससे ज़्यादा जवाब मैसेज भेज सकती है. ये मैसेज, सुरक्षित नहीं किए गए हिस्से पर वापस डिलीवर किए जाते हैं और सही चैनल फ़ाइल डिस्क्रिप्टर मैसेज कतार में डाल दिए जाते हैं. उपयोगकर्ता, स्पेस ऐप्लिकेशन read() कॉल की मदद से इन्हें वापस पा सकता है.

tipc_connect()

यह किसी खास tipc डिवाइस नोड को खोलता है और किसी खास भरोसेमंद सेवा से कनेक्शन शुरू करता है.

int tipc_connect(const char *dev_name, const char *srv_name);

[in] dev_name: Trusty IPC डिवाइस नोड का पाथ, जिसे खोलना है

[in] srv_name: पब्लिश की गई किसी भरोसेमंद सेवा का नाम, जिससे कनेक्ट करना है

[retval]: फ़ाइल का मान्य डिस्क्रिप्टर, सफल होने पर -1.

tipc_close()

फ़ाइल डिस्क्रिप्टर की मदद से बताई गई Trusty सेवा से कनेक्शन बंद करता है.

int tipc_close(int fd);

[in] fd: फ़ाइल का ब्यौरा, जिसे पहले tipc_connect() कॉल से खोला गया था

Kernel Trusty IPC Client API

kernel Trusty IPC Client API, kernel ड्राइवर के लिए उपलब्ध है. इस एपीआई के ऊपर, उपयोगकर्ता के लिए बने Trusty IPC API को लागू किया गया है.

आम तौर पर, इस एपीआई का इस्तेमाल करने के लिए, कॉल करने वाला व्यक्ति tipc_create_channel() फ़ंक्शन का इस्तेमाल करके struct tipc_chan ऑब्जेक्ट बनाता है. इसके बाद, सुरक्षित साइड पर चल रही Trusty IPC सेवा से कनेक्ट करने के लिए, tipc_chan_connect() कॉल का इस्तेमाल करता है. रिमोट साइड से कनेक्शन को बंद करने के लिए, tipc_chan_shutdown() को कॉल करने के बाद, संसाधनों को हटाने के लिए tipc_chan_destroy() को कॉल करें.

handle_event() कॉलबैक के ज़रिए सूचना मिलने पर, कॉल करने वाला व्यक्ति ये काम करता है:

  • tipc_chan_get_txbuf_timeout() कॉल का इस्तेमाल करके मैसेज बफ़र पाता है
  • मैसेज लिखता है और
  • tipc_chan_queue_msg() का इस्तेमाल करके, संदेश को सूची में जोड़ता है सुरक्षित पक्ष पर मौजूद किसी भरोसेमंद सेवा को डिलीवरी के लिए, जिससे चैनल कनेक्ट है

मैसेज को सूची में जोड़ने के बाद, कॉलर को मैसेज बफ़र को भूल जाना चाहिए. ऐसा इसलिए, क्योंकि रिमोट साइड पर प्रोसेस करने के बाद, मैसेज बफ़र, फ़्री बफ़र पूल में वापस आ जाता है. ऐसा, बाद में अन्य मैसेज के लिए, फिर से इस्तेमाल करने के लिए किया जाता है. उपयोगकर्ता को tipc_chan_put_txbuf() को सिर्फ़ तब कॉल करना होगा, जब ऐसा बफ़र कतार में न आए या अब उसकी ज़रूरत न हो.

एपीआई उपयोगकर्ता को रिमोट साइड से मैसेज मिलते हैं. इसके लिए, वह handle_msg() सूचना कॉलबैक को मैनेज करता है. इसे ट्रस्टी-आईपीसी rx वर्कक्वे के संदर्भ में कॉल किया जाता है. यह rx बफ़र का पॉइंटर देता है, जिसमें मैनेज किए जाने वाले इनकमिंग मैसेज होते हैं.

उम्मीद है कि handle_msg() कॉलबैक को लागू करने पर, मान्य struct tipc_msg_buf का पॉइंटर दिखेगा. अगर इसे स्थानीय तौर पर मैनेज किया जाता है और अब इसकी ज़रूरत नहीं है, तो यह इनकमिंग मैसेज बफ़र जैसा हो सकता है. इसके अलावा, अगर आने वाले बफ़र को आगे की प्रोसेसिंग के लिए कतार में रखा गया है, तो यह tipc_chan_get_rxbuf() कॉल से मिला नया बफ़र भी हो सकता है. डिटैच किए गए rx बफ़र को ट्रैक किया जाना चाहिए और जब इसकी ज़रूरत न हो, तब tipc_chan_put_rxbuf() कॉल का इस्तेमाल करके इसे रिलीज़ किया जाना चाहिए.

Kernel Trusty IPC Client API में मौजूद तरीके

tipc_create_channel()

किसी खास ट्रस्टी-आईपीसी डिवाइस के लिए, ट्रस्टी आईपीसी चैनल का एक इंस्टेंस बनाता और कॉन्फ़िगर करता है.

struct tipc_chan *tipc_create_channel(struct device *dev,
                          const struct tipc_chan_ops *ops,
                              void *cb_arg);

[in] dev: उस ट्रस्टी-आईपीसी का पॉइंटर जिसके लिए डिवाइस चैनल बनाया गया है

[in] ops: struct tipc_chan_ops का पॉइंटर, जिसमें कॉलर के हिसाब से कॉलबैक भरे गए हैं

[in] cb_arg: tipc_chan_ops कॉलबैक में पास किए गए डेटा का पॉइंटर

[retval]: अगर फ़ंक्शन सही तरीके से काम करता है, तो struct tipc_chan के नए इंस्टेंस का पॉइंटर, नहीं तो ERR_PTR(err)

आम तौर पर, कॉलर को दो कॉलबैक देने होते हैं, जो संबंधित गतिविधि होने पर, एक साथ नहीं बल्कि अलग-अलग समय पर शुरू होते हैं.

चैनल के स्टेटस में हुए बदलाव के बारे में कॉलर को सूचना देने के लिए, void (*handle_event)(void *cb_arg, int event)इवेंट को ट्रिगर किया जाता है.

[in] cb_arg: tipc_create_channel() कॉल में पास किए गए डेटा का पॉइंटर

[in] event: यह इवेंट इनमें से कोई एक वैल्यू हो सकता है:

  • TIPC_CHANNEL_CONNECTED - रिमोट साइड से कनेक्ट होने का संकेत देता है
  • TIPC_CHANNEL_DISCONNECTED - इससे पता चलता है कि रिमोट साइड ने कनेक्ट करने के नए अनुरोध को अस्वीकार किया है या पहले से कनेक्ट किए गए चैनल को डिसकनेक्ट करने का अनुरोध किया है
  • TIPC_CHANNEL_SHUTDOWN - इससे पता चलता है कि रिमोट साइड बंद हो रहा है और सभी कनेक्शन हमेशा के लिए बंद हो जाएंगे

struct tipc_msg_buf *(*handle_msg)(void *cb_arg, struct tipc_msg_buf *mb) callback को यह सूचना देने के लिए शुरू किया जाता है कि किसी खास चैनल पर नया मैसेज मिला है:

  • [in] cb_arg: tipc_create_channel() कॉल में पास किए गए डेटा का पॉइंटर
  • [in] mb: किसी struct tipc_msg_buf के लिए पॉइंटर जिसमें इनकमिंग मैसेज के बारे में जानकारी दी गई हो
  • [retval]: कॉलबैक लागू करने पर, struct tipc_msg_buf का एक पॉइंटर दिखेगा. यह वही पॉइंटर हो सकता है जो मैसेज को स्थानीय तौर पर मैनेज करने पर, mb पैरामीटर के तौर पर मिलता है. हालांकि, अब इसकी ज़रूरत नहीं है. इसके अलावा, यह tipc_chan_get_rxbuf() कॉल से मिला नया बफ़र भी हो सकता है

tipc_chan_connect()

यह तय की गई Trusty IPC सेवा से कनेक्शन शुरू करता है.

int tipc_chan_connect(struct tipc_chan *chan, const char *port);

[in] chan: tipc_create_chan() कॉल से मिले चैनल का पॉइंटर

[in] port: उस स्ट्रिंग का पॉइंटर जिसमें उस सेवा का नाम है जिससे कनेक्ट करना है

[retval]: अगर फ़ीड अपलोड हो जाता है, तो 0. अगर नहीं हो पाता है, तो कोई गड़बड़ी का कोड

कनेक्शन बनने पर, कॉल करने वाले व्यक्ति को handle_event कॉलबैक के ज़रिए सूचना दी जाती है.

tipc_chan_shutdown()

Trusty IPC सेवा से कनेक्टिविटी को बंद करता है. इस सेवा को पहले tipc_chan_connect() कॉल से शुरू किया गया था.

int tipc_chan_shutdown(struct tipc_chan *chan);

[in] chan: tipc_create_chan() कॉल से मिले चैनल का पॉइंटर

tipc_chan_destroy()

किसी खास Trusty IPC चैनल को मिटा देता है.

void tipc_chan_destroy(struct tipc_chan *chan);

[in] chan: tipc_create_chan() कॉल से मिले चैनल का पॉइंटर

tipc_chan_get_txbuf_timeout()

एक मैसेज बफ़र पाता है, जिसका इस्तेमाल किसी तय चैनल पर डेटा भेजने के लिए किया जा सकता है. अगर बफ़र तुरंत उपलब्ध नहीं होता है, तो कॉलर को तय किए गए टाइम आउट (मिलीसेकंड में) के लिए ब्लॉक किया जा सकता है.

struct tipc_msg_buf *
tipc_chan_get_txbuf_timeout(struct tipc_chan *chan, long timeout);

[in] chan: उस चैनल का पॉइंटर जिस पर मैसेज भेजना है

[in] chan: tx बफ़र उपलब्ध होने तक इंतज़ार करने के लिए ज़्यादा से ज़्यादा टाइम आउट

[retval]: सही तरीके से पूरा होने पर मान्य मैसेज बफ़र, गड़बड़ी होने पर ERR_PTR(err)

tipc_chan_queue_msg()

यह किसी मैसेज को तय किए गए ट्रस्टी आईपीसी चैनलों पर भेजने के लिए, उसे सूची में जोड़ता है.

int tipc_chan_queue_msg(struct tipc_chan *chan, struct tipc_msg_buf *mb);

[in] chan: उस चैनल का पॉइंटर जिस पर मैसेज भेजना है

[in] mb: सूची में जोड़ने के लिए मैसेज का पॉइंटर (tipc_chan_get_txbuf_timeout() कॉल से मिला)

[retval]: अगर फ़ीड अपलोड हो जाता है, तो 0. अगर नहीं हो पाता है, तो कोई गड़बड़ी का कोड

tipc_chan_put_txbuf()

पहले tipc_chan_get_txbuf_timeout() कॉल से मिले, तय किए गए Tx मैसेज बफ़र को रिलीज़ करता है.

void tipc_chan_put_txbuf(struct tipc_chan *chan,
                         struct tipc_msg_buf *mb);

[in] chan: उस चैनल का पॉइंटर जिससे यह मैसेज बफ़र जुड़ा है

[in] mb: रिलीज़ किए जाने वाले मैसेज बफ़र का पॉइंटर

[retval]: None

tipc_chan_get_rxbuf()

एक नया मैसेज बफ़र मिलता है. इसका इस्तेमाल, तय किए गए चैनल पर मैसेज पाने के लिए किया जा सकता है.

struct tipc_msg_buf *tipc_chan_get_rxbuf(struct tipc_chan *chan);

[in] chan: उस चैनल का पॉइंटर जिससे यह मैसेज बफ़र जुड़ा है

[retval]: सही तरीके से पूरा होने पर मान्य मैसेज बफ़र, गड़बड़ी होने पर ERR_PTR(err)

tipc_chan_put_rxbuf()

पहले से तय किए गए मैसेज बफ़र को रिलीज़ करता है, जिसे पहले tipc_chan_get_rxbuf() कॉल से पाया गया था.

void tipc_chan_put_rxbuf(struct tipc_chan *chan,
                         struct tipc_msg_buf *mb);

[in] chan: उस चैनल का पॉइंटर जिससे यह मैसेज बफ़र जुड़ा है

[in] mb: रिलीज़ किए जाने वाले मैसेज बफ़र का पॉइंटर

[retval]: None