বিশ্বস্ত API রেফারেন্স

ট্রাস্টি দুটি শ্রেণীর অ্যাপ্লিকেশন/পরিষেবা বিকাশের জন্য API প্রদান করে:

  • বিশ্বস্ত অ্যাপ্লিকেশন বা পরিষেবা যা TEE প্রসেসরে চলে
  • সাধারণ/অবিশ্বস্ত অ্যাপ্লিকেশন যা প্রধান প্রসেসরে চলে এবং বিশ্বস্ত অ্যাপ্লিকেশন দ্বারা প্রদত্ত পরিষেবা ব্যবহার করে

ট্রাস্টি এপিআই সাধারণত বিশ্বস্ত আন্তঃপ্রক্রিয়া যোগাযোগ (আইপিসি) সিস্টেমকে বর্ণনা করে, যার মধ্যে অ-নিরাপদ বিশ্বের সাথে যোগাযোগ রয়েছে। প্রধান প্রসেসরে চলমান সফ্টওয়্যার বিশ্বস্ত অ্যাপ্লিকেশন/পরিষেবাগুলির সাথে সংযোগ করতে বিশ্বস্ত API ব্যবহার করতে পারে এবং আইপি-তে একটি নেটওয়ার্ক পরিষেবার মতোই তাদের সাথে নির্বিচারে বার্তা বিনিময় করতে পারে। একটি অ্যাপ-স্তরের প্রোটোকল ব্যবহার করে এই বার্তাগুলির ডেটা বিন্যাস এবং শব্দার্থবিদ্যা নির্ধারণ করা অ্যাপ্লিকেশনের উপর নির্ভর করে। বার্তাগুলির নির্ভরযোগ্য ডেলিভারি অন্তর্নিহিত বিশ্বস্ত পরিকাঠামো (প্রধান প্রসেসরে চালিত ড্রাইভারের আকারে) দ্বারা নিশ্চিত করা হয় এবং যোগাযোগ সম্পূর্ণরূপে অসিঙ্ক্রোনাস।

বন্দর এবং চ্যানেল

পোর্টগুলি বিশ্বস্ত অ্যাপ্লিকেশনগুলি দ্বারা পরিষেবার শেষ-পয়েন্টগুলিকে একটি নামযুক্ত পাথের আকারে প্রকাশ করতে ব্যবহৃত হয় যার সাথে ক্লায়েন্টরা সংযোগ করে৷ এটি ক্লায়েন্টদের ব্যবহারের জন্য একটি সাধারণ, স্ট্রিং-ভিত্তিক পরিষেবা আইডি দেয়। নামকরণের নিয়ম হল বিপরীত-DNS-শৈলীর নামকরণ, যেমন com.google.servicename

যখন একটি ক্লায়েন্ট একটি পোর্টের সাথে সংযোগ করে, ক্লায়েন্ট একটি পরিষেবার সাথে ইন্টারঅ্যাক্ট করার জন্য একটি চ্যানেল পায়। পরিষেবাটিকে অবশ্যই একটি ইনকামিং সংযোগ গ্রহণ করতে হবে, এবং যখন এটি করে, এটিও একটি চ্যানেল গ্রহণ করে৷ সংক্ষেপে, পোর্টগুলি পরিষেবাগুলি সন্ধান করার জন্য ব্যবহৃত হয় এবং তারপরে এক জোড়া সংযুক্ত চ্যানেলের মাধ্যমে যোগাযোগ ঘটে (অর্থাৎ, একটি বন্দরে সংযোগের উদাহরণ)। যখন একটি ক্লায়েন্ট একটি পোর্টের সাথে সংযোগ করে, একটি প্রতিসম, দ্বি-দিকনির্দেশক সংযোগ স্থাপন করা হয়। এই পূর্ণ-দ্বৈত পথটি ব্যবহার করে, ক্লায়েন্ট এবং সার্ভার উভয় পক্ষই সংযোগটি ছিন্ন করার সিদ্ধান্ত না নেওয়া পর্যন্ত নির্বিচারে বার্তা বিনিময় করতে পারে।

শুধুমাত্র নিরাপদ-সাইড বিশ্বস্ত অ্যাপ্লিকেশন বা বিশ্বস্ত কার্নেল মডিউল পোর্ট তৈরি করতে পারে। অ-সুরক্ষিত দিকে (সাধারণ বিশ্বে) চলমান অ্যাপ্লিকেশনগুলি শুধুমাত্র নিরাপদ দিক দ্বারা প্রকাশিত পরিষেবাগুলির সাথে সংযোগ করতে পারে৷

প্রয়োজনীয়তার উপর নির্ভর করে, একটি বিশ্বস্ত অ্যাপ্লিকেশন একই সময়ে একটি ক্লায়েন্ট এবং একটি সার্ভার উভয়ই হতে পারে। একটি বিশ্বস্ত অ্যাপ্লিকেশন যা একটি পরিষেবা প্রকাশ করে (একটি সার্ভার হিসাবে) অন্যান্য পরিষেবাগুলির সাথে সংযোগ করতে হতে পারে (ক্লায়েন্ট হিসাবে)৷

হ্যান্ডেল API

হ্যান্ডলগুলি হল স্বাক্ষরবিহীন পূর্ণসংখ্যা যা পোর্ট এবং চ্যানেলের মতো সংস্থানগুলিকে প্রতিনিধিত্ব করে, যা UNIX-এর ফাইল বর্ণনাকারীর মতো। হ্যান্ডেলগুলি তৈরি হওয়ার পরে, সেগুলি একটি অ্যাপ্লিকেশন-নির্দিষ্ট হ্যান্ডেল টেবিলে স্থাপন করা হয় এবং পরে উল্লেখ করা যেতে পারে।

একজন কলার set_cookie() পদ্ধতি ব্যবহার করে একটি হ্যান্ডেলের সাথে ব্যক্তিগত ডেটা সংযুক্ত করতে পারেন।

হ্যান্ডেল API-এ পদ্ধতি

হ্যান্ডলগুলি শুধুমাত্র একটি অ্যাপ্লিকেশনের প্রসঙ্গে বৈধ। স্পষ্টভাবে নির্দিষ্ট না করা পর্যন্ত একটি অ্যাপ্লিকেশন অন্য অ্যাপ্লিকেশনে একটি হ্যান্ডেলের মান পাস করা উচিত নয়। একটি হ্যান্ডেল মান শুধুমাত্র INVALID_IPC_HANDLE #define, যা একটি অ্যাপ্লিকেশন ব্যবহার করতে পারে একটি ইঙ্গিত হিসাবে যে একটি হ্যান্ডেল অবৈধ বা সেট করা নেই৷

একটি নির্দিষ্ট হ্যান্ডেলের সাথে কলার-প্রদত্ত ব্যক্তিগত ডেটা সংযুক্ত করে।

long set_cookie(uint32_t handle, void *cookie)

[in] handle : API কলগুলির একটি দ্বারা যে কোনো হ্যান্ডেল ফেরত দেওয়া হয়

[in] cookie : বিশ্বস্ত অ্যাপ্লিকেশনে নির্বিচারে ব্যবহারকারী-স্পেস ডেটার নির্দেশক

[retval]: সাফল্যে NO_ERROR , < 0 ত্রুটি কোড অন্যথায়

এই কলটি হ্যান্ডেল তৈরি হওয়ার পরে পরবর্তী সময়ে ঘটলে ঘটনাগুলি পরিচালনার জন্য কার্যকর। ইভেন্ট-হ্যান্ডলিং মেকানিজম হ্যান্ডেল এবং এর কুকি ইভেন্ট হ্যান্ডলারকে ফেরত সরবরাহ করে।

wait() কল ব্যবহার করে ইভেন্টের জন্য হ্যান্ডেলগুলি অপেক্ষা করা যেতে পারে।

অপেক্ষা করুন()

নির্দিষ্ট সময়ের জন্য একটি প্রদত্ত হ্যান্ডেলে একটি ইভেন্ট হওয়ার জন্য অপেক্ষা করে।

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

[in] handle_id : যে কোনো হ্যান্ডেল API কলগুলির একটি দ্বারা ফেরত দেওয়া হয়

[আউট] 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() পদ্ধতিতে কল করে হ্যান্ডেলগুলি ধ্বংস করা যেতে পারে।

বন্ধ ()

নির্দিষ্ট হ্যান্ডেলের সাথে যুক্ত সংস্থানকে ধ্বংস করে এবং হ্যান্ডেল টেবিল থেকে সরিয়ে দেয়।

long close(uint32_t handle_id);

[in] handle_id : ধ্বংস করতে হ্যান্ডেল

[retval]: 0 যদি সফল হয়; অন্যথায় একটি নেতিবাচক ত্রুটি

সার্ভার API

একটি সার্ভার তার পরিষেবার শেষ-পয়েন্টগুলির প্রতিনিধিত্ব করে এক বা একাধিক নামযুক্ত পোর্ট তৈরি করে শুরু হয়। প্রতিটি পোর্ট একটি হ্যান্ডেল দ্বারা প্রতিনিধিত্ব করা হয়.

সার্ভার 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 : ক্লায়েন্টের সাথে ডেটা আদান-প্রদানের সুবিধার্থে এই পোর্টে একটি চ্যানেল প্রাক-বরাদ্দ করতে পারে এমন বাফারের সর্বাধিক সংখ্যা। উভয় দিকের ডেটার জন্য বাফারগুলিকে আলাদাভাবে গণনা করা হয়, তাই এখানে 1 উল্লেখ করার অর্থ হল 1টি পাঠান এবং 1টি প্রাপ্ত বাফার আগে থেকে বরাদ্দ করা হয়েছে৷ সাধারণভাবে, প্রয়োজনীয় বাফারের সংখ্যা ক্লায়েন্ট এবং সার্ভারের মধ্যে উচ্চ-স্তরের প্রোটোকল চুক্তির উপর নির্ভর করে। খুব সিঙ্ক্রোনাস প্রোটোকলের ক্ষেত্রে সংখ্যাটি 1 এর মতো কম হতে পারে (বার্তা পাঠান, অন্য পাঠানোর আগে উত্তর গ্রহণ করুন)। তবে সংখ্যাটি আরও বেশি হতে পারে যদি ক্লায়েন্ট একটি উত্তর উপস্থিত হওয়ার আগে একাধিক বার্তা প্রেরণের আশা করে (যেমন, একটি বার্তা একটি প্রস্তাবনা হিসাবে এবং অন্যটি প্রকৃত কমান্ড হিসাবে)। বরাদ্দকৃত বাফার সেটগুলি প্রতি চ্যানেল, তাই দুটি পৃথক সংযোগের (চ্যানেল) পৃথক বাফার সেট থাকবে।

[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() কল করা এবং একটি চ্যানেল (অন্য হ্যান্ডেল দ্বারা প্রতিনিধিত্ব করা) তৈরি করা উচিত যা আগত বার্তাগুলির জন্য পোল করা যেতে পারে। .

গ্রহণ করুন()

একটি ইনকামিং সংযোগ গ্রহণ করে এবং একটি চ্যানেলে একটি হ্যান্ডেল পায়৷

long accept(uint32_t handle_id, uuid_t *peer_uuid);

[in] handle_id : হ্যান্ডেল যে পোর্টের সাথে একটি ক্লায়েন্ট সংযোগ করেছে তার প্রতিনিধিত্ব করে

[out] peer_uuid : সংযোগকারী ক্লায়েন্ট অ্যাপ্লিকেশনের UUID দিয়ে পূরণ করার জন্য একটি uuid_t কাঠামোর দিকে নির্দেশক। সংযোগটি অ-নিরাপদ বিশ্ব থেকে উদ্ভূত হলে এটি সমস্ত শূন্যে সেট করা হবে৷

[retval]: একটি চ্যানেল হ্যান্ডেল (যদি অ-নেতিবাচক) যেখানে সার্ভার ক্লায়েন্টের সাথে বার্তা বিনিময় করতে পারে (বা অন্যথায় একটি ত্রুটি কোড)

ক্লায়েন্ট API

এই বিভাগে ক্লায়েন্ট API-এর পদ্ধতি রয়েছে।

ক্লায়েন্ট API-এ পদ্ধতি

সংযোগ ()

নামের দ্বারা নির্দিষ্ট একটি পোর্টের সাথে একটি সংযোগ শুরু করে।

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

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

মেসেজিং API

মেসেজিং এপিআই কলগুলি পূর্বে প্রতিষ্ঠিত সংযোগ (চ্যানেল) এর মাধ্যমে বার্তা পাঠানো এবং পড়া সক্ষম করে। মেসেজিং API কল সার্ভার এবং ক্লায়েন্টদের জন্য একই।

একটি ক্লায়েন্ট একটি connect() কল ইস্যু করে একটি চ্যানেলে একটি হ্যান্ডেল পায় এবং একটি সার্ভার উপরে বর্ণিত একটি accept() কল থেকে একটি চ্যানেল হ্যান্ডেল পায়।

একটি বিশ্বস্ত বার্তার কাঠামো

নিম্নলিখিত হিসাবে দেখানো হয়েছে, বিশ্বস্ত 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 কাঠামোর একটি অ্যারে দ্বারা উপস্থাপিত এক বা একাধিক অ-সংলগ্ন বাফারের সমন্বয়ে গঠিত হতে পারে। ট্রাস্টি iov অ্যারে ব্যবহার করে এই ব্লকগুলিতে স্ক্যাটার-গেদার রিড এবং লেখে। বাফারের বিষয়বস্তু যা iov অ্যারে দ্বারা বর্ণনা করা যেতে পারে সম্পূর্ণ নির্বিচারে।

মেসেজিং 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 : বার্তার মধ্যে অফসেট যা থেকে পড়া শুরু করতে হবে

[আউট] 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

ফাইল বর্ণনাকারী API-তে read() , write() , এবং ioctl() কল রয়েছে। এই সমস্ত কলগুলি পূর্বনির্ধারিত (স্ট্যাটিক) ফাইল বর্ণনাকারীর সেটে কাজ করতে পারে যা ঐতিহ্যগতভাবে ছোট সংখ্যা দ্বারা উপস্থাপিত হয়। বর্তমান বাস্তবায়নে, ফাইল বর্ণনাকারী স্থানটি IPC হ্যান্ডেল স্থান থেকে পৃথক। ট্রাস্টিতে ফাইল বর্ণনাকারী API একটি প্রথাগত ফাইল বর্ণনাকারী-ভিত্তিক API-এর মতো।

ডিফল্টরূপে, 3টি পূর্বনির্ধারিত (স্ট্যান্ডার্ড এবং সুপরিচিত) ফাইল বর্ণনাকারী রয়েছে:

  • 0 - স্ট্যান্ডার্ড ইনপুট। স্ট্যান্ডার্ড ইনপুট fd এর ডিফল্ট বাস্তবায়ন একটি নো-অপ (যেহেতু বিশ্বস্ত অ্যাপ্লিকেশনগুলির একটি ইন্টারেক্টিভ কনসোল থাকবে বলে আশা করা হয় না) তাই fd 0-এ ioctl() পড়া, লেখা বা আহ্বান করলে একটি ERR_NOT_SUPPORTED ত্রুটি ফিরে আসবে।
  • 1 - স্ট্যান্ডার্ড আউটপুট। স্ট্যান্ডার্ড আউটপুটে লেখা ডেটা UART এবং/অথবা প্ল্যাটফর্ম এবং কনফিগারেশনের উপর নির্ভর করে অ-সুরক্ষিত দিকে উপলব্ধ একটি মেমরি লগ (LK ডিবাগ স্তরের উপর নির্ভর করে) রুট করা যেতে পারে। অ-গুরুত্বপূর্ণ ডিবাগ লগ এবং বার্তাগুলি আদর্শ আউটপুটে যাওয়া উচিত। read() এবং ioctl() পদ্ধতি নো-অপস এবং একটি ERR_NOT_SUPPORTED ত্রুটি ফেরত দেওয়া উচিত।
  • 2 - স্ট্যান্ডার্ড ত্রুটি। স্ট্যান্ডার্ড ত্রুটিতে লেখা ডেটা প্ল্যাটফর্ম এবং কনফিগারেশনের উপর নির্ভর করে, অ-সুরক্ষিত দিকে উপলব্ধ UART বা মেমরি লগে রুট করা উচিত। স্ট্যান্ডার্ড ত্রুটির জন্য শুধুমাত্র সমালোচনামূলক বার্তাগুলি লেখার সুপারিশ করা হয়, কারণ এই স্ট্রিমটি নিরবচ্ছিন্ন হওয়ার সম্ভাবনা খুব বেশি। read() এবং ioctl() পদ্ধতি নো-অপস এবং একটি ERR_NOT_SUPPORTED ত্রুটি ফেরত দেওয়া উচিত।

যদিও ফাইল বর্ণনাকারীর এই সেটটি আরও fds (প্ল্যাটফর্ম-নির্দিষ্ট এক্সটেনশনগুলি বাস্তবায়নের জন্য) বাস্তবায়নের জন্য প্রসারিত করা যেতে পারে, তবে ফাইল বর্ণনাকারীদের প্রসারিত করা সতর্কতার সাথে ব্যবহার করা প্রয়োজন। ফাইল বর্ণনাকারীকে প্রসারিত করা দ্বন্দ্ব তৈরির প্রবণতা এবং সাধারণত সুপারিশ করা হয় না।

ফাইল বর্ণনাকারী API-এ পদ্ধতি

পড়ুন()

একটি নির্দিষ্ট ফাইল বর্ণনাকারী থেকে ডেটা বাইট count জন্য পড়ার চেষ্টা করে।

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

[in] fd : ফাইল বর্ণনাকারী যা থেকে পড়তে হবে

[আউট] buf : একটি বাফারের নির্দেশক যেখানে ডেটা সংরক্ষণ করা যায়

[in] count : পড়ার জন্য সর্বাধিক বাইট সংখ্যা

[retval]: পড়া বাইট সংখ্যা ফেরত; অন্যথায় একটি নেতিবাচক ত্রুটি

লিখুন()

নির্দিষ্ট ফাইল বর্ণনাকারীতে ডেটার বাইট count পর্যন্ত লেখে।

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

[in] fd : ফাইল বর্ণনাকারী যা লিখতে হবে

[আউট] 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

বিবিধ API-এ পদ্ধতি

সময় পেতে()

বর্তমান সিস্টেম সময় প্রদান করে (ন্যানোসেকেন্ডে)।

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

[in] clock_id : প্ল্যাটফর্ম-নির্ভর; ডিফল্টের জন্য শূন্য পাস

[in] flags : সংরক্ষিত, শূন্য হওয়া উচিত

[আউট] time : একটি int64_t মান নির্দেশক যা বর্তমান সময় সংরক্ষণ করতে হবে

[retval]: সাফল্যের উপর NO_ERROR ; অন্যথায় একটি নেতিবাচক ত্রুটি

ন্যানোস্লিপ()

একটি নির্দিষ্ট সময়ের জন্য কলিং অ্যাপ্লিকেশানের কার্য সম্পাদন স্থগিত করে এবং সেই সময়ের পরে আবার শুরু করে৷

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

[in] clock_id : সংরক্ষিত, শূন্য হওয়া উচিত

[in] flags : সংরক্ষিত, শূন্য হওয়া উচিত

[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 এবং অ্যাপ্লিকেশন

বিশ্বস্ত পরিষেবাগুলির একটি সেট, সুরক্ষিত দিক থেকে প্রকাশিত এবং IPC_PORT_ALLOW_NS_CONNECT অ্যাট্রিবিউট দিয়ে চিহ্নিত, অ-সুরক্ষিত দিকে চলমান কার্নেল এবং ব্যবহারকারী স্পেস প্রোগ্রামগুলিতে অ্যাক্সেসযোগ্য।

নন-সিকিউর সাইডে এক্সিকিউশন এনভায়রনমেন্ট (কার্নেল এবং ইউজার স্পেস) সিকিউর সাইডের এক্সিকিউশন এনভায়রনমেন্ট থেকে একেবারে আলাদা। অতএব, উভয় পরিবেশের জন্য একটি একক লাইব্রেরির পরিবর্তে, API-এর দুটি ভিন্ন সেট রয়েছে। কার্নেলে, ক্লায়েন্ট এপিআই বিশ্বস্ত-আইপিসি কার্নেল ড্রাইভার দ্বারা সরবরাহ করা হয় এবং একটি অক্ষর ডিভাইস নোড নিবন্ধন করে যা ব্যবহারকারীর স্থান প্রক্রিয়া দ্বারা নিরাপদ দিকে চলমান পরিষেবাগুলির সাথে যোগাযোগ করতে ব্যবহার করা যেতে পারে।

ব্যবহারকারী স্থান বিশ্বস্ত IPC ক্লায়েন্ট API

ব্যবহারকারী স্থান বিশ্বস্ত IPC ক্লায়েন্ট API লাইব্রেরি হল ডিভাইস নোড 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 এর জন্য একটি লিখিত কল সম্পাদন করে বিশ্বস্ত পরিষেবাতে একটি বার্তা পাঠান। উপরের write() কলে পাস করা সমস্ত ডেটা বিশ্বস্ত-আইপিসি ড্রাইভার দ্বারা একটি বার্তায় রূপান্তরিত হয়। বার্তাটি নিরাপদ দিকে বিতরণ করা হয় যেখানে ট্রাস্টি কার্নেলে IPC সাবসিস্টেম দ্বারা ডেটা পরিচালনা করা হয় এবং সঠিক গন্তব্যে রুট করা হয় এবং একটি নির্দিষ্ট চ্যানেল হ্যান্ডেলে IPC_HANDLE_POLL_MSG ইভেন্ট হিসাবে একটি অ্যাপ ইভেন্ট লুপে বিতরণ করা হয়। নির্দিষ্ট, পরিষেবা-নির্দিষ্ট প্রোটোকলের উপর নির্ভর করে, বিশ্বস্ত পরিষেবা এক বা একাধিক উত্তর বার্তা পাঠাতে পারে যেগুলি অ-সুরক্ষিত দিকে ফেরত পাঠানো হয় এবং ব্যবহারকারীর স্থান অ্যাপ্লিকেশন read() কল।

tipc_connect()

একটি নির্দিষ্ট tipc ডিভাইস নোড খোলে এবং একটি নির্দিষ্ট বিশ্বস্ত পরিষেবার সাথে একটি সংযোগ শুরু করে।

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

[in] dev_name : খোলার জন্য বিশ্বস্ত IPC ডিভাইস নোডের পথ

[in] srv_name : একটি প্রকাশিত বিশ্বস্ত পরিষেবার নাম যার সাথে সংযোগ করতে হবে

[retval]: সফলতার উপর বৈধ ফাইল বর্ণনাকারী, -1 অন্যথায়।

tipc_close()

একটি ফাইল বর্ণনাকারী দ্বারা নির্দিষ্ট বিশ্বস্ত পরিষেবার সংযোগ বন্ধ করে৷

int tipc_close(int fd);

[in] fd : ফাইল বর্ণনাকারী আগে একটি tipc_connect() কল দ্বারা খোলা হয়েছিল

কার্নেল বিশ্বস্ত IPC ক্লায়েন্ট API

কার্নেল ট্রাস্টি IPC ক্লায়েন্ট API কার্নেল ড্রাইভারদের জন্য উপলব্ধ। ব্যবহারকারী স্থান বিশ্বস্ত IPC API এই API এর উপরে প্রয়োগ করা হয়েছে।

সাধারণভাবে, এই API-এর সাধারণ ব্যবহারে একজন কলার একটি struct tipc_chan অবজেক্ট তৈরি করে tipc_create_channel() ফাংশন ব্যবহার করে এবং তারপর নিরাপদ দিকে চলমান বিশ্বস্ত 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() কল করতে হবে যদি এটি এই ধরনের বাফার সারিবদ্ধ করতে ব্যর্থ হয় বা এটি আর প্রয়োজন হয় না।

একজন API ব্যবহারকারী একটি handle_msg() বিজ্ঞপ্তি কলব্যাক (যাকে বিশ্বস্ত-ipc rx ওয়ার্ককিউর প্রসঙ্গে বলা হয়) পরিচালনা করে দূরবর্তী দিক থেকে বার্তাগুলি গ্রহণ করে যা পরিচালনা করার জন্য একটি ইনকামিং বার্তা ধারণকারী একটি rx বাফারে একটি পয়েন্টার প্রদান করে।

এটা প্রত্যাশিত যে handle_msg() কলব্যাক বাস্তবায়ন একটি বৈধ struct tipc_msg_buf এ একটি পয়েন্টার ফিরিয়ে দেবে। এটি আগত বার্তা বাফারের মতোই হতে পারে যদি এটি স্থানীয়ভাবে পরিচালনা করা হয় এবং আর প্রয়োজন না হয়। বিকল্পভাবে, এটি একটি নতুন বাফার হতে পারে যা একটি tipc_chan_get_rxbuf() কল দ্বারা প্রাপ্ত হয় যদি ইনকামিং বাফারটি আরও প্রক্রিয়াকরণের জন্য সারিবদ্ধ থাকে। একটি বিচ্ছিন্ন rx বাফার ট্র্যাক করতে হবে এবং শেষ পর্যন্ত একটি tipc_chan_put_rxbuf() কল ব্যবহার করে ছেড়ে দিতে হবে যখন এটির আর প্রয়োজন নেই৷

কার্নেল ট্রাস্টি আইপিসি ক্লায়েন্ট API-এ পদ্ধতি

tipc_create_channel()

একটি নির্দিষ্ট বিশ্বস্ত-ipc ডিভাইসের জন্য একটি বিশ্বস্ত IPC চ্যানেলের একটি উদাহরণ তৈরি এবং কনফিগার করে।

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) কলব্যাক একটি নির্দিষ্ট চ্যানেলে একটি নতুন বার্তা গৃহীত হয়েছে তা বিজ্ঞপ্তি দেওয়ার জন্য আহ্বান করা হয়েছে:

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

নির্দিষ্ট বিশ্বস্ত 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_sutdown()

একটি tipc_chan_connect() কলের মাধ্যমে পূর্বে শুরু করা বিশ্বস্ত IPC পরিষেবার একটি সংযোগ বন্ধ করে।

int tipc_chan_shutdown(struct tipc_chan *chan);

[in] chan : tipc_create_chan() কলের মাধ্যমে ফিরে আসা একটি চ্যানেলের দিকে নির্দেশক

tipc_chan_destroy()

একটি নির্দিষ্ট বিশ্বস্ত 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()

একটি 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]: কিছুই না

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]: কিছুই না