aboutsummaryrefslogtreecommitdiffstats
path: root/lib/orber/doc/src/ch_interceptors.xml
diff options
context:
space:
mode:
Diffstat (limited to 'lib/orber/doc/src/ch_interceptors.xml')
-rw-r--r--lib/orber/doc/src/ch_interceptors.xml278
1 files changed, 278 insertions, 0 deletions
diff --git a/lib/orber/doc/src/ch_interceptors.xml b/lib/orber/doc/src/ch_interceptors.xml
new file mode 100644
index 0000000000..27b254c4bf
--- /dev/null
+++ b/lib/orber/doc/src/ch_interceptors.xml
@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding="latin1" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2001</year><year>2009</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ The contents of this file are subject to the Erlang Public License,
+ Version 1.1, (the "License"); you may not use this file except in
+ compliance with the License. You should have received a copy of the
+ Erlang Public License along with this software. If not, it can be
+ retrieved online at http://www.erlang.org/.
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ the License for the specific language governing rights and limitations
+ under the License.
+
+ </legalnotice>
+
+ <title>Orber Interceptors</title>
+ <prepared>Nick</prepared>
+ <docno></docno>
+ <date>2001-08-16</date>
+ <rev></rev>
+ <file>ch_interceptors.xml</file>
+ </header>
+
+ <section>
+ <title>Using Interceptors</title>
+ <p>For Inter-ORB communication, e.g., via <c>IIOP</c>, it is possible
+ to intercept requests and replies. To be able to use <c>Interceptors</c>
+ Orber the configuration parameter <c>interceptors</c> must be defined.</p>
+
+ <section>
+ <title>Configure Orber to Use Interceptors</title>
+ <p>The configuration parameter <c>interceptors</c> must be defined, e.g.,
+ as command line option:</p>
+ <code type="none">
+erl -orber interceptors "{native, ['myInterceptor']}"
+ </code>
+ <p>It is possible to use more than one interceptor; simply add them to the
+ list and they will be invoked in the same order as they appear in the list.</p>
+ <p>One can also active and deactivate an interceptor during
+ run-time, but this will only affect currently existing connections.
+ For more information, consult Orber's Reference Manual regarding the
+ operations <c>orber:activate_audit_trail/0/1</c> and
+ <c>orber:activate_audit_trail/0/1.</c></p>
+ </section>
+
+ <section>
+ <title>Creating Interceptors</title>
+ <p>Each supplied interceptor <em>must</em> export the following functions:</p>
+ <list type="bulleted">
+ <item><em>new_out_connection/3/5</em> - one of these operations is called when
+ a client application calls an object residing on remote ORB.
+ If an interceptor exports both versions, arity 3 and 5, which
+ operation that will be invoked is Orber internal.</item>
+ <item><em>new_in_connection/3/5</em> - one of these operations is invoked
+ when a client side ORB tries to set up a connection to the target ORB.
+ If an interceptor exports both versions, arity 3 and 5, which
+ operation that will be invoked is Orber internal.</item>
+ <item><em>out_request/6</em> - supplies all request data on the client side
+ ORB.</item>
+ <item><em>out_request_encoded/6</em> - similar to <c>out_request</c>
+ but the request body is encode.</item>
+ <item><em>in_request_encoded/6</em> - after a new request arrives at the
+ target ORB the request data is passed to the interceptor in
+ encoded format.</item>
+ <item><em>in_request/6</em> - prior to invoking the operation on the
+ target object, the interceptor <c>in_request</c> is called.</item>
+ <item><em>out_reply/6</em> - after the target object replied the
+ <c>out_reply</c> operation is called with the result of the object
+ invocation.</item>
+ <item><em>out_reply_encoded/6</em> - before sending a reply back to the
+ client side ORB this operation is called with the result in
+ encoded format.</item>
+ <item><em>in_reply_encoded/6</em> - after the client side ORB receives
+ a reply this function is called with the reply in encoded
+ format.</item>
+ <item><em>in_reply/6</em> - before delivering the reply to the client
+ this operation is invoked.</item>
+ <item><em>closed_in_connection/1</em> - when a connection is terminated
+ on the client side this function is called.</item>
+ <item><em>closed_out_connection/1</em> - if an outgoing connection is
+ terminated this operation will be invoked.</item>
+ </list>
+ <p>The operations <c>new_out_connection</c>, <c>new_in_connection</c>,
+ <c>closed_in_connection</c> and <c>closed_out_connection</c> operations
+ are only invoked <em>once</em> per connection. The remaining operations
+ are called, as shown below, for every Request/Reply to/from remote
+ CORBA Objects.</p>
+ <marker id="interceptor_operations"></marker>
+ <image file="interceptor_operations.gif">
+ <icaption>
+The Invocation Order of Interceptor Functions.</icaption>
+ </image>
+ </section>
+ </section>
+
+ <section>
+ <title>Interceptor Example</title>
+ <p>Assume we want to create a simple access service which purpose is to:</p>
+ <list type="bulleted">
+ <item>Only allow incoming request from ORB's residing on a certain set of
+ nodes.</item>
+ <item>Restrict the objects any client may invoke operations on.</item>
+ <item>Only allow outgoing requests to call a limited set of external
+ ORB's.</item>
+ <item>Add a checksum to each binary request/reply body.</item>
+ </list>
+ <p>To restricts the access we use a <c>protected</c> and <c>named</c> ets-table
+ holding all information. How the ets-table is initiated and maintained
+ is implementation specific, but it contain
+ <c>{Node, ObjectTable, ChecksumModule}</c> where <c>Node</c> is used as
+ ets-key, <c>ObjectTable</c> is a reference to another ets-table in which
+ we store which objects the clients are allowed to invoke operations on
+ and <c>ChecksumModule</c> determines which module we should use to handle
+ the checksums. </p>
+ <code type="none">
+new_in_connection(Arg, Host, Port) ->
+ %% Since we only use one interceptor we do not care about the
+ %% input Arg since it is set do undefined by Orber.
+ case ets:lookup(in_access_table, Host) of
+ [] ->
+ %% We may want to log the Host/Port to see if someone tried
+ %% to hack in to our system.
+ exit("Access not granted");
+ [{Host, ObjTable, ChecksumModule}] ->
+ {ObjTable, ChecksumModule}
+ end.
+ </code>
+ <p>The returned tuple, i.e., {ObjTable, ChecksumModule}, will be passed
+ as the first argument whenever invoking one of the interceptor functions.
+ Unless the connection attempt did not fail we are now ready for receiving
+ requests from the client side ORB.</p>
+ <p>When a new request comes in the first interceptor function to be invoked is
+ <c>in_request_encoded</c>. We will remove the checksum from the coded
+ request body in the following way:</p>
+ <code type="none">
+in_request_encoded({ObjTable, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
+ NewBin = ChecksumModule:remove_checksum(Bin),
+ {NewBin, Extra}.
+ </code>
+ <p>If the checksum check fails the <c>ChecksumModule</c> should invoke exit/1.
+ But if the check succeeded we are now ready to check if the client-ORB
+ objects are allowed to invoke operations on the target object. Please note,
+ it is possible to run both checks in <c>in_request_encoded</c>. Please
+ note, the checksum calculation must be relatively fast to ensure a
+ good throughput.</p>
+ <p>If we want to we can restrict any clients to only use a subset of operations
+ exported by a server:</p>
+ <code type="none">
+in_request({ObjTable, ChecksumModule}, ObjKey, Ctx, Op, Params, Extra) ->
+ case ets:lookup(ObjTable, {ObjKey, Op}) of
+ [] ->
+ exit("Client tried to invoke illegal operation");
+ [SomeData] ->
+ {Params, Extra}
+ end.
+ </code>
+ <p>At this point Orber are now ready to invoke the operation on the target
+ object. Since we do not care about what the reply is the <c>out_reply</c>
+ function do nothing, i.e.:</p>
+ <code type="none">
+out_reply(_, _, _, _, Reply, Extra) ->
+ {Reply, Extra}.
+ </code>
+ <p>If the client side ORB expects a checksum to be added to the reply we
+ add it by using:</p>
+ <code type="none">
+out_reply_encoded({ObjTable, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
+ NewBin = ChecksumModule:add_checksum(Bin),
+ {NewBin, Extra}.
+ </code>
+ <warning>
+ <p>If we manipulate the binary as above the behavior <em>must</em>
+ be <c>Bin == remove_checksum(add_checksum(Bin))</c>.</p>
+ </warning>
+ <p>For outgoing requests the principle is the same. Hence, it is not further
+ described here. The complete interceptor module would look like:</p>
+ <code type="none">
+
+-module(myInterceptor).
+
+%% Interceptor functions.
+-export([new_out_connection/3,
+\011 new_in_connection/3,
+\011 closed_in_connection/1,
+\011 closed_out_connection/1,
+\011 in_request_encoded/6,
+\011 in_reply_encoded/6,
+\011 out_reply_encoded/6,
+\011 out_request_encoded/6,
+\011 in_request/6,
+\011 in_reply/6,
+\011 out_reply/6,
+\011 out_request/6]).
+
+new_in_connection(Arg, Host, Port) ->
+ %% Since we only use one interceptor we do not care about the
+ %% input Arg since it is set do undefined by Orber.
+ case ets:lookup(in_access_table, Host) of
+ [] ->
+ %% We may want to log the Host/Port to see if someone tried
+ %% to hack in to our system.
+ exit("Access not granted");
+ [{Host, ObjTable, ChecksumModule}] ->
+ {ObjTable, ChecksumModule}
+ end.
+
+new_out_connection(Arg, Host, Port) ->
+ case ets:lookup(out_access_table, Host) of
+ [] ->
+ exit("Access not granted");
+ [{Host, ObjTable, ChecksumModule}] ->
+ {ObjTable, ChecksumModule}
+ end.
+
+in_request_encoded({_, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
+ NewBin = ChecksumModule:remove_checksum(Bin),
+ {NewBin, Extra}.
+
+in_request({ObjTable, _}, ObjKey, Ctx, Op, Params, Extra) ->
+ case ets:lookup(ObjTable, {ObjKey, Op}) of
+ [] ->
+ exit("Client tried to invoke illegal operation");
+ [SomeData] ->
+ {Params, Extra}
+ end.
+
+out_reply(_, _, _, _, Reply, Extra) ->
+ {Reply, Extra}.
+
+out_reply_encoded({_, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
+ NewBin = ChecksumModule:add_checksum(Bin),
+ {NewBin, Extra}.
+
+out_request({ObjTable, _}, ObjKey, Ctx, Op, Params, Extra) ->
+ case ets:lookup(ObjTable, {ObjKey, Op}) of
+ [] ->
+ exit("Client tried to invoke illegal operation");
+ [SomeData] ->
+ {Params, Extra}
+ end.
+
+out_request_encoded({_, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
+ NewBin = ChecksumModule:add_checksum(Bin),
+ {NewBin, Extra}.
+
+in_reply_encoded({_, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
+ NewBin = ChecksumModule:remove_checksum(Bin),
+ {NewBin, Extra}.
+
+in_reply(_, _, _, _, Reply, Extra) ->
+ {Reply, Extra}.
+
+closed_in_connection(Arg) ->
+ %% Nothing to clean up.
+ Arg.
+
+closed_out_connection(Arg) ->
+ %% Nothing to clean up.
+ Arg.
+ </code>
+ <note>
+ <p>One can also use interceptors for debugging purposes, e.g.,
+ print which objects and operations are invoked with which arguments
+ and the outcome of the operation. In conjunction with the configuration
+ parameter <c>orber_debug_level</c> it is rather easy to find out what
+ went wrong or just to log the traffic. </p>
+ </note>
+ </section>
+</chapter>
+