Trusty API Referansı

Trusty, iki uygulama/hizmet sınıfı geliştirmek için API'ler sağlar:

  • TEE işlemcide çalışan güvenilir uygulamalar veya hizmetler
  • Ana işlemcide çalışan ve sağlanan hizmetleri kullanan normal/güvenilmeyen uygulamalar güvenilir uygulamalara göre

Trusty API genellikle Trusty işlemler arası iletişim (IPC) sistemini güvenli olmayan dünyayla iletişim de dahil olmak üzere. ana işlemci, güvenilir uygulamalara/hizmetlere bağlanmak için Trusty API'lerini kullanabilir ve IP üzerinden bir ağ hizmeti gibi rastgele mesajlar gönderip alabilirsiniz. Bu verilerin biçimini ve anlamını belirlemek uygulamaya bağlıdır uygulama düzeyinde bir protokol kullanarak İletilerin güvenilir bir şekilde teslim edilmesi temel Trusty altyapısı tarafından garanti edilir (sürücüler biçiminde ana işlemci üzerinde çalışıyor) ve iletişim tamamen eşzamansız.

Bağlantı noktaları ve kanallar

Bağlantı noktaları, Trusty uygulamaları tarafından hizmet uç noktalarını biçimde sunmak için kullanılır bir ad verilmiş olması gerekir. Bu yöntem basit, dize tabanlı kullanacağı hizmet kimliğidir. Adlandırma kuralı ters DNS stilidir adlandırma, ör. com.google.servicename

İstemci bir bağlantı noktasına bağlandığında, istemci etkileşim için bir kanal alır sahip olacaksınız. Hizmetin gelen bir bağlantıyı kabul etmesi gerekir ve aynı şekilde kanal alır. Temelde, bağlantı noktaları hizmet aramak için kullanılır. Daha sonra iletişim, iki bağlı kanal (ör. bağlantı örnekleri) için geçerlidir. İstemci bir bağlantı noktasına bağlandığında simetrik iki yönlü bağlantı kurulduğunda. İstemciler bu tam çift yönlü yolu kullanarak Sunucular, her iki taraf da ortadan kaldırmaya karar verene kadar rastgele mesajlar gönderip alabilir. bağlantıyı keser.

Yalnızca güvenli taraftaki güvenilir uygulamalar veya Trusty çekirdek modülleri bağlantı noktaları. Güvenli olmayan tarafta çalışan uygulamalar (normal dünyada) yalnızca güvenli tarafından yayınlanan hizmetlere bağlanmalıdır.

Gereksinimlere bağlı olarak, güvenilir bir uygulama hem istemci hem de ekleyebileceğiniz anlamına gelir. Hizmeti yayınlayan ( sunucusu) diğer hizmetlere (istemci olarak) bağlanması gerekebilir.

Herkese açık kullanıcı adı API'si

Herkese açık kullanıcı adları, bağlantı noktaları ve bağlantı noktaları gibi kaynakları temsil eden imzasız tam sayılardır. UNIX'teki dosya tanımlayıcılarına benzer. Herkese açık kullanıcı adları oluşturulduktan sonra uygulamaya özel bir herkese açık kullanıcı adı tablosuna yerleştirilir ve daha sonra.

Arayan, herkese açık kullanıcı adı için şunları kullanarak gizli verileri bir herkese açık kullanıcı adıyla ilişkilendirebilir: set_cookie() yöntemi.

Handle API'deki Yöntemler

Herkese açık kullanıcı adları yalnızca bir uygulama bağlamında geçerlidir. Başvuru, herkese açık kullanıcı adı açıkça belirtilmediği sürece belirtiliyor. Herkese açık kullanıcı adı değeri, yalnızca bir uygulamanın kullanabileceği INVALID_IPC_HANDLE #define, bir herkese açık kullanıcı adının geçersiz olduğunu veya ayarlanmadığını gösterir.

Arayan tarafından sağlanan gizli verileri, belirtilen bir herkese açık kullanıcı adıyla ilişkilendirir.

long set_cookie(uint32_t handle, void *cookie)

[içinde] handle: API çağrılarından biri tarafından döndürülen herkese açık kullanıcı adı

[in] cookie: Trusty uygulamasındaki rastgele kullanıcı alanı verilerine işaretçi

[retval]: başarılı sonuçta NO_ERROR, aksi takdirde < 0 hata kodu

Bu çağrı, daha sonra gerçekleşen etkinliklerin işlenmesinde yararlıdır. herkese açık kullanıcı adı oluşturuldu. Etkinlik işleme mekanizması, herkese açık kullanıcı adını sağlar. ve çerezini etkinlik işleyiciye geri gönderir.

Herkese açık kullanıcı adları, wait() çağrısı kullanılarak etkinliklerde beklenebilir.

Wait()

Bir etkinliğin belirli bir süre boyunca, belirli bir herkese açık kullanıcı adında gerçekleşmesini bekler.

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

[içinde] handle_id: API çağrılarından biri tarafından döndürülen herkese açık kullanıcı adı

[out] event: Yapıyı temsil eden bir işaretçi bu herkese açık kullanıcı adında gerçekleşen bir etkinlik

[in] timeout_msecs: Milisaniye cinsinden zaman aşımı değeri; CANNOT TRANSLATE -1 değeri sonsuz bir zaman aşımıdır

[retval]: NO_ERROR belirtilen zaman aşımı aralığı; Belirtilen bir zaman aşımı süresi geçmişse ancak hiç zaman aşımı olmuşsa ERR_TIMED_OUT Etkinlik gerçekleştiyse; Diğer hatalar için < 0

Başarı üzerine (retval == NO_ERROR), wait() araması belirtilen bir uevent_t yapısını önemli bir nokta.

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 alanı aşağıdaki değerlerin bir kombinasyonunu içerir:

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: Gerçekte beklemede olan hiçbir etkinlik yok. arayan, beklemeyi yeniden başlatmalıdır

IPC_HANDLE_POLL_ERROR - Belirlenemeyen bir dahili hata oluştu

IPC_HANDLE_POLL_READY - aşağıdaki gibi herkese açık kullanıcı adı türüne bağlıdır:

  • Bağlantı noktaları için bu değer, beklemede olan bir bağlantı olduğunu gösterir
  • Kanallar için bu değer, eşzamansız bir bağlantının (bkz. connect()) kuruldu

Aşağıdaki etkinlikler yalnızca kanallar için geçerlidir:

  • IPC_HANDLE_POLL_HUP, kanalın bir eş tarafından kapatıldığını gösterir
  • IPC_HANDLE_POLL_MSG: Bu kanal için bekleyen bir mesaj olduğunu gösterir
  • IPC_HANDLE_POLL_SEND_UNBLOCKED - daha önce gönderen engellenen arayan, mesajı tekrar gönderin (ayrıntılar için send_msg() açıklamasına bakın)

Bir etkinlik işleyici, belirtilen kombinasyonun bir kombinasyonunu işleyecek şekilde hazırlanmalıdır. etkinlikleri için de önemlidir. Örneğin, olabilir, bu nedenle beklemedeki mesajlar olabilir ve bağlantınız aynı anda sizinle iletişim kurabiliyor.

Çoğu etkinlik sabittir. Temel koşul devam ettiği sürece devam eder (örneğin, bekleyen tüm iletiler alınmıştır ve bağlantı beklemededir emin olun. Ancak bir istisna olan IPC_HANDLE_POLL_SEND_UNBLOCKED etkinliği durumu okunduğunda temizlenir ve uygulamanın yalnızca bir kez ele alacağız.

Herkese açık kullanıcı adları, close() yöntemi çağrılanarak kaldırılabilir.

kapat()

Belirtilen herkese açık kullanıcı adıyla ilişkilendirilmiş kaynağı kaldırır ve hedefi şuradan kaldırır: kullanıcı adı tablosu.

long close(uint32_t handle_id);

[in] handle_id: Yok etmek için tutma yeri

[retval]: başarılıysa 0; aksi takdirde negatif bir hata oluşur

Sunucu API'si

Sunucu, başlangıç ayarlarını temsil eden bir veya daha fazla adlandırılmış bağlantı noktası uç noktalara gider. Her bağlantı noktası bir herkese açık kullanıcı adıyla temsil edilir.

Server API'deki yöntemler

port_create()

Adlandırılmış bir hizmet bağlantı noktası oluşturur.

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

[içinde] path: Bağlantı noktasının dize adı (yukarıda açıklandığı gibi). Bu ad, sistem genelinde benzersiz olmalıdır; başarısız olur.

[in] num_recv_bufs: Bir kanalın bulunduğu maksimum tampon sayısı bu bağlantı noktası, istemciyle veri alışverişini kolaylaştırmak için önceden tahsis edilebilir. Tamponlar sayılır her iki yönde giden veriler için ayrı ayrı olduğundan burada 1'in belirtilmesi 1 anlamına gelir gönder ve 1 alma arabelleği önceden tahsis edildi. Genel olarak tampon sayısı gereklilik, istemci ile istemci arasındaki üst düzey protokol sözleşmesine bağlıdır. sunucu. Çok eşzamanlı bir protokol söz konusu olduğunda sayı 1 kadar küçük olabilir. (ileti gönder, başka bir ileti göndermeden önce yanıt al). Ancak bu sayı bir yanıt gönderemeden birden fazla mesaj göndermeyi beklerse (ör.bir mesaj giriş olarak, başka bir mesaj da gerçek komut olarak gösterilir). İlgili içeriği oluşturmak için kullanılan ayrılan arabellek kümelerinin her kanal için geçerli olduğundan, iki ayrı bağlantı (kanallar) ayrı tampon kümeleri olur.

[in] recv_buf_size: üst sınır grubudur. Bu değer protokole bağlıdır ve gönderip alabileceğiniz maksimum ileti boyutunu etkili bir şekilde sınırlar eş ile

[içinde] flags: Ek bağlantı noktası davranışı belirten işaretlerin kombinasyonu

Bu değer, aşağıdaki değerlerin bir kombinasyonu olmalıdır:

IPC_PORT_ALLOW_TA_CONNECT - Diğer güvenli uygulamalardan bağlantıya izin verir

IPC_PORT_ALLOW_NS_CONNECT - güvenli olmayan dünyadan bağlantıya izin verir

[retval]: Negatif değilse oluşturulan bağlantı noktasını veya negatif

Sunucu daha sonra gelen bağlantılar için bağlantı noktası tanıtıcılarının listesini yoklar. wait() arama kullanılıyor. Bağlantı aldıktan sonra isteği,IPC_HANDLE_POLL_READY uevent_t yapısının event alanı, sunucu bağlantı kurmayı bitirmek ve biraccept() kanal ( herkese açık kullanıcı adı) gelen iletiler için sorgulanabilir.

kabul()

Gelen bağlantıyı kabul eder ve kanalın herkese açık kullanıcı adını belirler.

long accept(uint32_t handle_id, uuid_t *peer_uuid);

[içinde] handle_id: İstemcinin bağlandığı bağlantı noktasını temsil eden tutma yeri

[out] peer_uuid: Toplanacak uuid_t yapısının işaretçisi bağlanan istemci uygulamasının UUID'siyle doldurulur. Google bağlantı güvenli olmayan dünyadan geliyorsa hepsi sıfır olarak ayarlanır

[retval]: Sunucunun oluşturabileceği bir kanalı (negatif değilse) istemciyle mesaj alışverişi (veya başka bir hata kodu ile)

İstemci API'si

Bu bölümde, Client API'deki yöntemler yer almaktadır.

Client API'deki Yöntemler

Connect()

Adı belirtilen bir bağlantı noktasına bağlantı başlatır.

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

[içinde] path: Bir Trusty uygulaması tarafından yayınlanan bağlantı noktasının adı

[içinde] flags: Ek, isteğe bağlı davranışı belirtir

[retval]: Mesajları sunucu; negatifse hata

flags belirtilmezse (flags parametresi) 0 olarak ayarlanırsa connect() çağrısı yapıldığında eşzamanlı bir bağlantı başlatılır hemen aynı bağlantı noktasına bağlantı noktası yoksa bir hata döndürür ve sunucu aksi takdirde bağlantı kabul eder.

Bu davranış, iki değerin bir kombinasyonunu belirterek değiştirilebilir: aşağıda açıklanmıştır:

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

IPC_CONNECT_WAIT_FOR_PORT - connect() öğesini zorlar belirtilen bağlantı noktası yürütme sırasında hemen mevcut değilse bekleme çağrısı, yardımcı olur.

IPC_CONNECT_ASYNC: Ayarlanırsa eşzamansız bağlantı başlatır. uygulamanın herkese açık kullanıcı adı için wait() IPC_HANDLE_POLL_READY tarafından belirtilen bir bağlantı tamamlama etkinliği başlamadan önce uevent_t yapısının etkinlik alanında ayarlanmış bit normal çalışma.

Mesajlaşma API'si

Messaging API çağrıları, önceden oluşturulmuş bağlantı (kanal). Messaging API çağrıları, aynı şekilde kullanır.

Bir müşteri, connect() vererek kanalın herkese açık kullanıcı adını alır çağrısı ile sunucu tarafından accept() çağrısından kanalın herkese açık kullanıcı adı alınırsa 'ne başvurun.

Trusty mesajının yapısı

Aşağıda gösterildiği gibi, Trusty API'nin gönderdiği mesajlar minimum düzeydedir. yapılandırmanın anlamları üzerinde anlaşmak için sunucuya ve müşteriye gerçek içerik:

/*
 *  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;

Bir mesaj, zaman çizelgesiyle temsil edilen bir veya daha fazla bitişik olmayan tampondan iovec_t yapısı dizisidir. Trusty, dağılım toplama işlemi yapıyor bu blokları okur ve yazar iov dizisi kullanılır. Açıklanabilecek tamponların içeriği iov dizisi tamamen rastgeledir.

Messaging API'deki yöntemler

send_msg()

Belirli bir kanal üzerinden mesaj gönderir.

long send_msg(uint32_t handle, ipc_msg_t *msg);

[içinde] handle: Mesajın gönderileceği kanalı yönlendirme

[in] msg: Mesajı açıklayan ipc_msg_t structure öğesinin işaretçisi

[retval]: Başarıyla gönderilen toplam bayt sayısı; aksi takdirde negatif bir hata oluşur

İstemci (veya sunucu) kanal üzerinden bir mesaj göndermeye çalışıyorsa ve hedef benzerler mesajları sırasında boşluk yoksa kanal bir gönderme engellendi durumu girin (basit bir eşzamanlı iletimlerde bu hiçbir zaman daha karmaşık durumlarda yaşanabilir). ERR_NOT_ENOUGH_BUFFER hata kodu döndürülmesiyle gösterilir. Bu tür bir durumda arayan, akran biraz serbest bırakıncaya kadar beklemelidir alma sırasında bir alana geri dönmek için IPC_HANDLE_POLL_SEND_UNBLOCKED uevent_t yapısının event alanı wait() araması tarafından döndürüldü.

get_msg()

Gelen ileti sırasındaki bir sonraki iletiyle ilgili meta bilgileri alır

bir feed'dir.

long get_msg(uint32_t handle, ipc_msg_info_t *msg_info);

[şurada] handle: Yeni mesajın alınması gereken kanalın herkese açık kullanıcı adı

[out] msg_info: İleti bilgilerinin yapısı aşağıda açıklanmıştır:

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

Her bir iletiye, bekleyen iletiler kümesindeki benzersiz bir kimlik atanır. ve her mesajın toplam uzunluğu girilir. protokolü kullanıyorsanız, aynı anda birden çok bekleyen (açık) ileti olabilir. söz konusu olabilir.

[retval]: NO_ERROR başarılı; aksi takdirde negatif bir hata oluşur

Read_msg()

İletinin içeriğini belirtilen uzaklık.

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

[şurada] handle: Mesajın okunacağı kanalın herkese açık kullanıcı adı

[in] msg_id: Okunacak iletinin kimliği

[içinde] offset: Okumaya başlamak için mesajda ofset

[out] msg: Şu özellikleri açıklayan ipc_msg_t yapısının işaretçisi: gelen iletinin saklanacağı bir tampon grubu veri

[retval]: Şu tarihlerde msg arabelleklerinde depolanan toplam bayt sayısı başarı, aksi takdirde negatif bir hata oluşur

read_msg yöntemi, şu değerden itibaren birden fazla kez çağrılabilir: farklı (her zaman sıralı) ofseti kullanabilirsiniz.

put_msg()

Belirtilen kimliğe sahip bir iletiyi kullanımdan kaldırır.

long put_msg(uint32_t handle, uint32_t msg_id);

[şurada] handle: Mesajın ulaştığı kanalın herkese açık kullanıcı adı

[içinde] msg_id: Kullanımdan kaldırılan iletinin kimliği

[retval]: NO_ERROR başarılı; aksi takdirde negatif bir hata oluşur

Bir ileti kullanımdan kaldırıldıktan sonra ileti içeriğine erişilememesi boşa çıkarılmıştır.

File Descriptor API'sı

File Descriptor API şunları içerir: read(), write(), ve ioctl() arama. Bu çağrıların tümü önceden tanımlanmış (statik) bir dosya grubu üzerinde çalışabilir geleneksel olarak küçük sayılarla temsil edilen tanımlayıcılar. Şu anda uygulaması için, dosya açıklayıcı alanı, IPC herkese açık kullanıcı adından ayrıdır. boşluk oluşturur. Trusty'deki File Descriptor API, geleneksel dosya tanımlayıcı tabanlı API'ye benzer.

Varsayılan olarak, önceden tanımlanmış 3 dosya tanımlayıcısı (standart ve iyi bilinen) vardır:

  • 0 - standart giriş. Standart girişin varsayılan uygulaması: fd no-operatördür (güvenilir uygulamaların etkileşimli konsolu) olduğundan, fd 0 üzerinde ioctl() okuma, yazma veya çağrılma ERR_NOT_SUPPORTED hatası döndürecektir.
  • 1 - standart çıkış. Standart çıkışa yazılan veriler yönlendirilebilir (bağlı olarak LK hata ayıklama düzeyinde) UART'a ve/veya güvenli olmayan SDK'da bulunan bir bellek günlüğüne değişiklik gösterir. Kritik olmayan hata ayıklama günlükleri ve mesajların standart çıkışta gönderilmesi gerekir. read() ve ioctl() yöntemleri işlemsizdir ve ERR_NOT_SUPPORTED hatası verir.
  • 2 - standart hata. Standart hataya yazılan veriler UART'a yönlendirilmelidir Bu işlem platforma ve platforma bağlı olarak güvenli olmayan tarafta kullanılabilen bellek günlüğü veya yapılandırma. Standart iletilere yalnızca kritik iletileri yazmanız önerilir büyük olasılıkla kısıtlanmamıştır. read() ve ioctl() yöntemleri işlemsiz değil ve ERR_NOT_SUPPORTED hatası döndürecek.

Söz konusu dosya tanımlayıcıları kümesi, daha fazla kullanıcı fds (platforma özel uzantılar uygulamak için), dosya tanımlayıcıları ihtiyaçlarının kapsamını genişletiyor dikkatli olunmalıdır. Dosya tanımlayıcılarının genişletilmesi genellikle olduğundan genellikle önerilmez.

File Descriptor API'deki Yöntemler

Read()

Belirtilen dosya tanımlayıcısından count bayta kadar veriyi okumaya çalışır.

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

[in] fd: Okunacak dosya tanımlayıcısı

[out] buf: Verilerin depolanacağı tamponu işaret eder

[şunun içinde] count: Okunacak maksimum bayt sayısı

[retval]: Okunan bayt sayısı döndürülür; aksi takdirde negatif bir hata oluşur

Write()

Belirtilen dosya tanımlayıcısına count bayta kadar veri yazar.

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

[in] fd: Yazılacak dosya tanımlayıcısı

[out] buf: Yazılacak verilerin işaretçisi

[şunun içinde] count: Yazılacak maksimum bayt sayısı

[retval]: Yazılan bayt sayısı; aksi takdirde negatif bir hata oluşur

ioctl()

Belirli bir dosya açıklayıcı için belirli bir ioctl komutunu çağırır.

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

[içinde] fd: ioctl() çağrılacak dosya tanımlayıcısı

[içinde] cmd: ioctl komutu

[in/out] args: ioctl() bağımsız değişkene işaret eden

Çeşitli API

Çeşitli API'deki Yöntemler

gettime()

Geçerli sistem zamanını döndürür (nanosaniye cinsinden).

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

[in] clock_id: Platforma bağımlı; varsayılan için sıfırı geç

[içinde] flags: Ayrılmış, sıfır olmalıdır

[out] time: Geçerli zamanın depolanacağı bir int64_t değerine işaret eder

[retval]: NO_ERROR başarılı; aksi takdirde negatif bir hata oluşur

nanosleep()

Çağrı uygulamasının yürütülmesini belirli bir süre için askıya alır bu sürenin ardından da devam ettirilir.

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

[içinde] clock_id: Ayrılmış, sıfır olmalıdır

[içinde] flags: Ayrılmış, sıfır olmalıdır

[in] sleep_time: Nanosaniye cinsinden uyku süresi

[retval]: NO_ERROR başarılı; aksi takdirde negatif bir hata oluşur

Güvenilir uygulama sunucusu örneği

Aşağıdaki örnek uygulama, yukarıdaki API'lerin kullanımını göstermektedir. Örnek "yankı" oluşturuyor birden fazla gelen bağlantıyı işleyen ve Kaynaktan gelen istemcilerden aldığı tüm mesajları arayana yansıtır. güvenli olmayan taraftan çıkarır.

#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() yöntemi,eşzamansız olarak 10.000 mesaj gönderir "yankı"ya hizmet ve herkese açık kullanıcı adları yanıt.

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

Güvenli olmayan API'ler ve uygulamalar

Güvenli tarafta yayınlanan ve IPC_PORT_ALLOW_NS_CONNECT özelliğine, çekirdek tarafından erişilebilir. ve kullanıcı alanında çalışan güvenli olmayan tarafını belirler.

Güvenli olmayan taraftaki yürütme ortamı (çekirdek ve kullanıcı alanı) bu, güvenli taraftaki yürütme ortamından önemli ölçüde farklıdır. Dolayısıyla, her iki ortam için tek bir kitaplık yerine, her iki ortam için de farklı API'ler oluşturabilirsiniz. Çekirdekteki Client API, güvenilir-ipc çekirdek sürücüsü ve kullanılabilecek bir karakter cihaz düğümünü kaydeder güvenli bağlantıda çalışan hizmetlerle iletişim kurmak için kullanıcı yanı sıra.

Kullanıcı alanı Trusty IPC Client API

Kullanıcı alanı Trusty IPC Client API kitaplığı, fd cihaz düğümü.

Kullanıcı alanı programı bir iletişim oturumu başlatır tipc_connect() numaralı telefonu arayarak belirtilen bir Trusty hizmetiyle bağlantı başlatılıyor. Dahili olarak, tipc_connect() çağrısı, belirtilen cihaz düğümünü açar ve bir dosya tanımlayıcısı alır ve bir TIPC_IOC_CONNECT ioctl() çağırır bir dizeyi işaret eden argp parametresiyle hizmet adını seçin.

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

Ortaya çıkan dosya tanımlayıcısı, yalnızca hizmetle iletişim kurmak için kullanılabilir. örnek olarak verilebilir. Dosya tanımlayıcısı, bağlantı artık gerekli olmadığında tipc_close() aranıyor.

tipc_connect() çağrısıyla elde edilen dosya tanımlayıcısı tipik bir karakter cihaz düğümü gibi davranır; dosya tanımlayıcısı:

  • Gerekirse engellemeyen moda geçilebilir
  • Standart bir write() kullanılarak yazılabilir karşı tarafa mesaj göndermek için ara
  • Anket yapılabilir (poll() veya select() arama kullanılarak) gelen iletilerin normal bir dosya tanımlayıcısı olarak kullanılabilirliği için
  • Gelen mesajları almak için okunabilir

Arayan, belirtilen fd. Tüm veriler yukarıdaki write() çağrısına iletildi güvenilir-ipc sürücüsü tarafından bir mesaja dönüştürülür. Mesaj güvenli tarafa teslim edilir. Buradaki veriler, IPC alt sistemi tarafından Trusty çekirdeğinin çekirdeği doğru hedefe yönlendirilmiş ve bir uygulamaya iletilmiştir. belirli bir kanalda IPC_HANDLE_POLL_MSG etkinliği olarak etkinlik döngüsü herkese açık kullanıcı adı. İlgili özelliğe bağlı olarak, protokolü kullanıyorsanız, Trusty hizmeti bir veya daha fazla yanıt güvenli olmayan tarafa geri teslim edilen ve güvenli olmayan tarafa kullanıcı tarafından alınacak uygun kanal dosyası açıklayıcı mesaj sırası alan uygulaması read() çağrısı.

tipc_connect()

Belirtilen tipc cihaz düğümünü açar ve bir başlatma işlemi belirtilen bir Trusty hizmetine bağlanma.

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

[içinde] dev_name: Açılacak Trusty IPC cihaz düğümünün yolu

[içinde] srv_name: Bağlanılacak yayınlanmış bir Trusty hizmetinin adı

[retval]: Başarıyla ilgili geçerli dosya tanımlayıcısı, aksi takdirde -1 değeri.

tipc_close()

Bir dosya tanımlayıcısı tarafından belirtilen Trusty hizmetiyle olan bağlantıyı kapatır.

int tipc_close(int fd);

[şurada] fd: Dosya tanımlayıcısı daha önce şu kullanıcı tarafından açılmış: tipc_connect() araması

Kernel Trusty IPC İstemci API'si

Çekirdek Trusty IPC Client API, çekirdek sürücüleri için kullanılabilir. Kullanıcı bu API'ye ek olarak Space Trusty IPC API uygulanmış.

Genel olarak, bu API'nin tipik kullanımında, tipc_create_channel() kullanarak bir struct tipc_chan nesnesi işlevini başlatmak için tipc_chan_connect() çağrısını kullanarak güvenli bağlantıda çalışan Trusty IPC hizmetine yanı sıra. Uzak tarafla olan bağlantı Google tarafından tipc_chan_shutdown() aranıyor, ardından şu numara kullanılıyor: Kaynakları temizlemek için tipc_chan_destroy().

Bildirim alındığında (handle_event() geri araması üzerinden) bağlantısı kurulduğunda, arayan, şu:

  • tipc_chan_get_txbuf_timeout() çağrısını kullanarak bir ileti arabelleği alır
  • Bir ileti oluşturur ve
  • tipc_chan_queue_msg() kullanarak iletiyi sıraya alır güvenli tarafta) teslim etmek için kullanılan yöntem, kanal bağlı

Sıraya alma işlemi başarılı olduktan sonra, arayanın mesaj arabelleğini unutması gerekir çünkü ileti arabelleği, tarafından işleme konur (daha sonra diğer iletiler için yeniden kullanmak üzere). Kullanıcı , yalnızca şu başarısız olduğunda tipc_chan_put_txbuf() öğesini çağırması gerekir: sıraya sokabilir veya artık gerekmeyebilir.

Bir API kullanıcısı, bir handle_msg() bildirim geri çağırması ( güvenilir-ipc rx iş sırasının bağlamını ele alalım. içeren bir rx arabelleğine işaretçi sağlar: emin olmanız gerekir.

handle_msg() geri çağırması beklenir uygulanması bir işaretçiyi geçerli bir struct tipc_msg_buf öğesine döndürür. Yerel olarak işleniyorsa gelen ileti arabelleğiyle aynı olabilir ve artık gerekli değil. Alternatif olarak, gelen arabellek sıraya alındıysa tipc_chan_get_rxbuf() çağrısı göz atın. Ayrı bir rx tamponu takip edilmelidir ve nihayetinde bir tipc_chan_put_rxbuf() çağrısıyla yayınlandı. artık ihtiyacınız yok.

Kernel Trusty IPC Client API'deki Yöntemler

tipc_create_channel()

Belirli bir kullanıcı için Trusty IPC kanalının bir örneğini oluşturur ve yapılandırır güvenilir-ipc cihazı.

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

[in] dev: Cihazın bulunduğu güvenilir IP'nin işaretçisi kanal oluşturuldu

[in] ops: struct tipc_chan_ops işaretçisi, arayana özel geri arama dolduruldu

[in] cb_arg: Aktarılacak verilerin işaretçisi tipc_chan_ops geri arama

[retval]: Yeni oluşturulmuş bir örneğine işaret eden struct tipc_chan başarı, Aksi durumda ERR_PTR(err)

Genel olarak, bir çağrıyı yapan, eşzamansız olarak çağrılan iki geri çağırma sağlamalıdır. en iyi uygulamaları gözden geçirmelisiniz.

void (*handle_event)(void *cb_arg, int event) etkinliği çağrılır bir arayanı kanal durumu değişikliği konusunda bilgilendirmek için kullanılır.

[in] cb_arg: tipc_create_channel() araması

[in] event: Aşağıdaki değerlerden biri olabilecek bir etkinlik:

  • TIPC_CHANNEL_CONNECTED - bağlantının başarılı olduğunu gösterir uzak tarafa
  • TIPC_CHANNEL_DISCONNECTED: Uzak tarafın reddettiğini gösterir veya yeni bağlantı isteğinde bulunulduğunda daha önce bağlanmış olan kanalın bağlantısı kesilir
  • TIPC_CHANNEL_SHUTDOWN: Uzak tarafın kapandığını belirtir. tüm bağlantıları kalıcı olarak sonlandırma

struct tipc_msg_buf *(*handle_msg)(void *cb_arg, struct tipc_msg_buf *mb) Yeni bir mesaj olduğuna dair bildirim sağlamak için geri arama çağrılır Belirli bir kanal üzerinden alınan:

  • [in] cb_arg: tipc_create_channel() araması
  • [in] mb: struct tipc_msg_buf işaretçisi gelen bir mesajı açıklıyor
  • [retval]: Geri çağırma uygulamasının bir işaretçiyi Alınan aynı işaretçi olabilecek struct tipc_msg_buf olarak Mesaj yerel olarak işleniyorsa ve işlenmiyorsa mb parametresi (veya tipc_chan_get_rxbuf() çağrısıyla edinilen yeni bir tampon olabilir)

tipc_chan_connect()

Belirtilen Trusty IPC hizmetiyle bağlantı başlatır.

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

[in] chan: Kullanıcının döndürdüğü kanala tipc_create_chan() araması

[in] port: İmleci bağlanılacak hizmet adı

[retval]: Başarıda 0, aksi takdirde olumsuz bir hata vardır

Bir bağlantı kurulduğunda, arayan kişiye bir handle_event geri arama.

tipc_chan_shutdown()

Daha önce başlatılan Trusty IPC hizmetiyle olan bağlantıyı sonlandırır tipc_chan_connect() aramasıyla.

int tipc_chan_shutdown(struct tipc_chan *chan);

[içinde] chan: Şu kullanıcı tarafından döndürülen kanalın işaretçisi: tipc_create_chan() araması

tipc_chan_INSTALL()

Belirtilen bir Trusty IPC kanalını kaldırır.

void tipc_chan_destroy(struct tipc_chan *chan);

[in] chan: Kullanıcının döndürdüğü kanala tipc_create_chan() araması

tipc_chan_get_txbuf_timeout()

Belirli bir üzerinden veri göndermek için kullanılabilecek bir mesaj arabelleği alır yardımcı olur. Arabellek hemen kullanılamıyorsa arayan kişi engellenebilir belirtilen zaman aşımı süresi için (milisaniye cinsinden).

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

[içinde] chan: İmleci, iletinin sıraya alınacağı kanala yönlendirir

[in] chan: Şu saate kadar beklemek için maksimum zaman aşımı tx arabelleği kullanılabilir hale gelir

[retval]: Başarıda geçerli bir mesaj tamponu Hata durumunda ERR_PTR(err)

tipc_chan_kuyruğu_msg()

Bir iletiyi, belirtilen iletinin üzerinden gönderilecek şekilde sıraya alır Güvenilir IPC kanalları.

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

[içinde] chan: İletinin sıraya alınacağı kanalın işaretçisi

[in] mb: İşaretçiyi sıraya alacak iletinin üzerine getirin (tipc_chan_get_txbuf_timeout() çağrısı ile elde edilir)

[retval]: Başarıda 0, aksi takdirde olumsuz bir hata vardır

tipc_chan_put_txbuf()

Belirtilen Tx mesaj arabelleğini serbest bırakır daha önce bir tipc_chan_get_txbuf_timeout() aramasıyla edinilmiş bilgilerdir.

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

[in] chan: İşaretçi olan kanal bu mesaj arabelleği yine

[içinde] mb: Serbest bırakmak için mesaj arabelleğinin işaretçisi

[retval]: Yok

tipc_chan_get_rxbuf()

belirtilen kanal.

struct tipc_msg_buf *tipc_chan_get_rxbuf(struct tipc_chan *chan);

[şurada] chan: Bu mesaj arabelleğinin ait olduğu kanalın işaretçisi

[retval]: Başarılı olduğunda geçerli bir mesaj arabelleği, hata durumunda ERR_PTR(err)

tipc_chan_put_rxbuf()

Bir tipc_chan_get_rxbuf() arama.

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

[şurada] chan: Bu mesaj arabelleğinin ait olduğu kanalın işaretçisi

[içinde] mb: Serbest bırakmak için ileti arabelleğinin işaretçisi

[retval]: Yok