この節では、RPC メッセージプロトコルを、XDR データ記述言語を使用して説明します。メッセージは、例 B-1で示すようにトップダウン形式で定義します。
enum msg_type {
CALL = 0,
REPLY = 1
};
/*
* 呼び出しメッセージに対する応答には、2 つの形式があります。メッセージが
* 受け入れられた場合と拒絶された場合のどちらかです。
*/
enum reply_stat {
MSG_ACCEPTED = 0,
MSG_DENIED = 1
};
/*
* 呼び出しメッセージが受け入れられた場合、遠隔手続きを呼び出したときの
* ステータスが次のように示されます。
*/
enum accept_stat {
SUCCESS = 0, /* RPC が正常に実行された */
PROG_UNAVAIL = 1, /* 遠隔サービスにエクスポートされたプログラムがない */
PROG_MISMATCH = 2, /* 遠隔サービスがそのバージョン番号をサポートしていない */
PROC_UNAVAIL = 3, /* プログラムがその手続きをサポートしていない */
GARBAGE_ARGS = 4 /* 手続きが引数を復号化できない */
};
/*
* 呼び出しメッセージが拒絶された原因
*/
enum reject_stat {
RPC_MISMATCH = 0, /* RPC のバージョン番号が 2 でない */
AUTH_ERROR = 1 /* 遠隔サービスで呼び出し側の認証エラー */
};
/*
* 認証が失敗した原因
*/
enum auth_stat {
AUTH_BADCRED = 1, /* 認証エラーの原因 */
AUTH_REJECTEDCRED = 2, /* クライアントは新規セッションが必要 */
AUTH_BADVERF = 3, /* ベリファイアのエラー */
AUTH_REJECTEDVERF = 4, /* ベリファイアの失効または再使用 */
AUTH_TOOWEAK = 5 /* セキュリティによる拒絶 */
};
/*
* RPC メッセージ:
* どのメッセージもトランザクション ID xid と
* それに続く識別型共用体 (アームは 2 つ) で始まります。
* 共用体の要素識別子は msg_type で、2 つのメッセージタイプのうち
* どちらのタイプのメッセージかを示します。REPLY メッセージの xid は、
* 対応する CALL メッセージの xid に一致します。注意: xid フィールドは、
* クライアント側で応答メッセージがどの呼び出しメッセージに対応するかを
* 調べるか、サーバー側で再送信かどうかを調べるためにだけ使用できます。
* サービス側では xid をなんらかのシーケンス番号として使用することはできません。
*/
struct rpc_msg {
unsigned int xid;
union switch (msg_type mtype) {
case CALL:
call_body cbody;
case REPLY:
reply_body rbody;
} body;
};
/*
* RPC 要求呼び出しの本体:
* RPC プロトコル仕様のバージョン 2 では、rpcvers は 2 でなければ
* なりません。prog、vers、proc の各フィールドにはそれぞれ、
* 遠隔プログラム、そのバージョン番号、遠隔プログラムに入っている
* 呼び出し対象の手続きを指定します。これらのフィールドに続いて
* 2 つの認証パラメータ cred (認証を証明するもの) と verf (認証を検証する
* もの : 認証ベリファイア) があります。この 2 つの認証パラメータの後には、
* 遠隔手続きへの引数が入りますが、それらは特定プログラムの
* プロトコルで指定されます。
*/
struct call_body {
unsigned int rpcvers; /* この値は 2 でなければならない */
unsigned int prog;
unsigned int vers;
unsigned int proc;
opaque_auth cred;
opaque_auth verf;
/* ここからは手続きに固有の引数 */
};
/*
* RPC 要求への応答の本体:
* 呼び出しメッセージは受け入れられたか拒絶されたかのどちらか
*/
union reply_body switch (reply_stat stat) {
case MSG_ACCEPTED:
accepted_reply areply;
case MSG_DENIED:
rejected_reply rreply;
} reply;
/*
* RPC 要求がサーバーに受け入れられた場合の応答: 要求が受け入れられた場合も
* エラーはあり得ます。最初のフィールドはサーバーが呼び出し側に自分自身を
* 証明する認証ベリファイアです。次のフィールドは共用体で、
* 要素識別子は列挙型 accept_stat です。この共用体の SUCCESS アームは
* プロトコルによって異なります。
* PROG_UNAVAIL、PROC_UNAVAIL、GARBAGE_ARGP の
* アームは void です。PROG_MISMATCH アームにはサーバーが
* サポートしている遠隔プログラムのバージョン番号の
* 最大値と最小値が入ります。
*/
struct accepted_reply {
opaque_auth verf;
union switch (accept_stat stat) {
case SUCCESS:
opaque results[0];
/* ここからは手続き固有の戻り値 */
case PROG_MISMATCH:
struct {
unsigned int low;
unsigned int high;
} mismatch_info;
default:
/*
* PROG_UNAVAIL、PROC_UNAVAIL、GARBAGE_ARGS
* の場合は void
*/
void;
} reply_data;
};
/*
* RPC 要求がサーバーに拒絶された場合の応答:
* 要求が拒絶されるのには 2 つの原因があります。互換性のあるバージョンの
* RPC プロトコルがサーバーで実行されていない場合 (RPC_MISMATCH) と、
* サーバーが呼び出し側の認証を拒否した場合 (AUTH_ERROR) です。
* RPC バージョンの不一致の場合は、サーバーがサポートしている RPC バージョンの
* 最大値と最小値が返されます。認証拒否の場合は、
* 異常終了ステータスが返されます。
*/
union rejected_reply switch (reject_stat stat) {
case RPC_MISMATCH:
struct {
unsigned int low;
unsigned int high;
} mismatch_info;
case AUTH_ERROR:
auth_stat stat;
};
|