~rdoering/ubuntu/karmic/erlang/fix-535090

« back to all changes in this revision

Viewing changes to lib/orber/doc/src/ch_interceptors.xml

  • Committer: Bazaar Package Importer
  • Author(s): Sergei Golovan
  • Date: 2009-02-15 16:42:52 UTC
  • mfrom: (3.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090215164252-q5x4rcf8a5pbesb1
Tags: 1:12.b.5-dfsg-2
Upload to unstable after lenny is released.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?xml version="1.0" encoding="latin1" ?>
 
2
<!DOCTYPE chapter SYSTEM "chapter.dtd">
 
3
 
 
4
<chapter>
 
5
   <header>
 
6
    <copyright>
 
7
      <year>2001</year>
 
8
      <year>2008</year>
 
9
      <holder>Ericsson AB, All Rights Reserved</holder>
 
10
    </copyright>
 
11
    <legalnotice>
 
12
  The contents of this file are subject to the Erlang Public License,
 
13
  Version 1.1, (the "License"); you may not use this file except in
 
14
  compliance with the License. You should have received a copy of the
 
15
  Erlang Public License along with this software. If not, it can be
 
16
  retrieved online at http://www.erlang.org/.
 
17
 
 
18
  Software distributed under the License is distributed on an "AS IS"
 
19
  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 
20
  the License for the specific language governing rights and limitations
 
21
  under the License.
 
22
 
 
23
  The Initial Developer of the Original Code is Ericsson AB.
 
24
    </legalnotice>
 
25
 
 
26
    <title>Orber Interceptors</title>
 
27
    <prepared>Nick</prepared>
 
28
    <docno></docno>
 
29
    <date>2001-08-16</date>
 
30
    <rev></rev>
 
31
  </header>
 
32
 
 
33
  <section>
 
34
    <title>Using Interceptors</title>
 
35
    <p>For Inter-ORB communication, e.g., via <c>IIOP</c>, it is possible
 
36
      to intercept requests and replies. To be able to use <c>Interceptors</c>
 
37
      Orber the configuration parameter <c>interceptors</c> must be defined.</p>
 
38
 
 
39
    <section>
 
40
      <title>Configure Orber to Use Interceptors</title>
 
41
      <p>The configuration parameter <c>interceptors</c> must be defined, e.g.,
 
42
        as command line option:</p>
 
43
      <code type="none">
 
44
erl -orber interceptors "{native, ['myInterceptor']}"
 
45
      </code>
 
46
      <p>It is possible to use more than one interceptor; simply add them to the
 
47
        list and they will be invoked in the same order as they appear in the list.</p>
 
48
      <p>One can also active and deactivate an interceptor during
 
49
        run-time, but this will only affect currently existing connections. 
 
50
        For more information, consult Orber's Reference Manual regarding the
 
51
        operations <c>orber:activate_audit_trail/0/1</c> and
 
52
        <c>orber:activate_audit_trail/0/1.</c></p>
 
53
    </section>
 
54
 
 
55
    <section>
 
56
      <title>Creating Interceptors</title>
 
57
      <p>Each supplied interceptor <em>must</em> export the following functions:</p>
 
58
      <list type="bulleted">
 
59
        <item><em>new_out_connection/3/5</em> - one of these operations is called when
 
60
         a client application calls an object residing on remote ORB.
 
61
         If an interceptor exports both versions, arity 3 and 5, which
 
62
         operation that will be invoked is Orber internal.</item>
 
63
        <item><em>new_in_connection/3/5</em> - one of these operations is invoked
 
64
         when a client side ORB tries to set up a connection to the target ORB.
 
65
         If an interceptor exports both versions, arity 3 and 5, which
 
66
         operation that will be invoked is Orber internal.</item>
 
67
        <item><em>out_request/6</em> - supplies all request data on the client side
 
68
         ORB.</item>
 
69
        <item><em>out_request_encoded/6</em> - similar to <c>out_request</c>
 
70
         but the request body is encode.</item>
 
71
        <item><em>in_request_encoded/6</em> - after a new request arrives at the
 
72
         target ORB the request data is passed to the interceptor in
 
73
         encoded format.</item>
 
74
        <item><em>in_request/6</em> - prior to invoking the operation on the
 
75
         target object, the interceptor <c>in_request</c> is called.</item>
 
76
        <item><em>out_reply/6</em> - after the target object replied the
 
77
        <c>out_reply</c> operation is called with the result of the object
 
78
         invocation.</item>
 
79
        <item><em>out_reply_encoded/6</em> - before sending a reply back to the
 
80
         client side ORB this operation is called with the result in 
 
81
         encoded format.</item>
 
82
        <item><em>in_reply_encoded/6</em> - after the client side ORB receives
 
83
         a reply this function is called with the reply in encoded 
 
84
         format.</item>
 
85
        <item><em>in_reply/6</em> - before delivering the reply to the client
 
86
         this operation is invoked.</item>
 
87
        <item><em>closed_in_connection/1</em> - when a connection is terminated
 
88
         on the client side this function is called.</item>
 
89
        <item><em>closed_out_connection/1</em> - if an outgoing connection is
 
90
         terminated this operation will be invoked.</item>
 
91
      </list>
 
92
      <p>The operations <c>new_out_connection</c>, <c>new_in_connection</c>, 
 
93
        <c>closed_in_connection</c> and <c>closed_out_connection</c> operations
 
94
        are only invoked <em>once</em> per connection. The remaining operations
 
95
        are called, as shown below, for every Request/Reply to/from remote
 
96
        CORBA Objects.</p>
 
97
      <marker id="interceptor_operations"></marker>
 
98
      <image file="interceptor_operations">
 
99
        <icaption>
 
100
The Invocation Order of Interceptor Functions.</icaption>
 
101
      </image>
 
102
    </section>
 
103
  </section>
 
104
 
 
105
  <section>
 
106
    <title>Interceptor Example</title>
 
107
    <p>Assume we want to create a simple access service which purpose is to:</p>
 
108
    <list type="bulleted">
 
109
      <item>Only allow incoming request from ORB's residing on a certain set of
 
110
       nodes.</item>
 
111
      <item>Restrict the objects any client may invoke operations on.</item>
 
112
      <item>Only allow outgoing requests to call a limited set of external
 
113
       ORB's.</item>
 
114
      <item>Add a checksum to each binary request/reply body.</item>
 
115
    </list>
 
116
    <p>To restricts the access we use a <c>protected</c> and <c>named</c> ets-table
 
117
      holding all information. How the ets-table is initiated and maintained
 
118
      is implementation specific, but it contain 
 
119
      <c>{Node, ObjectTable, ChecksumModule}</c> where <c>Node</c> is used as 
 
120
      ets-key, <c>ObjectTable</c> is a reference to another ets-table in which
 
121
      we store which objects the clients are allowed to invoke operations on
 
122
      and <c>ChecksumModule</c> determines which module we should use to handle
 
123
      the checksums. </p>
 
124
    <code type="none">
 
125
new_in_connection(Arg, Host, Port) ->
 
126
    %% Since we only use one interceptor we do not care about the
 
127
    %% input Arg since it is set do undefined by Orber.
 
128
    case ets:lookup(in_access_table, Host) of
 
129
         [] ->
 
130
            %% We may want to log the Host/Port to see if someone tried
 
131
            %% to hack in to our system.
 
132
            exit("Access not granted");
 
133
         [{Host, ObjTable, ChecksumModule}] ->
 
134
            {ObjTable, ChecksumModule}
 
135
    end.
 
136
    </code>
 
137
    <p>The returned tuple, i.e., {ObjTable, ChecksumModule}, will be passed
 
138
      as the first argument whenever invoking one of the interceptor functions.
 
139
      Unless the connection attempt did not fail we are now ready for receiving
 
140
      requests from the client side ORB.</p>
 
141
    <p>When a new request comes in the first interceptor function to be invoked is
 
142
      <c>in_request_encoded</c>. We will remove the checksum from the coded
 
143
      request body in the following way:</p>
 
144
    <code type="none">
 
145
in_request_encoded({ObjTable, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
 
146
    NewBin = ChecksumModule:remove_checksum(Bin),
 
147
    {NewBin, Extra}.
 
148
    </code>
 
149
    <p>If the checksum check fails the <c>ChecksumModule</c> should invoke exit/1.
 
150
      But if the check succeeded we are now ready to check if the client-ORB 
 
151
      objects are allowed to invoke operations on the target object. Please note,
 
152
      it is possible to run both checks in <c>in_request_encoded</c>. Please
 
153
      note, the checksum calculation must be relatively fast to ensure a
 
154
      good throughput.</p>
 
155
    <p>If we want to we can restrict any clients to only use a subset of operations
 
156
      exported by a server:</p>
 
157
    <code type="none">
 
158
in_request({ObjTable, ChecksumModule}, ObjKey, Ctx, Op, Params, Extra) ->
 
159
    case ets:lookup(ObjTable, {ObjKey, Op}) of
 
160
         [] ->
 
161
            exit("Client tried to invoke illegal operation");
 
162
         [SomeData] ->
 
163
            {Params, Extra}
 
164
    end.
 
165
    </code>
 
166
    <p>At this point Orber are now ready to invoke the operation on the target 
 
167
      object. Since we do not care about what the reply is the <c>out_reply</c>
 
168
      function do nothing, i.e.:</p>
 
169
    <code type="none">
 
170
out_reply(_, _, _, _, Reply, Extra) ->
 
171
    {Reply, Extra}.
 
172
    </code>
 
173
    <p>If the client side ORB expects a checksum to be added to the reply we
 
174
      add it by using:</p>
 
175
    <code type="none">
 
176
out_reply_encoded({ObjTable, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
 
177
    NewBin = ChecksumModule:add_checksum(Bin),
 
178
    {NewBin, Extra}.
 
179
    </code>
 
180
    <warning>
 
181
      <p>If we manipulate the binary as above the behavior <em>must</em>
 
182
        be <c>Bin == remove_checksum(add_checksum(Bin))</c>.</p>
 
183
    </warning>
 
184
    <p>For outgoing requests the principle is the same. Hence, it is not further
 
185
      described here. The complete interceptor module would look like:</p>
 
186
    <code type="none">
 
187
 
 
188
-module(myInterceptor).
 
189
 
 
190
%% Interceptor functions.
 
191
-export([new_out_connection/3,
 
192
\011 new_in_connection/3,
 
193
\011 closed_in_connection/1,
 
194
\011 closed_out_connection/1,
 
195
\011 in_request_encoded/6,
 
196
\011 in_reply_encoded/6,
 
197
\011 out_reply_encoded/6,
 
198
\011 out_request_encoded/6,
 
199
\011 in_request/6,
 
200
\011 in_reply/6,
 
201
\011 out_reply/6,
 
202
\011 out_request/6]).
 
203
 
 
204
new_in_connection(Arg, Host, Port) ->
 
205
    %% Since we only use one interceptor we do not care about the
 
206
    %% input Arg since it is set do undefined by Orber.
 
207
    case ets:lookup(in_access_table, Host) of
 
208
         [] ->
 
209
            %% We may want to log the Host/Port to see if someone tried
 
210
            %% to hack in to our system.
 
211
            exit("Access not granted");
 
212
         [{Host, ObjTable, ChecksumModule}] ->
 
213
            {ObjTable, ChecksumModule}
 
214
    end.
 
215
 
 
216
new_out_connection(Arg, Host, Port) ->
 
217
    case ets:lookup(out_access_table, Host) of
 
218
         [] ->
 
219
            exit("Access not granted");
 
220
         [{Host, ObjTable, ChecksumModule}] ->
 
221
            {ObjTable, ChecksumModule}
 
222
    end.
 
223
 
 
224
in_request_encoded({_, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
 
225
    NewBin = ChecksumModule:remove_checksum(Bin),
 
226
    {NewBin, Extra}.
 
227
 
 
228
in_request({ObjTable, _}, ObjKey, Ctx, Op, Params, Extra) ->
 
229
    case ets:lookup(ObjTable, {ObjKey, Op}) of
 
230
         [] ->
 
231
            exit("Client tried to invoke illegal operation");
 
232
         [SomeData] ->
 
233
            {Params, Extra}
 
234
    end.
 
235
 
 
236
out_reply(_, _, _, _, Reply, Extra) ->
 
237
    {Reply, Extra}.
 
238
 
 
239
out_reply_encoded({_, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
 
240
    NewBin = ChecksumModule:add_checksum(Bin),
 
241
    {NewBin, Extra}.
 
242
 
 
243
out_request({ObjTable, _}, ObjKey, Ctx, Op, Params, Extra) ->
 
244
    case ets:lookup(ObjTable, {ObjKey, Op}) of
 
245
         [] ->
 
246
            exit("Client tried to invoke illegal operation");
 
247
         [SomeData] ->
 
248
            {Params, Extra}
 
249
    end.
 
250
 
 
251
out_request_encoded({_, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
 
252
    NewBin = ChecksumModule:add_checksum(Bin),
 
253
    {NewBin, Extra}.
 
254
 
 
255
in_reply_encoded({_, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) ->
 
256
    NewBin = ChecksumModule:remove_checksum(Bin),
 
257
    {NewBin, Extra}.
 
258
 
 
259
in_reply(_, _, _, _, Reply, Extra) ->
 
260
    {Reply, Extra}.
 
261
 
 
262
closed_in_connection(Arg) ->
 
263
    %% Nothing to clean up.
 
264
    Arg.
 
265
 
 
266
closed_out_connection(Arg) ->
 
267
    %% Nothing to clean up.
 
268
    Arg.
 
269
    </code>
 
270
    <note>
 
271
      <p>One can also use interceptors for debugging purposes, e.g.,
 
272
        print which objects and operations are invoked with which arguments
 
273
        and the outcome of the operation. In conjunction with the configuration
 
274
        parameter <c>orber_debug_level</c> it is rather easy to find out what
 
275
        went wrong or just to log the traffic.  </p>
 
276
    </note>
 
277
  </section>
 
278
</chapter>
 
279