CORBAオブジェクト間の通信時の振舞
Simple Wiki Based Contents Management System
ソフトウェア関連 >> ライブラリ >> RtORBについて >> RtORBの動作について >> CORBAオブジェクト間の通信時の振舞

CORBAオブジェクト間の通信時の振舞

RtORBにおいて、CORBAオブジェクト間の通信は、下記のようになっている。
  1. リモートCORBAオブジェクトの取得先ず、クライアント側では、リモートCORBAオブジェクトの生成を行う。詳細は、CORBAオブジェクトの取得を参照願います。
  2. リモートCORBAオブジェクトのメソッド呼び出し
上記の手続きでリモートCORBAオブジェクトの参照 C_Obje が生成できたとする。通常、C++等のオブジェクト指向の言語では、メソッド呼び出しは、C_Obj.method1(arg1, arg2)のように行う。しかし、C言語は、基本的にオブジェクト指向の言語ではないため、IDLコンパイラによりクラスメソッドは、
クラス名_メソッド名
の関数にマッピングされることになる。例として、下記のようなinterfaceを考える。
interface Echo {
 string echoString(in string mesg);
 string echoString2(in string mesg, out string res);
 string echoString3(inout string mesg);
};
リモートCORBAオブジェクトの参照は、 Echo という型になり、その変数を myEchoとするとechoStringのメソッド呼び出しは、
Echo_echoString(myEcho, "hello" , &env);
となる。ここでenvは、 CORBA_Environmentという型の構造体である。この関数は、XX-common.c に定義されており、IDLコンパイラにより自動生成され、下記のようになる。
CORBA_string Echo_echoString(CORBA_Echo _obj, const CORBA_char * mesg, CORBA_Environment *ev)
{
  CORBA_string _ORBIT_retval;
  void * _args[1];
  _args[0] = (void *)&mesg;
  invokeMethod (_obj, &Echo__imp.methods[0], (void **)&_ORBIT_retval, _args, ev );
  return _ORBIT_retval;
}

このようにクライアント側では、invokeMethod関数が実行される。

【invokeMethod関数】

この関数は、リモートCORBAオブジェクトに対するMethodの呼び出しを行う。rtorb.cに記述されている。この関数では、先ず、CORBA_ORB_find_object関数にて、リモートCORBAオブジェクトがThe_RootPOAに含まれていないかどうかをチェックする。もし、The_RootPOAのオブジェクトマップになければ、invokeMethod_via_GIOP関数を呼び出し、GIOP経由(TCPソケット経由)でメソッドの実行を呼び出す。リモートCORBAオブジェクトがThe_RootPOAに含まれていた場合には、実装の関数を検索し、関数コールを行う。すなわち、同一プロセス内のCORBAオブジェクトに対するメソッド呼び出しは、単なる関数呼び出しになる。

【invokeMethod_via_GIOP関数】

リモートCORBAオブジェクトが外部プロセスに存在している場合に、この関数が呼ばれる。rtorb.cに記述されている。この関数の処理は、下記の通りである。
  1. h = make_client_connection(obj->connection); 参照情報に基づきIIOPの通信用TCPソケットを生成する。
  2. obj->_url[0].location_flagsをチェックして、以前呼び出しを行ったかどうかをチェックする。もし、最初に呼び出しを行う場合には、confirmLocation関数を使って、リモートCORBAオブジェクトが存在するかどうかを確認する。確認できたら、obj->_url[0].location_flagsを1にセットする。
  3. 通信用のバッファarg_buf、req_buf、bufを確保する。arg_bufは、引数のシリアライズ化、req_bufは、GIOPメッセージのシリアライズ化(arg_bufを含む)、bufはメソッドリクエストの結果を保持するためのものである。
  4. len = Marshal_Args(arg_buf, args, method->in_argc, method->in_argv); 引数のシリアライズ化
  5. len = createRequest(req_buf, 1, obj->_url[0].object_key, obj->_url[0].object_key_len,method->name, strlen(method->name)+1, arg_buf, len, 2 ); 引数を含め、リモートCORBAオブジェクトへ送るGIOPメッセージを生成
  6. GIOP_ConnectionHandler_send関数で、リモートCORBAオブジェクトへGIOPメッセージを送信
  7. receiveMessage関数で、リモートメソッドの実行結果を受信。戻り値が 0より小さければ、EXCEPTIONの発生なので、歯バッファをクリアして戻る。
  8. header.flagsをチェックして、エンディアンを確認しメッセージサイズを取得
  9. actionReply関数を呼び出す。(bufからCORBA_Sequence_Octet型のreply_bodyを抽出?)
  10. env->_majorをチェックして、正常終了であれば、deMarshal_Arguments関数を実行して、返り値等を復号する。
  11. CORBA_USER_EXCEPTIONが発生していれば、メッセージを出力する
  12. 最後に、reply_body、h、arg_buf、req_buf、bufをクリアして戻る

【make_client_connection関数】

IIOPの通信のためのTCPソケットを生成する。connection.cに記述されている。GIOP_Connection *conn を引数として、conn->sock が0であった場合に、make_client_socket_port関数でTCP socket を生成する。その後、GIOP_ConnectionHandler を生成して、それを返す。この時、GIOP_ConnectionHandlerをmallocしているので、開放を忘れないようにする。本来は、GIOP_ConnectionHandlerを生成する必要はないと思う。

【confirmLocation関数】

リモートCORBAオブジェクトの場所を確認する。giop.cに記述されている。
(GIOP_ConnectionHandler *h, CORBA_URL *ior)を引数として渡している。この関数の処理は下記の手順。
  1. GIOPメッセージ用のバッファbufを生成し、正常に生成されていれば、それをクリアする。
  2. createLocateRequest関数でiorのCORBAオブジェクトに対するLocateRequestを生成する。
  3. GIOP_ConnectionHandler_send関数で、LocateRequestを送信する。
  4. bufを受信に使うためにメモリ内容をクリアする。
  5. receiveMessage関数でCORBAオブジェクトからの返信を待つ。受信エラーがあればエラーメッセージを出力し−1を返す。
  6. new_CORBA_Sequence_Octet関数で、GIOPメッセージ処理用のCORBA_Sequence_Octetを生成する。
  7. newLocateReplyHeader関数でLocateReplyのヘッダー処理用メモリ領域locate_reply_headerを確保する。
  8. deMarshalLocateReply関数で、LocateReplyを処理する。
  9. locate_reply_header->locate_statusを返り値resultに設定する。
  10. delete_CORBA_Sequence_Octet関数でGIOPメッセージ処理用のCORBA_Sequence_Octetを解放する。
  11. RtORB_free関数で、locate_reply_headerと bufを解放する。
  12. resultを返り値として、終了。

【Marshal_Args関数】

リモート呼び出しの引数をシリアライズ化(marshaling)する。rtorb.cに記述されている。この関数は、(octet *buf, void **argv, int i_args, CORBA_IArg *i_argv)を引数として、CORBA_IArgの内容にしたがってargvをmarshal_by_typecode関数を使ってシリアライズ化し、bufに保存する。CORBA_IArgは、下記のように定義されている。
    typedef struct CORBA_IArg {
      CORBA_TypeCode tc;
      unsigned char  io;
      char *name;
    }CORBA_IArg;
シリアライズ化される引数、すなわちGIOPメッセージで送信される引数は、CORBA_I_ARG_IN、CORBA_I_ARG_INOUTのみである。

【createRequest関数】

リモート呼び出しのためのGIOPメッセージを生成する。giop.cに記述されている。この関数での処理は下記の通り。
  1. newRequestHeader関数で、GIOP_RequestHeaderの領域を確保し、初期化する。
  2. GIOP_Create_MessageHeader関数で、GIOP_MessageHeaderを生成する。このとき、シリアライズ化用のbyte_orderとGIOPのメッセージのマイナーバージョン versionを設定する。
  3. ersionにしたがって、GIOP_RequestHeaderを設定する。
  4. GIOP_RequestHeaderは、versionの値によって下記のような処理を行う。
    • version < 2の時:
      • header->_1_0.request_id に next_request_id関数で、request_idを設定
      • header->_1_0.response_expected に 引数で与えラているresponseをセット。
      • set_CORBA_Sequence_Octet関数で、header->_1_0.object_keyに引数で与えられているobject_keyをセット。
      • set_CORBA_Sequence_Octet関数で、header->_1_0.operationに引数で与えられているoperationをセット。
    • version >= 2の時:
      • header->_1_2.request_id に next_request_id関数で、request_idを設定
      • header->_1_2.response_flangs に 引数で与えられているresponseをセット。
      • header->_1_2.target_type に GIOP_KeyAddr(=0)をセット。
      • set_CORBA_Sequence_Octet関数で、header->_1_2.target.object_keyに引数で与えられているobject_keyをセット。
      • set_CORBA_Sequence_Octet関数で、header->_1_2.operationに引数で与えられているoperationをセット。
  5. MarshalRequest関数でheader、argsをシリアライズ化し、bufに格納する。返り値は、bufのサイズでありlenにセット。
  6. MsgHeader->message_sizeに  len - SIZEOF_GIOP_HEADER をセット。(GIOPのメセージボディのサイズ)
  7. memcpy関数で、MsgHeaderをbufにコピーする。
  8. deleteRequestHeader関数でheaderを削除。
  9. RtORB_free関数でMsgHeaderを解放する。

【GIOP_ConnectionHandler_send関数】

リモートCORBAオブジェクトに対して、GIOPメッセージを送信する。giop.cに記述されている。(GIOP_ConnectionHandler *h, char *buf, int32_t len)を引数として、h->type == CONNECTION_TYPE_SOCKETの時にwriteBytes関数で、h->sockに対して、bufを送信する。この時、writeBytesは、GIOPヘッダー部分とメッセージボディの部分の2つに分けて処理している。(本来は、必要ないかもしれませんが)

【receiveMessage関数】

リモートCORBAオブジェクトからの返事を受け取る。(リモートオブジェクトの処理の終了を待つ)giop.cに記述されている。この関数は、(GIOP_ConnectionHandler *h, GIOP_MessageHeader *header, octet *buf, int maxMsg)を引数として、下記のような処理を行う。
  1. GIOP_ConnectionHandler_recv関数で、GIOPヘッダー部分を受信。(bufに保存)
  2. この時、受信エラーが発生すれば、−1を返す。
  3. headerにbufの内容をmemcpy関数でコピーする。
  4. (header->flags & 0x01) == 0 のとき、header->message_size=ntohl(header->message_size)でheader->message_sizeの内容を正しくする。この処理は、RtORBがBigEndianであることが前提になっているので修正の必要がある。本来は、自分のbyte_orderとことなっていれば、データバイト列を逆順にする必要がある。
  5. msgLen = header->message_size として、GIOPメッセージボディのサイズをmsgLenにセット。
  6. msgLen > maxMsg であれば、バッファオーバーフローとなるので、エラーメッセージを出力し、−1を返す。
  7. GIOP_ConnectionHandler_recv関数で残りのメッセージを受信。この時メッセージは、(buf+SIZEOF_GIOP_HEADER)に保存する。GIOP_ConnectionHandler_recvにエラーがあれば、エラーメッセージを出力し、−1を返す。
  8. 正常終了であれば、 header->message_sizeを返り値として終了

【actionReply関数】

GIOPメッセージのReplyHeader解釈して、第1段階の復号処理。rtorb.cに記述されている。(octet *buf, CORBA_Sequence_Octet *body, CORBA_Class_Method *method, CORBA_Environment *env)を引数として下記の処理をする。
  1. memcpy関数で、GIOP_MessageHeader headerにbufからコピー。
  2. newReplyHeader関数でGIOP_ReplyHeader用のデータ領域を確保し、reply_headerにセット。
  3. deMarshalReply関数で、bufからreply_header、bodyを抽出する。
  4. header.version.minor < 2の場合には、reply_status = reply_header->_1_0.reply_status;とする。それ以外の場合には、reply_status = reply_header->_1_2.reply_status; とする。
  5. (header.flags & 0x01) == 0 のときheader->message_size=ntohl(header->message_size)でheader->message_sizeの内容を正しくする。それ以外であれば、 byte_order = 1にセット。この処理は、RtORBがBigEndianであることが前提になっているので修正の必要がある。本来は、自分のbyte_orderとことなっていれば、データバイト列を逆順にする必要がある。
  6. env->_major に reply_statusをセット。
  7. reply_statusの値に応じて下記の処理をする。
    • eply_statusがGIOP_NO_EXCEPTIONの場合:正常終了なので何もしない。
    • reply_statusがGIOP_USER_EXCEPTIONの場合:あとで処理するので何もしない。
    • reply_statusがGIOP_SYSTEM_EXCEPTIONの場合:エラーメッセージを出力。
    • reply_statusがGIOP_LOCATION_FORWARDの場合:GIOPメッセージと"Location forward\n"を出力。
    • reply_statusがGIOP_LOCATION_FORWARD_PERMの場合:GIOPメッセージと"Location forward\n"を出力。
    • reply_statusがGIOP_NEEDS_ADDRESSING_MODEとその他の場合:GIOPメッセージを出力。
  8. deleteReplyHeader関数でreply_headerを削除する。

【deMarshal_Arguments関数】

リモートメソッドの返り値をdeMarshal_Result関数で復号化し、必要があれば、引数の復号を実行する。第2段階の復号処理を実施する。giop-marshal.cに記述されている。この関数は、(void **retval, void **args, octet *buf, CORBA_Class_Method *method, int order) を引数として、次の処理を行う。
  1. retvalがNULLでない場合には、deMarshal_Result関数でリモートメソッド呼び出しの結果を復号化する。
  2. リモートメソッドの引数でCORBA_I_ARG_OUTまたは、CORBA_I_ARG_INOUTのものがあれば、GIOPメッセージに含まれているので、それをdemarshal_by_typecode関数で復号化する。

【deMarshal_Result関数】

リモートメソッドの返り値の型に応じてdemarshal_by_typecode関数を用いて複合化する。giop-marshal.cに記述されている。この関数は、(void **retval, CORBA_TypeCode tc, octet *buf, int *size, int order)を引数として次の処理を行う。
  1. SKIP_ALIAS(tc)マクロ関数で tc->kindがtk_aliasであれば、そのメンバに置き換える
  2. tc->kindを調査して次の処理をする。
  3. tc->kindがtk_unionの場合:CORBA_TypeCode_is_fixed_size(tc)が真であれば、demarshal_by_typecode関数で復号化する。この部分には、バグがあるが、現時点でunionは原則使わないので、問題が出ていない。書きなおす必要がある。
  4. tc->kindがtk_struct、tk_sequence、tk_anyの場合:RtORB_typecode_alloc関数で結果を入れるメモリ領域valを確保して、demarshal_by_typecode関数で復号化する。そして、 *retval = val でretvalをセットする。
  5. その他の場合:demarshal_by_typecode関数で結果を復号化する。この関数は、invokeServant関数の修正に伴い、再度変更する必要がある。もしかするとこの関数自体が必要ないかもしれませんが、その時は、invokeServantの修正、deMarshal_Arguments関数の修正も行う必要がある。【見直しが必要】

リモートCORBAオブジェクトのメソッドの実行処理

リモートCORBAオブジェクトのメッソド呼び出し実行時に、サーバー側の実行処理について述べる。「ORBの実行」のところでも述べたように、サーバー側では、CORBA_ORB_run関数で、socket記述子からのデータ送受信処理のための無限ループが実行されている。低レベルのイベント処理に関しては、そちらを参照していただきたい。
ここでは、リモートCORBAオブジェクトのメッソド呼び出し実行が起こった処理について述べる。
  1. まず、リモートCORBAオブジェクトのメッソド呼び出しがクライアント側で起こった場合には、サーバー側に接続要求が発生する。それに応じて、通信用のsocket記述子がaccept_connection関数で生成され、通信用socketが確立する。
  2. 次に、クライアントからのGIOPメッセージは、PortableServer_enqueue_request関数によりpoaのrequest queueに入れられる。
  3. すべてのクライアントからのGIOPメッセージの受信終了後、PortableServer_execute_request関数により、リモートCORBAオブジェクトのメソッドが順次実行される。

【PortableServer_enqueue_request関数】

GIOPのリクエストをRootPOAのrequest queueに入れる。PortableServer_POA_activate内でset_SockProfile(poa->_server->sock, SOCK_SERVER, NULL, NULL, PortableServer_enqueue_request);として、socketのenqueueコマンドとして登録されている。
  1. GIOP_ConnectionHandler_get_arg関数でPOAを取得。(The_RootPOAのみを使用する場合には不必要)
  2. MutexLock(Mutexをとる。Thread対応版のみ)
  3. poa->requests = (PtrList *)GIOP_enqueue_request(h, poa->requests); でGIOPメッセージをキューに入れる
  4. MuteUnLock(Mutexを解放する。Thread対応版のみ)
  5. poa->requests == -1 (メッセージ読み込み失敗)ならば、 -1 を返し、そうでなければ 1を返す。

【GIOP_enqueue_request関数】

GIOPのリクエストをrequst queue に追加する。PortableServer_enqueue_request から呼ばれる
  1. メッセージを読み込むためのバッファ(buf)を確保
  2. receiveMessage をコールし、メッセージを読み込む
  3. Requestのバッファを確保し、ConnectionHandler用の領域確保、GIOPメッセージの領域確保
  4. RequestにConnectionHandlerとGIOPメッセージをコピー
  5. Request queueにRequestを追加
  6. bufを開放
  7. Request queue を返す。

【PortableServer_execute_request関数】

この関数は、GIOPメセージを処理する。CORBAのリモートメソッドコールのメインの関数である。引数であたえられたポインタは、POAであるはず。また、GIOPのリクエストは、一時的に、poa->requests にストックされ、そのリクエストキューに対して  GIOP_execute_request(poa, poa->requests);を実行する。

【GIOP_execute_request関数】

この関数は、GIOPメセージをすべて処理する。この処理が、CORBAのメインの処理となる。この関数の処理の流れは、下記のとおり。
引数であたえられたPtrList *lstの各要素に対して以下の処理をする。
  1. request = (GIOP_Request_Item)current_request->item; 要素の中身を取る。
  2. header = (GIOP_MessageHeader *)request->buf; 要素の中のGIOPメッセージをGIOPヘッダーheadにキャスト
  3. buf = request->buf; 要素の中のGIOPメッセージをbufにセット
  4. h = request->connh; コネクションハンドラをセット
  5. version = header->minor; GIOPバージョンをセット
  6. header->flags & 0x01 をチェックしてbyte_orderをセットし、必要であれば、メッセージサイズを変換。この部分には、まだ不具合がある。
  7. header->message_typeに応じて下記の処理をする
    • header->message_typeがGIOP_Requestの時:
      • スレッドをサポートしている場合には、該当リクエストのコピーを作ってRunThread(&thr, GIOP_Request_perform_thread, (void *)arg, 1); で新規スレッドに処理を渡す。
      • スレッドをサポートしていない場合には、GIOP_Request_perform(h, (octet *)buf, poa, header, body, &env);を実行
    • header->message_typeがGIOP_Replyの時:これは、リプライ用なのでここでは不要?
      • GIOP_Reply_perform(h, (octet *)buf, poa, header, body, &env);を実行
    • header->message_typeがGIOP_CancelRequestの時:
      • GIOP_CancelRequest_perform(h, (octet *)buf, poa, header, body, &env);を実行
    • header->message_typeがGIOP_LocateRequestの時:
      • GIOP_LocationRequest_perform(h, (octet *)buf, poa, header, body, &env);を実行
    • header->message_typeがGIOP_LocateReplyの時:これは、リプライ用なのでここでは不要?
      • GIOP_LocationReply_perform(h, (octet *)buf, poa, header, body, &env);を実行
    • header->message_typeがGIOP_CloseConnectionの時:
      • 何もしない
    • header->message_typeがGIOP_MessageErrorの時:これは、リプライ用なのでここでは不要?
      • "Message Error occured\n"のメッセージを表示
    • header->message_typeがGIOP_Fragmentの時:これは、未実装なのでMessageErrorを返すべき
      • "FragmentMessage have not implemented.....\n"のメッセージを表示
    • その他:
      • "Invalid message type ([header->message_type])\n"メッセージを表示
  8. current_request->released = 1; 処理が終わったのでreleaseに1をセット
  9. current_request = current_request->next; 次の要素に移動。

【GIOP_Request_perform関数】

この関数は、リモートCORBAオブジェクメソッドのリクエストの処理を行う。この関数は、giop.cに記述されている。この関数は、(GIOP_ConnectionHandler *h, octet *buf, PortableServer_POA poa, GIOP_MessageHeader *header, CORBA_Sequence_Octet *body, CORBA_Environment *env)を引数としてもち、次の処理を行う。
  1. (header->flags & 0x01) != 0 をチェックして、bufのバイトオーダーをセットする。
  2. newRequestHeader関数で、GIOP_RequestHeaderの格納領域request_headerを確保する。
  3. deMarshalRequest関数で、GIOPメッセージヘッダーを復号化する。
  4. 関数を呼び出し、リモートCORBAオブジェクメソッドを実行する。結果は、GIOP_ReplyBody *reply_bodyにセットされる。
  5. reply_Message関数で、処理結果をクライアントに送る
  6. deleteReplyBody関数で、reply_bodyを解放する。
  7. deleteRequestHeader関数で、request_headerを解放する。

【invokeServant関数】

この関数は、リモートCORBAオブジェクメソッドの実体である。この関数は、giop.cに記述されている。この関数は、(PortableServer_POA poa, GIOP_RequestHeader *header, CORBA_Environment *env, octet *arg_buf, int version, int order)を引数としてもち、次の処理を行う。
  1. RtORB_alloc関数で、GIOP_ReplyBodyを格納する領域replyを確保
  2. replyを次のように初期化: reply->status = GIOP_NO_EXCEPTION ; reply->body = NULL;  reply->body_size = 0;
  3. poaがあれば、tbl = poa->object_mapとしてサーバント格納テーブルをセット。poaがNULLであれば、_ORB_->_object_table;を使用する。(次のバージョンでは、poaはThe_RootPOAのみになる)
  4. versionをチェックし、obj_keyとfunctionをセット
  5.  
    • version > 1の場合:
      • obj_key = (char *)header->_1_2.target.object_key._buffer;
      • function = (char *)header->_1_2.operation._buffer;
    • 上記以外の場合:
      • obj_key = (char *)header->_1_0.object_key._buffer;
      • function = (char *)header->_1_0.operation._buffer;
  6. obj_keyがNULLの時、 obj_keyを"NameService" とする。
  7. poa_obj = (RtORB_POA_Object *)getValue(tbl, obj_key); により、obj_keyに対応するRtORB_POA_Objectを取得する。
  8. poa_objがNULL、すなわちobj_keyに対応するRtORB_POA_Objectが見つからない場合には、replyにGIOP_SYSTEM_EXCEPTIONをセットし、"Unknown Object"をreply->exception.exception_id._bufferにセットする。
  9. poa_objを取得できれば、poa_obj->_privateは、PortableServer_ClassInfoであるので、これをキャスティングしてinfoにセット。
  10. また、poa_obj->servantは、PortableServer_ServantBaseにキャストして、PortableServer_ServantBase *sbにセットする。
  11. info->impl_finderには、実装関数を検索するための関数ポインタが代入されているので、
    • call_impl_func = (impl_func_type)(*info->impl_finder)(&sb->_private, function, &m_data, &impl_method );
  12. を実行して、実装関数の関数ポインタを得る。
  13. call_impl_funcがNULLの場合は、下記の処理をする。
    • functionが_is_aの場合には、sb->vepv[0]->is_aを調べて、ここに関数ポインタが設定されているのであれば、引数を復号化して、(sb->vepv[0]->is_a)(&sb->_private, id , env );を実行し実行結果をreplyにセットする。
    • functionが_non_existentの場合には、sb->vepv[0]->non_existentを調べて、ここに関数ポインタが設定されているのであれば、(sb->vepv[0]->non_existent)(&sb->_private, env );を実行し実行結果をreplyにセットする。
    • 上記以外であれば、リモートメソッドは実装されていないのでreplyにGIOP_SYSTEM_EXCEPTIONをセットする。
  14. 次に、deMarshal_Arg関数で、実装関数のに渡す引数を復号化しargvにセットする。
  15. 実行結果を入れるresultにResult_allocで確保した領域のポインタをセットする。
  16. (*call_impl_func)(sb, result, m_data, argv, env, impl_method); を実行し、実装関数をコールする。
  17. env->_majorをチェックすることで、実装関数が正常終了かどうかがわかるために、次の処理をする。
    • env->_majorがCORBA_NO_EXCEPTIONの場合:Marshal_Reply_Arguments(reply, (void**)result, argv, m_data);で結果をシリアライズ化する。
    • env->_majorがCORBA_USER_EXCEPTIONの場合:
      • reply_bufをRtORB_alloc関数で確保し、初期化する。
      • 次に、marshalString関数でenv->_repo_idをシリアライズ化
      • marshal_by_typecode関数でenv->_paramsをシリアライズ化
      • reply->body_sizeにシリアライズ化した情報の長さをセット
      • reply->bodyをRtORB_alloc関数で確保。
      • memcpy関数でreply->bodyにreply_bufをコピー
      • reply->statusにGIOP_USER_EXCEPTIONをセットし、RtORB_free関数でreply_bufを解放する。
    • env->_majorがCORBA_SYSTEM_EXCEPTIONの場合:replyにGIOP_SYSTEM_EXCEPTIONをセットし、必要な情報をセットする。
    • env->_majorが上記以外の場合: これはありえないので、何もしない。
  18. RtORB_Arguments_free関数でargvのポインタの内容をを削除する。
  19. RtORB_Result__free関数でresultを削除する。
  20. RtORB_free関数でargvを削除する。

【GIOP_Reply_perform関数】

この関数は、リモートCORBAオブジェクメソッドからの返事を処理する。この関数は、giop.cに記述されている。この関数は、(GIOP_ConnectionHandler *h, octet *buf, PortableServer_POA poa, GIOP_MessageHeader *header, CORBA_Sequence_Octet *body, CORBA_Environment *env)を引数としてもち、次の処理を行う。この関数は、ほとんどの場合Client側のみの実装で問題ないが、GIOP1.2でのBidirectional IIOPへの対応のために、記載されている。OpenRTM-aistでは使わないので削除予定。
  1. newReplyHeader関数で、GIOP_ReplyHeaderの格納領域reply_headerを確保する。
  2. deMarshalReply関数で、GIOPのメッセージから、GIOP_ReplyHeaderとReplyBodyを復号化する。
  3. header->version.minor < 2の場合:reply_status = reply_header->_1_0.reply_status とし、それ以外であれば、reply_status = reply_header->_1_2.reply_status として、返り値をセットする。
  4. reply_statusの値に応じて下記の処理をする。
    • reply_statusがGIOP_NO_EXCEPTIONの場合:正常終了なので何もしない。
    • reply_statusがGIOP_USER_EXCEPTIONの場合: "User Exception occured!!!\n"を出力。
    • reply_statusがGIOP_SYSTEM_EXCEPTIONの場合:"System Exception occured in GIOP_Reply_perform\n"を出力。
    • reply_statusがGIOP_LOCATION_FORWARDの場合:GIOPメッセージと"Location forward\n"を出力。
    • reply_statusがGIOP_LOCATION_FORWARD_PERMの場合:GIOPメッセージと"Location forward\n"を出力。
    • reply_statusがGIOP_NEEDS_ADDRESSING_MODEとその他の場合:GIOPメッセージを出力。
  5. deleteReplyHeader関数でreply_headerを削除する。この関数の処理は、actionReply関数と非常に似ており、統合する可能性がある。

【GIOP_CancelRequest_perform関数】

この関数は、CancelRequestが起こった場合の処理になる。giop.cに記述されている。この関数は、(GIOP_ConnectionHandler *h, octet *buf, PortableServer_POA poa, GIOP_MessageHeader *header, CORBA_Sequence_Octet *body, CORBA_Environment *env) を引数としてもち、次の処理を行う。
  1. newCancelRequestHeader関数で、GIOP_CancelRequestHeaderの格納領域cancel_request_headerを確保。
  2. deMarshalCancelRequest関数で、cancel_request_headerを復号化。
  3. "Call Cancel %d\n"のメッセージをstderrへ出力
  4. RtORB_free関数で、cancel_request_headerを解放。

【GIOP_LocationRequest_perform関数】

この関数は、リモートCORBAオブジェクトメソッドの実体の一つであるが、リモートCORBAオブジェクトが正しいオブジェクトかどうかの問い合わせに対する処理を行う。giop.cに記述されている。この関数は、(GIOP_ConnectionHandler *h, octet *buf, PortableServer_POA poa, GIOP_MessageHeader *header, CORBA_Sequence_Octet *body, CORBA_Environment *env) を引数としてもち、次の処理を行う。
  1. newLocateRequestHeader関数で、GIOP_LocateRequestHeaderの格納領域locate_request_headerを確保。
  2. deMarshalLocateRequest関数で、locate_request_headerを復号化。
  3. reply_locateMessage関数で、GIOPリクエストを送信。
  4. deleteLocateRequestHeader関数で、locate_request_headerを解放。

【reply_locateMessage関数】

この関数は、GIOP_LocationRequest_perform関数の実体である。giop.cに記述されている。この関数は、(PortableServer_POA poa, GIOP_ConnectionHandler *h, GIOP_LocateRequestHeader *locate_request_header, int version)を引数として、次の処理をする。
  1. RtORB_alloc関数で、返信用のbufを確保し、初期化。
  2. versionを確認して、header.request_id、object_keyをセット
    • version < 2 の場合:
      • header.request_id = locate_request_header->_1_0.request_id;
      • object_key = (char *)locate_request_header->_1_0.object_key._buffer;
    • 上記以外の場合:
      • header.request_id = locate_request_header->_1_2.request_id;
      • object_key = (char *)locate_request_header->_1_2.target.object_key._buffer;
  3. find_object関数で、object_keyのオブジェクトのエントリを確認
  4. MarshalLocateReply関数で、結果をシリアライズ化
  5. GIOP_ConnectionHandler_send関数で結果を送信
  6. RtORB_free関数でbufを削除

【GIOP_LocationReply_perform関数】

GIOP_LocationRequest_performの返事を処理する。giop.cに記述されている。この関数は、(GIOP_ConnectionHandler *h, octet *buf, PortableServer_POA poa, GIOP_MessageHeader *header, CORBA_Sequence_Octet *body, CORBA_Environment *env) を引数としてもち、次の処理を行う。
  1. newLocateReplyHeader関数でGIOP_LocateReplyHeaderの格納領域locate_reply_headerを確保。
  2. deMarshalLocateReply関数で、locate_reply_headerを復号化。
  3. locate_reply_header->locate_statusの値の応じて下記の処理を行う。
    • GIOP_UNKNOWN_OBJECTの場合:"Unknown Object\n"と表示
    • GIOP_OBJECT_HEREの場合:何もしない。
    • GIOP_OBJECT_FORWARD、GIOP_OBJECT_FORWARD_PERMの場合:"Object forward\n"と表示して、GIOPメッセージを表示
    • GIOP_LOC_SYSTEM_EXCEPTIONの場合:"Locate System Exception\n"と表示して、GIOPメッセージを表示
    • GIOP_LOC_NEEDS_ADDRESSING_MODEの場合:"Not Implemented\n"と表示して、GIOPメッセージを表示
    • 上記以外の場合:locate_reply_header->locate_statusを表示
  4. RtORB_free関数で、locate_reply_headerを解放。
この関数は、ほとんどの場合Client側のみの実装で問題ないが、GIOP1.2でのBidirectional IIOPへの対応のために、記載されている。OpenRTM-aistでは使わないので削除予定。