<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html xmlns:fn="http://www.w3.org/2005/02/xpath-functions"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link rel="stylesheet" href="../../../../doc/otp_doc.css" type="text/css"> <title>Erlang -- Orber Interceptors</title> </head> <body bgcolor="white" text="#000000" link="#0000ff" vlink="#ff00ff" alink="#ff0000"><div id="container"> <script id="js" type="text/javascript" language="JavaScript" src="../../../../doc/js/flipmenu/flipmenu.js"></script><script id="js2" type="text/javascript" src="../../../../doc/js/erlresolvelinks.js"></script><script language="JavaScript" type="text/javascript"> <!-- function getWinHeight() { var myHeight = 0; if( typeof( window.innerHeight ) == 'number' ) { //Non-IE myHeight = window.innerHeight; } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) { //IE 6+ in 'standards compliant mode' myHeight = document.documentElement.clientHeight; } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { //IE 4 compatible myHeight = document.body.clientHeight; } return myHeight; } function setscrollpos() { var objf=document.getElementById('loadscrollpos'); document.getElementById("leftnav").scrollTop = objf.offsetTop - getWinHeight()/2; } function addEvent(obj, evType, fn){ if (obj.addEventListener){ obj.addEventListener(evType, fn, true); return true; } else if (obj.attachEvent){ var r = obj.attachEvent("on"+evType, fn); return r; } else { return false; } } addEvent(window, 'load', setscrollpos); //--></script><div id="leftnav"><div class="innertube"> <img alt="Erlang logo" src="../../../../doc/erlang-logo.png"><br><small><a href="users_guide.html">User's Guide</a><br><a href="index.html">Reference Manual</a><br><a href="release_notes.html">Release Notes</a><br><a href="../pdf/orber-3.6.15.pdf">PDF</a><br><a href="../../../../doc/index.html">Top</a></small><p><strong>orber</strong><br><strong>User's Guide</strong><br><small>Version 3.6.15</small></p> <br><a href="javascript:openAllFlips()">Expand All</a><br><a href="javascript:closeAllFlips()">Contract All</a><p><small><strong>Chapters</strong></small></p> <ul class="flipMenu" imagepath="../../../../doc/js/flipmenu"> <li id="no" title="The Orber Application" expanded="false">The Orber Application<ul> <li><a href="ch_contents.html"> Top of chapter </a></li> <li title="Content Overview"><a href="ch_contents.html#id2259549">Content Overview</a></li> <li title="Brief Description of the User's Guide"><a href="ch_contents.html#id2261515">Brief Description of the User's Guide</a></li> </ul> </li> <li id="no" title="Introduction to Orber" expanded="false">Introduction to Orber<ul> <li><a href="ch_introduction.html"> Top of chapter </a></li> <li title="Overview"><a href="ch_introduction.html#id2253679">Overview</a></li> </ul> </li> <li id="no" title="The Orber Application" expanded="false">The Orber Application<ul> <li><a href="ch_orber_kernel.html"> Top of chapter </a></li> <li title="ORB Kernel and IIOP "><a href="ch_orber_kernel.html#id2267799">ORB Kernel and IIOP </a></li> <li title="The Object Request Broker (ORB)"><a href="ch_orber_kernel.html#id2273126">The Object Request Broker (ORB)</a></li> <li title="Internet Inter-Object Protocol (IIOP)"><a href="ch_orber_kernel.html#id2266281">Internet Inter-Object Protocol (IIOP)</a></li> </ul> </li> <li id="no" title="Interface Repository" expanded="false">Interface Repository<ul> <li><a href="ch_ifr.html"> Top of chapter </a></li> <li title="Interface Repository(IFR)"><a href="ch_ifr.html#id2251838">Interface Repository(IFR)</a></li> </ul> </li> <li id="no" title="Installing Orber" expanded="false">Installing Orber<ul> <li><a href="ch_install.html"> Top of chapter </a></li> <li title="Installation Process "><a href="ch_install.html#id2267620">Installation Process </a></li> <li title="Configuration"><a href="ch_install.html#id2258668">Configuration</a></li> <li title="Firewall Configuration"><a href="ch_install.html#id2274587">Firewall Configuration</a></li> <li title="Interface Configuration"><a href="ch_install.html#id2275079">Interface Configuration</a></li> </ul> </li> <li id="no" title="OMG IDL to Erlang Mapping" expanded="false">OMG IDL to Erlang Mapping<ul> <li><a href="ch_idl_to_erlang_mapping.html"> Top of chapter </a></li> <li title="OMG IDL to Erlang Mapping - Overview"><a href="ch_idl_to_erlang_mapping.html#id2275329">OMG IDL to Erlang Mapping - Overview</a></li> <li title="OMG IDL Mapping Elements"><a href="ch_idl_to_erlang_mapping.html#id2275358">OMG IDL Mapping Elements</a></li> <li title="Getting Started"><a href="ch_idl_to_erlang_mapping.html#id2275422">Getting Started</a></li> <li title="Basic OMG IDL Types"><a href="ch_idl_to_erlang_mapping.html#id2275495">Basic OMG IDL Types</a></li> <li title="Template OMG IDL Types and Complex Declarators"><a href="ch_idl_to_erlang_mapping.html#id2276045">Template OMG IDL Types and Complex Declarators</a></li> <li title="Constructed OMG IDL Types"><a href="ch_idl_to_erlang_mapping.html#id2276571">Constructed OMG IDL Types</a></li> <li title="Scoped Names and Generated Files"><a href="ch_idl_to_erlang_mapping.html#id2277017">Scoped Names and Generated Files</a></li> <li title="Typecode, Identity and Name Access Functions"><a href="ch_idl_to_erlang_mapping.html#id2277452">Typecode, Identity and Name Access Functions</a></li> <li title="References to Constants"><a href="ch_idl_to_erlang_mapping.html#id2277608">References to Constants</a></li> <li title="References to Objects Defined in OMG IDL"><a href="ch_idl_to_erlang_mapping.html#id2277673">References to Objects Defined in OMG IDL</a></li> <li title="Exceptions"><a href="ch_idl_to_erlang_mapping.html#id2277699">Exceptions</a></li> <li title="Access to Attributes"><a href="ch_idl_to_erlang_mapping.html#id2277737">Access to Attributes</a></li> <li title="Invocations of Operations"><a href="ch_idl_to_erlang_mapping.html#id2277798">Invocations of Operations</a></li> <li title="Implementing the DB Application"><a href="ch_idl_to_erlang_mapping.html#id2277980">Implementing the DB Application</a></li> <li title="Reserved Compiler Names and Keywords"><a href="ch_idl_to_erlang_mapping.html#id2278268">Reserved Compiler Names and Keywords</a></li> <li title="Type Code Representation"><a href="ch_idl_to_erlang_mapping.html#id2279028">Type Code Representation</a></li> </ul> </li> <li id="no" title="CosNaming Service" expanded="false">CosNaming Service<ul> <li><a href="ch_naming_service.html"> Top of chapter </a></li> <li title="Overview of the CosNaming Service"><a href="ch_naming_service.html#id2279707">Overview of the CosNaming Service</a></li> <li title="The Basic Use-cases of the Naming Service"><a href="ch_naming_service.html#id2279873">The Basic Use-cases of the Naming Service</a></li> <li title="Interoperable Naming Service"><a href="ch_naming_service.html#id2280252">Interoperable Naming Service</a></li> </ul> </li> <li id="no" title="How to use security in Orber" expanded="false">How to use security in Orber<ul> <li><a href="ch_security.html"> Top of chapter </a></li> <li title="Security in Orber"><a href="ch_security.html#id2281165">Security in Orber</a></li> </ul> </li> <li id="no" title="Orber Stubs/Skeletons" expanded="false">Orber Stubs/Skeletons<ul> <li><a href="ch_stubs.html"> Top of chapter </a></li> <li title="Orber Stubs and Skeletons Description"><a href="ch_stubs.html#id2281584">Orber Stubs and Skeletons Description</a></li> </ul> </li> <li id="no" title="CORBA System and User Defined Exceptions" expanded="false">CORBA System and User Defined Exceptions<ul> <li><a href="ch_exceptions.html"> Top of chapter </a></li> <li title="System Exceptions"><a href="ch_exceptions.html#id2282246">System Exceptions</a></li> <li title="User Defined Exceptions"><a href="ch_exceptions.html#id2282730">User Defined Exceptions</a></li> <li title="Throwing Exceptions"><a href="ch_exceptions.html#id2282754">Throwing Exceptions</a></li> <li title="Catching Exceptions"><a href="ch_exceptions.html#id2282790">Catching Exceptions</a></li> </ul> </li> <li id="loadscrollpos" title="Orber Interceptors" expanded="true">Orber Interceptors<ul> <li><a href="ch_interceptors.html"> Top of chapter </a></li> <li title="Using Interceptors"><a href="ch_interceptors.html#id2282911">Using Interceptors</a></li> <li title="Interceptor Example"><a href="ch_interceptors.html#id2283153">Interceptor Example</a></li> </ul> </li> <li id="no" title="OrberWeb" expanded="false">OrberWeb<ul> <li><a href="ch_orberweb.html"> Top of chapter </a></li> <li title="Using OrberWeb"><a href="ch_orberweb.html#id2283471">Using OrberWeb</a></li> <li title="Starting OrberWeb"><a href="ch_orberweb.html#id2284120">Starting OrberWeb</a></li> </ul> </li> <li id="no" title="Debugging" expanded="false">Debugging<ul> <li><a href="ch_debugging.html"> Top of chapter </a></li> <li title="Tools and FAQ"><a href="ch_debugging.html#id2284216">Tools and FAQ</a></li> </ul> </li> </ul> </div></div> <div id="content"> <div class="innertube"> <h1>11 Orber Interceptors</h1> <h3><a name="id2282911">11.1 Using Interceptors</a></h3> <p>For Inter-ORB communication, e.g., via <span class="code">IIOP</span>, it is possible to intercept requests and replies. To be able to use <span class="code">Interceptors</span> Orber the configuration parameter <span class="code">interceptors</span> must be defined.</p> <h4>Configure Orber to Use Interceptors</h4> <p>The configuration parameter <span class="code">interceptors</span> must be defined, e.g., as command line option:</p> <div class="example"><pre> erl -orber interceptors "{native, ['myInterceptor']}" </pre></div> <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 <span class="code">orber:activate_audit_trail/0/1</span> and <span class="code">orber:activate_audit_trail/0/1.</span></p> <h4>Creating Interceptors</h4> <p>Each supplied interceptor <strong>must</strong> export the following functions:</p> <ul> <li> <strong>new_out_connection/3/5</strong> - 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.</li> <li> <strong>new_in_connection/3/5</strong> - 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.</li> <li> <strong>out_request/6</strong> - supplies all request data on the client side ORB.</li> <li> <strong>out_request_encoded/6</strong> - similar to <span class="code">out_request</span> but the request body is encode.</li> <li> <strong>in_request_encoded/6</strong> - after a new request arrives at the target ORB the request data is passed to the interceptor in encoded format.</li> <li> <strong>in_request/6</strong> - prior to invoking the operation on the target object, the interceptor <span class="code">in_request</span> is called.</li> <li> <strong>out_reply/6</strong> - after the target object replied the <span class="code">out_reply</span> operation is called with the result of the object invocation.</li> <li> <strong>out_reply_encoded/6</strong> - before sending a reply back to the client side ORB this operation is called with the result in encoded format.</li> <li> <strong>in_reply_encoded/6</strong> - after the client side ORB receives a reply this function is called with the reply in encoded format.</li> <li> <strong>in_reply/6</strong> - before delivering the reply to the client this operation is invoked.</li> <li> <strong>closed_in_connection/1</strong> - when a connection is terminated on the client side this function is called.</li> <li> <strong>closed_out_connection/1</strong> - if an outgoing connection is terminated this operation will be invoked.</li> </ul> <p>The operations <span class="code">new_out_connection</span>, <span class="code">new_in_connection</span>, <span class="code">closed_in_connection</span> and <span class="code">closed_out_connection</span> operations are only invoked <strong>once</strong> per connection. The remaining operations are called, as shown below, for every Request/Reply to/from remote CORBA Objects.</p> <a name="interceptor_operations"></a> <img alt="IMAGE MISSING" src="interceptor_operations.gif"><br> <em>Figure 11.1: The Invocation Order of Interceptor Functions.</em> <h3><a name="id2283153">11.2 Interceptor Example</a></h3> <p>Assume we want to create a simple access service which purpose is to:</p> <ul> <li>Only allow incoming request from ORB's residing on a certain set of nodes.</li> <li>Restrict the objects any client may invoke operations on.</li> <li>Only allow outgoing requests to call a limited set of external ORB's.</li> <li>Add a checksum to each binary request/reply body.</li> </ul> <p>To restricts the access we use a <span class="code">protected</span> and <span class="code">named</span> ets-table holding all information. How the ets-table is initiated and maintained is implementation specific, but it contain <span class="code">{Node, ObjectTable, ChecksumModule}</span> where <span class="code">Node</span> is used as ets-key, <span class="code">ObjectTable</span> is a reference to another ets-table in which we store which objects the clients are allowed to invoke operations on and <span class="code">ChecksumModule</span> determines which module we should use to handle the checksums. </p> <div class="example"><pre> 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. </pre></div> <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 <span class="code">in_request_encoded</span>. We will remove the checksum from the coded request body in the following way:</p> <div class="example"><pre> in_request_encoded({ObjTable, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) -> NewBin = ChecksumModule:remove_checksum(Bin), {NewBin, Extra}. </pre></div> <p>If the checksum check fails the <span class="code">ChecksumModule</span> 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 <span class="code">in_request_encoded</span>. 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> <div class="example"><pre> 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. </pre></div> <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 <span class="code">out_reply</span> function do nothing, i.e.:</p> <div class="example"><pre> out_reply(_, _, _, _, Reply, Extra) -> {Reply, Extra}. </pre></div> <p>If the client side ORB expects a checksum to be added to the reply we add it by using:</p> <div class="example"><pre> out_reply_encoded({ObjTable, ChecksumModule}, ObjKey, Ctx, Op, Bin, Extra) -> NewBin = ChecksumModule:add_checksum(Bin), {NewBin, Extra}. </pre></div> <div class="warning"> <div class="label">Warning</div> <div class="content"><p> <p>If we manipulate the binary as above the behavior <strong>must</strong> be <span class="code">Bin == remove_checksum(add_checksum(Bin))</span>.</p> </p></div> </div> <p>For outgoing requests the principle is the same. Hence, it is not further described here. The complete interceptor module would look like:</p> <div class="example"><pre> -module(myInterceptor). %% Interceptor functions. -export([new_out_connection/3, new_in_connection/3, closed_in_connection/1, closed_out_connection/1, in_request_encoded/6, in_reply_encoded/6, out_reply_encoded/6, out_request_encoded/6, in_request/6, in_reply/6, out_reply/6, 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. </pre></div> <div class="note"> <div class="label">Note</div> <div class="content"><p> <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 <span class="code">orber_debug_level</span> it is rather easy to find out what went wrong or just to log the traffic. </p> </p></div> </div> </div> <div class="footer"> <hr> <p>Copyright © 1997-2010 Ericsson AB. All Rights Reserved.</p> </div> </div> </div></body> </html>