การอ้างอิง API ที่เชื่อถือได้

จัดทุกอย่างให้เป็นระเบียบอยู่เสมอด้วยคอลเล็กชัน บันทึกและจัดหมวดหมู่เนื้อหาตามค่ากำหนดของคุณ

Trusty จัดเตรียม API สำหรับการพัฒนาแอปพลิเคชัน/บริการสองคลาส:

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

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

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

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

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

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

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

จัดการ API

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

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

เมธอดใน Handle API

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

เชื่อมโยงข้อมูลส่วนตัวของผู้โทรที่มีหมายเลขอ้างอิงที่ระบุ

long set_cookie(uint32_t handle, void *cookie)

[ใน] handle : หมายเลขอ้างอิงใด ๆ ที่ส่งคืนโดยการเรียก API ตัวใดตัวหนึ่ง

[ใน] cookie : ตัวชี้ไปยังข้อมูลพื้นที่ผู้ใช้ตามอำเภอใจในแอปพลิเคชัน Trusty

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

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

สามารถรอหมายเลขอ้างอิงสำหรับเหตุการณ์ได้โดยใช้การเรียก wait()

รอ()

รอให้เหตุการณ์เกิดขึ้นในหมายเลขอ้างอิงที่กำหนดสำหรับช่วงเวลาที่ระบุ

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

[ใน] handle_id : หมายเลขอ้างอิงใด ๆ ที่ส่งคืนโดยการเรียก API ตัวใดตัวหนึ่ง

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

[ใน] 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()

ปิด()

ทำลายทรัพยากรที่เกี่ยวข้องกับหมายเลขอ้างอิงที่ระบุและลบออกจากตารางหมายเลขอ้างอิง

long close(uint32_t handle_id);

[ใน] handle_id : จัดการเพื่อทำลาย

[ย้อนกลับ]: 0 ถ้าสำเร็จ; ข้อผิดพลาดเชิงลบเป็นอย่างอื่น

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

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

เมธอดในเซิร์ฟเวอร์ API

port_create()

สร้างพอร์ตบริการที่มีชื่อ

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

[ใน] path : ชื่อสตริงของพอร์ต (ตามที่อธิบายไว้ข้างต้น) ชื่อนี้ควรไม่ซ้ำกันทั้งระบบ การพยายามสร้างรายการซ้ำจะล้มเหลว

[ใน] num_recv_bufs : จำนวนบัฟเฟอร์สูงสุดที่ช่องสัญญาณบนพอร์ตนี้สามารถจัดสรรล่วงหน้าเพื่ออำนวยความสะดวกในการแลกเปลี่ยนข้อมูลกับลูกค้า บัฟเฟอร์จะถูกนับแยกกันสำหรับข้อมูลที่ไปในทั้งสองทิศทาง ดังนั้นการระบุ 1 ที่นี่จะหมายถึง 1 การส่งและ 1 บัฟเฟอร์การรับจะได้รับการจัดสรรล่วงหน้า โดยทั่วไป จำนวนบัฟเฟอร์ที่ต้องการขึ้นอยู่กับข้อตกลงโปรโตคอลระดับสูงกว่าระหว่างไคลเอนต์และเซิร์ฟเวอร์ ตัวเลขอาจน้อยกว่า 1 ในกรณีของโปรโตคอลแบบซิงโครนัส (ส่งข้อความ รับการตอบกลับก่อนส่งใหม่) แต่ตัวเลขอาจมากกว่านี้ได้หากลูกค้าต้องการส่งข้อความมากกว่าหนึ่งข้อความก่อนที่จะมีการตอบกลับ (เช่น ข้อความหนึ่งเป็นบทนำและอีกข้อความเป็นคำสั่งจริง) ชุดบัฟเฟอร์ที่จัดสรรเป็นชุดต่อช่องสัญญาณ ดังนั้นการเชื่อมต่อสองช่อง (ช่องสัญญาณ) แยกกันจะมีชุดบัฟเฟอร์แยกกัน

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

[ใน] flags ก : การรวมกันของแฟล็กที่ระบุพฤติกรรมพอร์ตเพิ่มเติม

ค่านี้ควรเป็นค่าผสมต่อไปนี้:

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

[ใน] handle_id : จัดการแทนพอร์ตที่ไคลเอนต์เชื่อมต่อ

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

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

Client API

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

เมธอดใน Client API

เชื่อมต่อ()

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

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

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

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

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 ดำเนินการอ่านและเขียนแบบ scatter-gather ไปยังบล็อกเหล่านี้โดยใช้อาร์เรย์ iov เนื้อหาของบัฟเฟอร์ที่สามารถอธิบายโดยอาร์เรย์ iov นั้นเป็นไปตามอำเภอใจโดยสมบูรณ์

เมธอดใน Messaging API

send_msg()

ส่งข้อความผ่านช่องทางที่กำหนด

long send_msg(uint32_t handle, ipc_msg_t *msg);

[ใน] handle : จัดการกับช่องที่จะส่งข้อความ

[ใน] 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);

[ใน] handle : หมายเลขอ้างอิงของช่องที่ต้องดึงข้อความใหม่

[ออก] msg_info : โครงสร้างข้อมูลข้อความอธิบายดังนี้:

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

แต่ละข้อความจะได้รับรหัสที่ไม่ซ้ำกันในชุดข้อความที่ค้างอยู่ และความยาวรวมของแต่ละข้อความจะถูกกรอก หากโปรโตคอลกำหนดค่าและอนุญาต อาจมีข้อความค้างชำระ (เปิด) หลายข้อความพร้อมกันสำหรับช่องหนึ่งๆ

[ย้อนกลับ]: NO_ERROR กับความสำเร็จ; ข้อผิดพลาดเชิงลบเป็นอย่างอื่น

read_msg()

อ่านเนื้อหาของข้อความด้วย ID ที่ระบุโดยเริ่มจากออฟเซ็ตที่ระบุ

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

[ใน] handle : หมายเลขอ้างอิงของช่องที่จะอ่านข้อความ

[ใน] msg_id : ID ของข้อความที่จะอ่าน

[ใน] offset : ออฟเซ็ตเป็นข้อความที่จะเริ่มอ่าน

[ใน] msg : ชี้ไปที่โครงสร้าง ipc_msg_t ที่อธิบายชุดของบัฟเฟอร์ที่จะเก็บข้อมูลข้อความขาเข้า

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

เมธอด read_msg สามารถเรียกได้หลายครั้งโดยเริ่มจากออฟเซ็ตที่แตกต่างกัน (ไม่จำเป็นต้องเป็นลำดับ) ตามต้องการ

put_msg()

ยกเลิกข้อความที่มี ID ที่ระบุ

long put_msg(uint32_t handle, uint32_t msg_id);

[ใน] handle : จัดการของช่องที่ข้อความมาถึง

[ใน] msg_id : ID ของข้อความที่ถูกยกเลิก

[ย้อนกลับ]: NO_ERROR กับความสำเร็จ; ข้อผิดพลาดเชิงลบเป็นอย่างอื่น

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

ตัวอธิบายไฟล์ API

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

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

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

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

เมธอดใน File Descriptor API

อ่าน()

พยายามอ่านเพื่อ count ไบต์ข้อมูลจากตัวอธิบายไฟล์ที่ระบุ

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

[ใน] fd : ตัวอธิบายไฟล์ที่จะอ่าน

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

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

[retval]: ส่งคืนจำนวนไบต์ที่อ่าน; ข้อผิดพลาดเชิงลบเป็นอย่างอื่น

เขียน()

เขียนขึ้นเพื่อ count ไบต์ของข้อมูลไปยัง file descriptor ที่ระบุ

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

[ใน] fd : ตัวอธิบายไฟล์ที่จะเขียน

[ออก] buf : ชี้ไปยังข้อมูลที่จะเขียน

[ใน] count : จำนวนไบต์สูงสุดที่จะเขียน

[retval]: ส่งคืนจำนวนไบต์ที่เขียน; ข้อผิดพลาดเชิงลบเป็นอย่างอื่น

ioctl()

เรียกใช้คำสั่ง ioctl ที่ระบุสำหรับ file descriptor ที่กำหนด

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

[ใน] fd : ตัวอธิบายไฟล์ที่จะเรียกใช้ ioctl()

[ใน] cmd : คำสั่ง ioctl

[เข้า/ออก] args : ชี้ไปที่ ioctl() ข้อโต้แย้ง

API เบ็ดเตล็ด

เมธอดใน Miscellaneous API

รับเวลา ()

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

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

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

[ใน] flags ก : สงวนไว้ ควรเป็นศูนย์

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

[ย้อนกลับ]: NO_ERROR กับความสำเร็จ; ข้อผิดพลาดเชิงลบเป็นอย่างอื่น

นาโนสลีป()

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

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

[ใน] clock_id : สงวนไว้ ควรเป็นศูนย์

[ใน] flags ก : สงวนไว้ ควรเป็นศูนย์

[ใน] sleep_time : เวลาสลีปในหน่วยนาโนวินาที

[ย้อนกลับ]: NO_ERROR กับความสำเร็จ; ข้อผิดพลาดเชิงลบเป็นอย่างอื่น

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

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

#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 ข้อความแบบอะซิงโครนัสไปยังบริการ "echo" และจัดการการตอบกลับ

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 สามารถเข้าถึงได้จากเคอร์เนลและโปรแกรมพื้นที่ผู้ใช้ที่ทำงานด้านที่ไม่ปลอดภัย

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

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

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

โปรแกรมพื้นที่ผู้ใช้เริ่มเซสชันการสื่อสารโดยเรียก tipc_connect() เพื่อเริ่มต้นการเชื่อมต่อกับบริการ Trusty ที่ระบุ ภายในการ tipc_connect() จะเปิดโหนดอุปกรณ์ที่ระบุเพื่อรับ file descriptor และเรียก TIPC_IOC_CONNECT ioctl() ด้วยพารามิเตอร์ argp ที่ชี้ไปที่สตริงที่มีชื่อบริการที่จะเชื่อมต่อ

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

ตัวอธิบายไฟล์ที่เป็นผลลัพธ์สามารถใช้เพื่อสื่อสารกับบริการที่สร้างขึ้นเท่านั้น file descriptor ควรปิดโดยเรียก tipc_close() เมื่อไม่ต้องการการเชื่อมต่ออีกต่อไป

file descriptor ที่ได้รับจากการ tipc_connect() ทำหน้าที่เป็นโหนดอุปกรณ์อักขระทั่วไป ตัวอธิบายไฟล์:

  • สามารถเปลี่ยนเป็นโหมดไม่ปิดกั้นได้หากจำเป็น
  • สามารถเขียนโดยใช้การเรียก standard write() เพื่อส่งข้อความไปยังอีกด้านหนึ่งได้
  • สามารถสำรวจได้ (โดยใช้การเรียกแบบ poll() หรือ select() การเรียก) สำหรับความพร้อมใช้งานของข้อความขาเข้าเป็นตัวอธิบายไฟล์ปกติ
  • สามารถอ่านเพื่อดึงข้อความขาเข้า

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

tipc_connect()

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

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

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

[ใน] srv_name : ชื่อของบริการ Trusty ที่เผยแพร่เพื่อเชื่อมต่อ

[retval]: ตัวอธิบายไฟล์ที่ถูกต้องสำหรับความสำเร็จ -1 มิฉะนั้น

tipc_close()

ปิดการเชื่อมต่อกับบริการ Trusty ที่ระบุโดย file descriptor

int tipc_close(int fd);

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

Kernel Trusty IPC Client API

เคอร์เนล Trusty IPC Client API พร้อมใช้งานสำหรับไดรเวอร์เคอร์เนล พื้นที่ผู้ใช้ 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() (ซึ่งถูกเรียกในบริบทของคิวงาน trusty-ipc 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()

สร้างและกำหนดค่าอินสแตนซ์ของช่อง Trusty IPC สำหรับอุปกรณ์ trusty-ipc โดยเฉพาะ

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

[ใน] dev : ชี้ไปที่ trusty-ipc ที่สร้างช่องสัญญาณของอุปกรณ์

[ใน] ops : ชี้ไปที่ struct tipc_chan_ops พร้อมการเรียกกลับเฉพาะผู้โทรเข้า

[ใน] cb_arg : ตัวชี้ไปยังข้อมูลที่จะถูกส่งไปยังการเรียกกลับ tipc_chan_ops

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

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

เหตุการณ์ void (*handle_event)(void *cb_arg, int event) ถูกเรียกใช้เพื่อแจ้งผู้โทรเกี่ยวกับการเปลี่ยนแปลงสถานะของแชนเนล

[ใน] cb_arg : ตัวชี้ไปยังข้อมูลที่ส่งไปยัง tipc_create_channel() call

[ใน] event : เหตุการณ์ที่สามารถเป็นหนึ่งในค่าต่อไปนี้:

  • TIPC_CHANNEL_CONNECTED - ระบุการเชื่อมต่อกับฝั่งระยะไกลได้สำเร็จ
  • TIPC_CHANNEL_DISCONNECTED - ระบุว่าฝั่งระยะไกลปฏิเสธคำขอเชื่อมต่อใหม่หรือขอยกเลิกการเชื่อมต่อสำหรับช่องสัญญาณที่เชื่อมต่อก่อนหน้านี้
  • TIPC_CHANNEL_SHUTDOWN - ระบุว่าฝั่งระยะไกลกำลังปิดตัวลง เป็นการยุติการเชื่อมต่อทั้งหมดอย่างถาวร

การเรียก struct tipc_msg_buf *(*handle_msg)(void *cb_arg, struct tipc_msg_buf *mb) ถูกเรียกใช้เพื่อให้การแจ้งเตือนว่าได้รับข้อความใหม่ผ่านช่องทางที่ระบุ:

  • [ใน] cb_arg : ตัวชี้ไปยังข้อมูลที่ส่งไปยังการ tipc_create_channel()
  • [ใน] 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);

[ใน] chan : ตัวชี้ไปยังช่องที่ส่งคืนโดยการ tipc_create_chan()

[ใน] port : ชี้ไปที่สตริงที่มีชื่อบริการที่จะเชื่อมต่อ

[retval]: 0 เมื่อสำเร็จ ข้อผิดพลาดด้านลบเป็นอย่างอื่น

ผู้โทรจะได้รับแจ้งเมื่อมีการสร้างการเชื่อมต่อโดยรับการเรียกกลับ handle_event

tipc_chan_shutdown()

ยุติการเชื่อมต่อกับบริการ Trusty IPC ที่เริ่มต้นโดยการ tipc_chan_connect() ก่อนหน้านี้

int tipc_chan_shutdown(struct tipc_chan *chan);

[ใน] chan : ตัวชี้ไปยังช่องที่ส่งคืนโดยการ tipc_create_chan()

tipc_chan_destroy()

ทำลายช่อง Trusty IPC ที่ระบุ

void tipc_chan_destroy(struct tipc_chan *chan);

[ใน] chan : ตัวชี้ไปยังช่องที่ส่งคืนโดยการ tipc_create_chan()

tipc_chan_get_txbuf_timeout()

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

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

[ใน] chan : ชี้ไปที่ช่องที่จะจัดคิวข้อความ

[ใน] chan : หมดเวลาสูงสุดเพื่อรอจนกว่าบัฟเฟอร์ tx จะพร้อมใช้งาน

[retval]: บัฟเฟอร์ข้อความที่ถูกต้องเมื่อสำเร็จ ERR_PTR(err) จากข้อผิดพลาด

tipc_chan_queue_msg()

จัดคิวข้อความที่จะส่งผ่านช่องทาง Trusty IPC ที่ระบุ

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

[ใน] chan : ชี้ไปที่ช่องที่จะจัดคิวข้อความ

[ใน] 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);

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

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

[ย้อนหลัง]: ไม่มี

tipc_chan_get_rxbuf()

ได้รับบัฟเฟอร์ข้อความใหม่ที่สามารถใช้เพื่อรับข้อความผ่านช่องทางที่ระบุ

struct tipc_msg_buf *tipc_chan_get_rxbuf(struct tipc_chan *chan);

[ใน] 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);

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

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

[ย้อนหลัง]: ไม่มี