ข้อมูลอ้างอิงของ Trusty API

Trusty มี API สำหรับการพัฒนาแอปพลิเคชัน/บริการ 2 คลาส ได้แก่

  • แอปพลิเคชันหรือบริการที่เชื่อถือได้ซึ่งทำงานบนโปรเซสเซอร์ TEE
  • แอปพลิเคชันปกติ/ไม่น่าเชื่อถือซึ่งทำงานบนโปรเซสเซอร์หลักและใช้บริการที่มี โดยแอปพลิเคชันที่เชื่อถือได้

ทรัสตี API โดยทั่วไปแล้วจะอธิบายถึงระบบ Trusty Inter-Process Communication (IPC) ซึ่งรวมถึงการสื่อสารกับโลกที่ไม่ปลอดภัย ซอฟต์แวร์ที่ทำงานบน ผู้ประมวลผลข้อมูลหลักสามารถใช้ Trusty API เพื่อเชื่อมต่อกับแอปพลิเคชัน/บริการที่เชื่อถือได้ และแลกเปลี่ยนข้อความที่กำหนดเองกับพวกเขา เหมือนกับบริการเครือข่ายผ่าน IP ขึ้นอยู่กับแอปพลิเคชันที่จะตัดสินรูปแบบข้อมูลและความหมายของข้อมูลเหล่านี้ โดยใช้โปรโตคอลระดับแอป การส่งข้อความที่เชื่อถือได้ รับประกันโดยโครงสร้างพื้นฐานของ Trusty ที่สำคัญ (ในรูปแบบของไดรเวอร์ ที่ทำงานบนโปรเซสเซอร์หลัก) และการสื่อสารจะไม่พร้อมกันโดยสมบูรณ์

พอร์ตและช่องทาง

แอปพลิเคชัน Trusty ใช้พอร์ตเพื่อแสดงจุดสิ้นสุดของบริการในรูปแบบ ของเส้นทางที่มีชื่อซึ่งไคลเอ็นต์เชื่อมต่อ ซึ่งจะให้แท็กที่เรียบง่ายตามสตริง รหัสบริการของลูกค้าที่จะใช้ แบบแผนการตั้งชื่อเป็นรูปแบบ DNS ย้อนกลับ การตั้งชื่อ เช่น com.google.servicename

เมื่อไคลเอ็นต์เชื่อมต่อกับพอร์ต ลูกค้าจะได้รับช่องทางสำหรับการโต้ตอบ กับบริการ บริการต้องยอมรับการเชื่อมต่อขาเข้าและเมื่อ วิดีโอก็ได้รับช่องเช่นกัน โดยพื้นฐานแล้ว ระบบจะใช้พอร์ตเพื่อค้นหาบริการ จากนั้นการสื่อสารจะเกิดขึ้นผ่านช่องทางที่เชื่อมต่อ 2 ช่องทาง (เช่น อินสแตนซ์การเชื่อมต่อบนพอร์ต) เมื่อลูกค้าเชื่อมต่อกับพอร์ต รูปแบบสมมาตร สร้างการเชื่อมต่อ 2 ทิศทางแล้ว ไคลเอ็นต์ที่ใช้เส้นทางแบบ 2 ด้านนี้อยู่ และเซิร์ฟเวอร์สามารถแลกเปลี่ยนข้อความตามต้องการจนกว่าฝ่ายใดฝ่ายหนึ่งจะตัดสินใจฉีก ลดการเชื่อมต่อ

สร้างได้เฉพาะแอปพลิเคชันที่เชื่อถือด้านความปลอดภัยหรือโมดูลเคอร์เนลของ Trusty เท่านั้น พอร์ต แอปพลิเคชันที่ทำงานในฝั่งที่ไม่ปลอดภัย (ในโลกปกติ) สามารถ เชื่อมต่อกับบริการที่เผยแพร่โดยด้านที่ปลอดภัยเท่านั้น

แอปพลิเคชันที่เชื่อถือได้สามารถเป็นได้ทั้งไคลเอ็นต์และ ทำงานพร้อมกันได้ แอปพลิเคชันที่เชื่อถือได้ซึ่งเผยแพร่บริการ (ในฐานะ เซิร์ฟเวอร์) อาจต้องเชื่อมต่อกับบริการอื่นๆ (ในฐานะไคลเอ็นต์)

API ของแฮนเดิล

แฮนเดิลคือจำนวนเต็มที่ไม่มีเครื่องหมายซึ่งแสดงถึงทรัพยากร เช่น พอร์ตและ ซึ่งคล้ายกับข้อบ่งชี้ไฟล์ใน UNIX หลังจากสร้างแฮนเดิลแล้ว จะวางลงในตารางแฮนเดิลเฉพาะแอปพลิเคชันและนำไปใช้อ้างอิงได้ ในภายหลัง

ผู้โทรสามารถเชื่อมโยงข้อมูลส่วนตัวกับแฮนเดิลได้โดยใช้ เมธอด set_cookie()

เมธอดใน Handle API

แฮนเดิลจะใช้ได้ในบริบทของแอปพลิเคชันเท่านั้น แอปพลิเคชันควร ไม่ส่งผ่านค่าของแฮนเดิลไปยังแอปพลิเคชันอื่น เว้นแต่จะมีการระบุไว้อย่างชัดแจ้ง ที่ระบุ ควรแปลค่าแฮนเดิลเท่านั้นด้วยการเปรียบเทียบกับค่าแฮนเดิล INVALID_IPC_HANDLE #define, ซึ่งแอปพลิเคชันสามารถใช้เป็น แสดงว่าแฮนเดิลไม่ถูกต้องหรือไม่ได้ตั้งค่า

เชื่อมโยงข้อมูลส่วนตัวที่ผู้โทรให้ไว้กับแฮนเดิลที่ระบุ

long set_cookie(uint32_t handle, void *cookie)

[in] handle: แฮนเดิลใดก็ตามที่แสดงผลโดยการเรียก API รายการใดรายการหนึ่ง

[in] cookie: ชี้ไปที่ข้อมูลพื้นที่ผู้ใช้ที่กำหนดเองในแอปพลิเคชัน Trusty

[retval]: NO_ERROR เมื่อสำเร็จ, < 0 รหัสข้อผิดพลาด

การโทรนี้มีประโยชน์ในการจัดการเหตุการณ์เมื่อเหตุการณ์ดังกล่าวเกิดขึ้นในภายหลัง สร้างแฮนเดิลแล้ว กลไกการจัดการเหตุการณ์จะจัดเตรียมแฮนเดิล และคุกกี้ของตัวแฮนเดิลกลับไปยัง เครื่องจัดการเหตุการณ์

ใช้การเรียก wait() เพื่อรอเหตุการณ์ต่างๆ ได้

รอ()

รอให้มีเหตุการณ์เกิดขึ้นในแฮนเดิลหนึ่งๆ ในระยะเวลาที่ระบุ

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

[in] handle_id: แฮนเดิลใดก็ตามที่แสดงผลโดยการเรียก API รายการใดรายการหนึ่ง

[out] event: ตัวชี้ไปยังโครงสร้างที่แสดง เหตุการณ์ที่เกิดขึ้นในแฮนเดิลนี้

[in] timeout_msecs: ค่าระยะหมดเวลาเป็นมิลลิวินาที CANNOT TRANSLATE ค่า -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()

ปิด()

ทำลายทรัพยากรที่เชื่อมโยงกับแฮนเดิลที่ระบุ และนำออกจาก ตารางแฮนเดิล

long close(uint32_t handle_id);

[in] handle_id: แฮนเดิลเพื่อทำลาย

[retval]: 0 หากสำเร็จ ข้อผิดพลาดด้านลบหากไม่เป็นเช่นนั้น

API เซิร์ฟเวอร์

เซิร์ฟเวอร์จะเริ่มต้นด้วยการสร้างพอร์ตที่มีชื่ออย่างน้อย 1 รายการที่แสดง จุดสิ้นสุดของบริการ พอร์ตแต่ละพอร์ตจะแสดงด้วยแฮนเดิล

เมธอดใน 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: จำนวนบัฟเฟอร์สูงสุดที่ช่องใช้ พอร์ตนี้สามารถจัดสรรล่วงหน้าเพื่ออำนวยความสะดวกในการแลกเปลี่ยนข้อมูลกับไคลเอ็นต์ กำลังนับบัฟเฟอร์ แยกต่างหากสำหรับข้อมูลที่ไปในทั้ง 2 ทิศทาง ดังนั้นการระบุ 1 ที่นี่จะหมายถึง 1 มีการจัดสรรบัฟเฟอร์การส่งและการรับ 1 รายการไว้ล่วงหน้า โดยทั่วไป จำนวนบัฟเฟอร์ ขึ้นอยู่กับข้อตกลงด้านโปรโตคอลระดับที่สูงกว่าระหว่างลูกค้ากับ เซิร์ฟเวอร์ ตัวเลขอาจมีแค่ 1 ก็ได้ ในกรณีที่เป็นโปรโตคอลแบบซิงโครนัสมาก (ส่งข้อความ รับคำตอบก่อนที่จะส่งอีกรายการ) แต่ตัวเลขสามารถ เพิ่มเติมหากลูกค้าคาดว่าจะส่งข้อความมากกว่า 1 ข้อความก่อนที่จะตอบกลับ (เช่น ข้อความหนึ่งเป็นอารัมภบทและอีกข้อความเป็นคำสั่งจริง) ชุดบัฟเฟอร์ที่จัดสรรเป็นหน่วยต่อช่อง ดังนั้นการเชื่อมต่อ 2 ช่อง (แชนเนล) จะแยกกัน จะมีชุดบัฟเฟอร์แยกกัน

[in] recv_buf_size: ขนาดสูงสุดของบัฟเฟอร์แต่ละรายการใน เหนือชุดบัฟเฟอร์ ค่านี้คือ ขึ้นอยู่กับโปรโตคอลและจำกัดขนาดสูงสุดของข้อความที่คุณแลกเปลี่ยนได้ กับแอปเทียบเท่า

[in] flags: ชุดค่าผสมของ Flag ที่ระบุลักษณะการทำงานเพิ่มเติมของพอร์ต

ค่านี้ควรเป็นชุดค่าผสมของค่าต่อไปนี้

IPC_PORT_ALLOW_TA_CONNECT - อนุญาตการเชื่อมต่อจากแอปที่ปลอดภัยอื่นๆ

IPC_PORT_ALLOW_NS_CONNECT - อนุญาตการเชื่อมต่อจากโลกที่ไม่ปลอดภัย

[retval]: จัดการพอร์ตที่สร้างขึ้นหากไม่ใช่ด้านลบ หรือเกิดข้อผิดพลาดที่เฉพาะเจาะจง ลบ

จากนั้นเซิร์ฟเวอร์จะสำรวจรายการแฮนเดิลพอร์ตสำหรับการเชื่อมต่อขาเข้า โดยใช้การโทร wait() เมื่อได้รับการเชื่อมต่อ ซึ่งระบุด้วยบิต IPC_HANDLE_POLL_READY ที่ตั้งค่าไว้ใน ฟิลด์ event ของโครงสร้าง uevent_t ค่า เซิร์ฟเวอร์ควรเรียก accept() เพื่อทำการเชื่อมต่อให้เสร็จสิ้นและสร้าง ช่อง (นำเสนอโดย แฮนเดิลอื่น) ที่จะดึงข้อมูลสำหรับข้อความขาเข้าได้

ยอมรับ()

ยอมรับการเชื่อมต่อที่เข้ามาใหม่และรับแฮนเดิลของช่อง

long accept(uint32_t handle_id, uuid_t *peer_uuid);

[in] handle_id: แฮนเดิลที่แสดงถึงพอร์ตที่ไคลเอ็นต์เชื่อมต่อ

[out] peer_uuid: ชี้ไปที่โครงสร้าง uuid_t ที่จะ กรอก UUID ของแอปพลิเคชันไคลเอ็นต์ที่เชื่อมต่อ ทั้งนี้ จะตั้งเป็น 0 ทั้งหมดหากการเชื่อมต่อมาจากโลกที่ไม่ปลอดภัย

[retval]: จัดการแชแนล (ถ้าไม่เป็นลบ) ซึ่งเซิร์ฟเวอร์สามารถ แลกเปลี่ยนข้อความกับไคลเอ็นต์ (หรือรหัสข้อผิดพลาด)

API ของไคลเอ็นต์

ส่วนนี้ประกอบด้วยเมธอดใน Client API

เมธอดใน Client API

เชื่อมต่อ()

เริ่มการเชื่อมต่อกับพอร์ตที่ระบุตามชื่อ

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

[in] path: ชื่อพอร์ตที่เผยแพร่โดยแอปพลิเคชันของ Trusty

[in] flags: ระบุลักษณะการทำงานเพิ่มเติมที่ไม่บังคับ

[retval]: จัดการช่องที่สามารถแลกเปลี่ยนข้อความกับ เซิร์ฟเวอร์; หากเป็นลบ

หากไม่ได้ระบุ flags (พารามิเตอร์ flags มีค่าเป็น 0) การเรียกใช้ connect() จะเริ่มต้นการเชื่อมต่อแบบซิงโครนัส ไปยังพอร์ตที่ระบุทันที แสดงข้อผิดพลาดหากไม่มีพอร์ต และสร้างการบล็อกจนกว่า หรือเซิร์ฟเวอร์ยอมรับการเชื่อมต่อเป็นอย่างอื่น

ลักษณะการทำงานนี้เปลี่ยนแปลงได้โดยการระบุชุดค่าผสมของ 2 ค่า ที่อธิบายไว้ด้านล่าง

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

IPC_CONNECT_WAIT_FOR_PORT - บังคับให้connect() เพื่อรอหากไม่มีพอร์ตที่ระบุทันทีขณะดำเนินการ แทนที่จะล้มเหลวทันที

IPC_CONNECT_ASYNC - หากมีการตั้งค่าไว้ จะเป็นการเริ่มต้นการเชื่อมต่อแบบไม่พร้อมกัน CANNOT TRANSLATE แอปพลิเคชันมีการโพลสำหรับ แฮนเดิลที่แสดงผล (โดยการเรียกใช้ wait() สำหรับ เหตุการณ์การเชื่อมต่อเสร็จสมบูรณ์ซึ่งระบุโดย IPC_HANDLE_POLL_READY บิตที่ตั้งค่าในช่องเหตุการณ์ของโครงสร้าง uevent_t ก่อนเริ่มต้น การทำงานตามปกติ

API การรับส่งข้อความ

การเรียก API การรับส่งข้อความ จะทำให้สามารถส่งและอ่านข้อความผ่าน การเชื่อมต่อ (ช่อง) ที่สร้างไว้ก่อนหน้านี้ การเรียก 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;

ข้อความอาจประกอบด้วยบัฟเฟอร์ที่ไม่ต่อเนื่องกันอย่างน้อย 1 รายการซึ่งแสดงเป็น อาร์เรย์ของ 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 ในกรณีนี้ ผู้โทรจะต้องรอจนกว่าเพื่อนจะปล่อยว่าง ที่ว่างในคิวการรับ โดยเรียกคืนการจัดการและเลิกใช้ข้อความ ระบุด้วยการตั้งค่าบิต IPC_HANDLE_POLL_SEND_UNBLOCKED ใน ฟิลด์ event ของโครงสร้าง uevent_t แสดงผลโดยการเรียก wait()

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);

[in] handle: แฮนเดิลของช่องที่ได้รับข้อความ

[in] msg_id: รหัสข้อความที่เลิกใช้

[retval]: ประสบความสำเร็จ NO_ERROR ข้อผิดพลาดด้านลบหากไม่เป็นเช่นนั้น

ไม่สามารถเข้าถึงเนื้อหาข้อความได้อีกหลังจากเลิกใช้ข้อความไปแล้ว และ พื้นที่อื่นที่มีอยู่ถูกปล่อยว่างแล้ว

API ข้อบ่งชี้ไฟล์

File Descriptor API ประกอบด้วย read(), write(), และ ioctl() สาย การเรียกทั้งหมดนี้สามารถทำงานในชุดไฟล์ที่กำหนดไว้ล่วงหน้า (แบบคงที่) ได้ แต่เดิมเรียกด้วยเลขน้อยๆ ในปัจจุบัน การใช้งาน พื้นที่ข้อบ่งชี้ไฟล์จะแยกจากแฮนเดิล IPC พื้นที่ทำงาน File Descriptor API ใน Trusty คือ คล้ายกับ API ที่ใช้ข้อบ่งชี้ไฟล์แบบดั้งเดิม

โดยค่าเริ่มต้น จะมีข้อบ่งชี้ไฟล์ที่กำหนดไว้ล่วงหน้า 3 แบบ (แบบมาตรฐานและที่รู้จัก) ดังนี้

  • 0 - อินพุตมาตรฐาน การใช้งานเริ่มต้นของอินพุตมาตรฐาน fd ไม่จำเป็นต้องดำเนินการใดๆ (เนื่องจากแอปพลิเคชันที่เชื่อถือได้ไม่ได้ต้องการ คอนโซล) ดังนั้นการอ่าน การเขียน หรือการเรียกใช้ ioctl() ใน fd 0 ควรแสดงข้อผิดพลาด ERR_NOT_SUPPORTED
  • 1 - เอาต์พุตมาตรฐาน สามารถกำหนดเส้นทางข้อมูลที่เขียนไปยังเอาต์พุตมาตรฐานได้ (ขึ้นอยู่กับ ที่ระดับแก้ไขข้อบกพร่อง LK) เป็น UART และ/หรือบันทึกหน่วยความจำที่มีอยู่ในตัวเลือกที่ไม่ปลอดภัย ขึ้นอยู่กับแพลตฟอร์มและการกำหนดค่า บันทึกการแก้ไขข้อบกพร่องที่ไม่สำคัญและ ข้อความควรอยู่ในเอาต์พุตมาตรฐาน read() และ ioctl() ไม่มีการดำเนินการ และควรแสดงข้อผิดพลาด ERR_NOT_SUPPORTED
  • 2 - ข้อผิดพลาดมาตรฐาน ข้อมูลที่เขียนถึงข้อผิดพลาดมาตรฐานควรกำหนดเส้นทางไปยัง UART หรือบันทึกหน่วยความจำที่ใช้ได้ในด้านที่ไม่ปลอดภัย ทั้งนี้ขึ้นอยู่กับแพลตฟอร์มและ การกำหนดค่า ขอแนะนำให้เขียนเฉพาะข้อความสำคัญตามมาตรฐาน เนื่องจากสตรีมนี้มีแนวโน้มที่จะไม่มีการควบคุม read() และ เมธอด ioctl() ไม่ทำงานและควรแสดงข้อผิดพลาด ERR_NOT_SUPPORTED

แม้ว่าคุณสามารถขยายข้อบ่งชี้ไฟล์ชุดนี้เพื่อนำไปใช้เพิ่มเติม fds (เพื่อใช้ส่วนขยายเฉพาะแพลตฟอร์ม) ขยายความต้องการด้านข้อบ่งชี้ไฟล์ คุณต้องใช้ความระมัดระวัง การขยายข้อบ่งชี้ไฟล์มีแนวโน้มที่จะสร้าง ทับซ้อนกันและโดยทั่วไปจะไม่แนะนำ

เมธอดใน File Descriptor API

อ่าน()

พยายามอ่านข้อมูลสูงสุด count ไบต์จากข้อบ่งชี้ไฟล์ที่ระบุ

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

[in] fd: ตัวบ่งชี้ไฟล์ที่จะอ่าน

[out] buf: ชี้ไปที่บัฟเฟอร์ที่ใช้จัดเก็บข้อมูล

[in] count: จำนวนไบต์สูงสุดที่อ่านได้

[retval]: แสดงผลจำนวนไบต์ที่อ่าน ข้อผิดพลาดด้านลบหากไม่เป็นเช่นนั้น

เขียน()

เขียนข้อมูลสูงสุด 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

[in/out] args: ชี้ไปที่อาร์กิวเมนต์ ioctl()

API เบ็ดเตล็ด

เมธอดใน Miscellancies API

gettime()

แสดงเวลาของระบบปัจจุบัน (เป็นนาโนวินาที)

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

[ใน] clock_id: ขึ้นอยู่กับแพลตฟอร์ม Pass 0 สำหรับค่าเริ่มต้น

[in] flags: สงวนไว้ ควรเป็น 0

[out] time: ชี้ไปที่ค่า int64_t ซึ่งจะจัดเก็บเวลาปัจจุบัน

[retval]: ประสบความสำเร็จ NO_ERROR ข้อผิดพลาดด้านลบหากไม่เป็นเช่นนั้น

nanosleep()

ระงับการดำเนินการแอปพลิเคชันการโทรตามระยะเวลาที่ระบุ และกลับมาใช้งานอีกครั้งหลังจากช่วงเวลาดังกล่าว

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

[in] clock_id: สงวนไว้ ควรเป็น 0

[in] flags: สงวนไว้ ควรเป็น 0

[in] sleep_time: เวลานอนหลับในหน่วยนาโนวินาที

[retval]: ประสบความสำเร็จ NO_ERROR ข้อผิดพลาดด้านลบหากไม่เป็นเช่นนั้น

ตัวอย่างของแอปพลิเคชันเซิร์ฟเวอร์ที่เชื่อถือได้

แอปพลิเคชันตัวอย่างต่อไปนี้แสดงการใช้งาน API ข้างต้น ตัวอย่าง ทำให้เกิด "เสียงสะท้อน" บริการที่รองรับการเชื่อมต่อขาเข้าหลายรายการ แสดงกลับไปยังผู้โทร ข้อความทั้งหมดที่ได้รับจากไคลเอ็นต์นั้น จากด้านที่ปลอดภัยหรือไม่ปลอดภัย

#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 application 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() จะส่งข้อความ 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;
}

API และแอปพลิเคชันสากลที่ไม่ปลอดภัย

ชุดของบริการ Trusty ซึ่งเผยแพร่จากด้านที่ปลอดภัยและ เคอร์เนลเข้าถึงแอตทริบิวต์ IPC_PORT_ALLOW_NS_CONNECT ได้ และโปรแกรมพื้นที่ผู้ใช้ที่ทำงานใน ที่ไม่ปลอดภัย

สภาพแวดล้อมการดำเนินการในฝั่งที่ไม่ปลอดภัย (เคอร์เนลและพื้นที่ของผู้ใช้) แตกต่างจากสภาพแวดล้อมการดำเนินการในด้านที่ปลอดภัยอย่างเห็นได้ชัด ดังนั้นแทนที่จะมีไลบรารีเดียวสำหรับ 2 สภาพแวดล้อม API ชุดต่างๆ ในเคอร์เนล Client API จะจัดเตรียมโดย ไดรเวอร์เคอร์เนล Trusty-ipc และลงทะเบียนโหนดอุปกรณ์แบบตัวละครที่สามารถใช้ได้ เพื่อสื่อสารกับบริการที่ทำงานใน

พื้นที่ผู้ใช้ Trusty IPC Client API

ไลบรารี Trusty IPC Client API สำหรับพื้นที่ของผู้ใช้เป็นเลเยอร์สั้นๆ ที่ด้านบนของแท็ก โหนดของอุปกรณ์ fd

โปรแกรมพื้นที่ทำงานของผู้ใช้เริ่มเซสชันการสื่อสาร โดยโทรหา tipc_connect() กำลังเริ่มต้นการเชื่อมต่อกับบริการ Trusty ที่ระบุ เป็นการภายใน การเรียกใช้ 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() ครั้ง) สำหรับความพร้อมใช้งานของข้อความขาเข้าเป็นข้อบ่งชี้ไฟล์ทั่วไป
  • สามารถอ่านเพื่อเรียกข้อความขาเข้าได้

ผู้โทรส่งข้อความไปยังบริการ Trusty โดยเรียกใช้การเขียนสำหรับ fd ที่ระบุ ข้อมูลทั้งหมดที่ส่งผ่านไปยังการโทร write() ข้างต้น จะเปลี่ยนเป็นข้อความโดยไดรเวอร์ Trusty-ipc ข้อความคือ ที่ส่งไปยังด้านที่ปลอดภัยซึ่งข้อมูลได้รับการจัดการโดยระบบย่อย IPC ใน เคอร์เนล Trusty และไปยังปลายทางที่เหมาะสมและส่งไปยังแอป การวนเหตุการณ์เป็นเหตุการณ์ IPC_HANDLE_POLL_MSG ในช่องทางหนึ่งๆ แฮนเดิล ซึ่งขึ้นอยู่กับ โปรโตคอลเฉพาะบริการ บริการ Trusty อาจส่งการตอบกลับอย่างน้อย 1 รายการ ข้อความที่ส่งไปยังฝั่งที่ไม่ปลอดภัย และวางไว้ใน คิวข้อความข้อบ่งชี้ไฟล์ช่องที่เหมาะสมที่ผู้ใช้จะใช้เรียก แอปพลิเคชันพื้นที่ทำงาน read() สาย

Tipc_connect()

เปิดโหนดอุปกรณ์ tipc ที่ระบุและเริ่ม การเชื่อมต่อกับบริการ Trusty ที่ระบุ

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

[in] dev_name: เส้นทางไปยังโหนดอุปกรณ์ IPC ที่เชื่อถือได้เพื่อเปิด

[in] srv_name: ชื่อบริการ Trusty ที่เผยแพร่แล้วที่จะเชื่อมต่อ

[retval]: ข้อบ่งชี้ไฟล์ถูกต้องเมื่อสำเร็จ มิฉะนั้น -1

Tipc_close()

ปิดการเชื่อมต่อกับบริการ Trusty ที่ระบุโดยข้อบ่งชี้ไฟล์

int tipc_close(int fd);

[in] fd: ตัวอธิบายไฟล์ที่เคยเปิดโดย การโทรจาก tipc_connect()

API ไคลเอ็นต์ IPC ของ Kernel Trusty

เคอร์เนล Trusty IPC Client API พร้อมใช้งานสำหรับไดรเวอร์เคอร์เนล ผู้ใช้ มีการใช้ Space Trusty IPC API เพิ่มเติมจาก API นี้

โดยทั่วไป การใช้งานทั่วไปของ API นี้จะประกอบไปด้วยโปรแกรมสร้าง ออบเจ็กต์ struct tipc_chan โดยใช้ tipc_create_channel() แล้วใช้การเรียก tipc_chan_connect() เพื่อเริ่มต้น กับบริการ Trusty IPC ที่ทำงานบน การเชื่อมต่อกับฝั่งรีโมตจะยกเลิกได้ด้วย กำลังโทรหา tipc_chan_shutdown() ตามด้วย tipc_chan_destroy() เพื่อล้างข้อมูลทรัพยากร

เมื่อได้รับการแจ้งเตือน (ผ่านการเรียกกลับของ handle_event()) ว่าสร้างการเชื่อมต่อสำเร็จแล้ว ดังต่อไปนี้

  • รับบัฟเฟอร์ข้อความโดยใช้การโทรของ tipc_chan_get_txbuf_timeout()
  • เขียนข้อความ และ
  • จัดคิวข้อความโดยใช้ tipc_chan_queue_msg() ในการจัดส่งไปยังบริการ Trusty (ในด้านที่ปลอดภัย) ซึ่ง เชื่อมต่อช่องแล้ว

หลังจากจัดคิวเรียบร้อยแล้ว ผู้โทรควรลืมบัฟเฟอร์ข้อความ เนื่องจากบัฟเฟอร์ข้อความจะกลับไปที่บัฟเฟอร์พูลหลังจาก การประมวลผลโดยรีโมต (เพื่อใช้ซ้ำในภายหลังสำหรับข้อความอื่นๆ) ผู้ใช้ จำเป็นต้องโทรหา tipc_chan_put_txbuf() เท่านั้นหากติดต่อไม่ได้ อยู่ในคิวของบัฟเฟอร์ดังกล่าว หรือไม่จำเป็นต้องใช้อีกต่อไป

ผู้ใช้ API ได้รับข้อความจากฝ่ายระยะไกลโดยจัดการกับ handle_msg() Callback (ที่เป็นการโทร) บริบทของคิวงาน Trusty-ipc rx) ที่ แสดงตัวชี้ไปยังบัฟเฟอร์ rx ที่มี ข้อความขาเข้าที่ต้องจัดการ

คาดว่า Callback handle_msg() จะส่งตัวชี้ไปยัง struct tipc_msg_buf ที่ถูกต้อง ซึ่งอาจเหมือนกับบัฟเฟอร์ข้อความขาเข้าหากมีการจัดการในเครื่อง และไม่จำเป็นอีกต่อไป หรืออาจเป็นบัฟเฟอร์ใหม่ที่ได้จาก สาย tipc_chan_get_rxbuf() หากบัฟเฟอร์ขาเข้าอยู่ในคิว เพื่อประมวลผลต่อไป ต้องติดตามบัฟเฟอร์ rx ที่ถอดออก และในที่สุดก็ปล่อยตัวโดยใช้การโทร tipc_chan_put_rxbuf() เมื่อ ก็ไม่จำเป็นอีกต่อไป

เมธอดใน Kernel Trusty IPC Client API

Tipc_create_channel()

สร้างและกำหนดค่าอินสแตนซ์ของแชแนล Trusty IPC สำหรับ อุปกรณ์ที่เชื่อถือได้-IPc

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

[in] dev: ชี้ไปที่ Trusty-ipc ที่อุปกรณ์ใช้ สร้างช่องแล้ว

[in] ops: ชี้ไปที่ struct tipc_chan_ops มีความเฉพาะเจาะจงกับผู้โทร Callback ที่ได้รับการเติมโฆษณา

[in] cb_arg: ชี้ไปที่ข้อมูลที่จะส่งไป ถึง tipc_chan_ops Callback

[retval]: ชี้ไปยังอินสแตนซ์ที่สร้างขึ้นใหม่ของ ประสบความสำเร็จ struct tipc_chan อีก ERR_PTR(err)

โดยทั่วไป ผู้โทรต้องระบุ Callback 2 รายการซึ่งเรียกใช้แบบไม่พร้อมกัน เมื่อกิจกรรมที่เกี่ยวข้องเกิดขึ้น

มีการเรียกเหตุการณ์ 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]: การใช้งาน Callback คาดว่าจะแสดงตัวชี้ไปยัง 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()

จัดคิวข้อความที่จะส่งถึง ช่อง IPC ที่เชื่อถือได้

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()

ปล่อยบัฟเฟอร์ข้อความ Tx ที่ระบุ ได้รับก่อนหน้านี้จากการเรียก tipc_chan_get_txbuf_timeout()

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

[in] chan: ชี้ไปที่ช่อง บัฟเฟอร์ข้อความนี้

[in] mb: ชี้ไปที่บัฟเฟอร์ข้อความที่จะปล่อย

[retval]: ไม่มี

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]: ไม่มี