Merge branch 'pu'
[jungerl.git] / lib / rpc / doc / API.txt
blob4805dd5253071ce6552ad7cf62ec4b74294d4763
1 Copyright (c) 2000, 2001 Sendmail, Inc.  All rights reserved.
3 Introduction
4 ------------
5   
6   This document explains how the generated erlang modules work, and
7   the relationship between the different modules.  It also describes
8   the API to the rpc package.
10   The purpose of this document is to give an overview of the package.
11   It might not be completely correct and up-to-date; consult the code
12   for further details.
14   This package conforms to rfc1831 and rfc1832.  Note that not all rpc
15   generation packages implement the full RPC language.  For example,
16   some C packages does not allow a rpc procedure to take more than one
17   parameter.  This package does not have these limitations.  Keep that
18   in mind if your creating RPC specifications which should be
19   portable.
22 Generating code
23 ---------------
25   see README
28 XDR code
29 --------
31 1.  Representation
33   strings are represented as binaries.
34   structs are represented as tuples.
35   unions are represented as tuples where the first element
36     is the discriminant.
37   all arrays are represented as lists (i.e. w/o explicit size tag)
38   bools are represented as true | false.
39   everything else is straightforward, e.g. hyper as int etc.
41 1.1. Example:
43 Given the following contents of "xx.x":
45   enum eventtype {
46     EVENT_CREATE = 1,
47     EVENT_DELETE = 2
48   };
50   struct event_create {
51     int key;
52     string new;
53   };  
55   union regevent switch (eventtype type) {
56   case EVENT_CREATE:
57     event_create c;
58   case EVENT_DELETE:
59     int          key;
60   };
62 Correct erlang representations:
63   
64   {'EVENT_CREATE', {2, <<"hi mom">>}}
65   {'EVENT_DELETE', 3}
67 Given:
69   union regevent switch (int type) {
70   case 1:
71     event_create c;
72   default:
73     int          key;
74   };
76 Correct erlang representations:
77   
78   {1, {2, <<"hi mom">>}}
79   {5, 3}
82 2.  Encode routines
84   Each type in the .x file gets a enc_type/1 function:
85      enc_type(Term) -> IoList.
87 2.1.  Example
89   xx_xdr:enc_regevent({'EVENT_DELETE', 3}) ->
90      [<<0,0,0,2>>, <<0,0,0,3>>]
92 3.  Decode routines
94   Each type in the .x file gets a dec_type/2 function:
95      dec_type(Bin, Offset) -> {Term, NewOffset}
97   The Offset is an offset in the Binary where to start decoding.
99 3.1.  Example
101   xx_xdr:dec_regevent(<<0,0,0,2,0,0,0,3>>, 0) ->
102      {{'EVENT_DELETE', 3}, 8}
103   xx_xdr:dec_regevent(<<1,2,3,4,0,0,0,2,0,0,0,3>>, 4) ->
104      {{'EVENT_DELETE', 3}, 12}
106 4.  clnt routines
108   The library module rpc_client, and the generated xx_clnt module
109   provides complete client implementations for TCP and UDP.
111   The user must start a rpc_client process explicitly.  Each
112   rpc_client process handles one RPC protocol over one socket only.
113   Each rpc_client can handle many erlang clients though - all calls
114   are multiplexed over the socket.
116 4.1. Diagram
118   The following diagram illustrates the processes and modules
119   involved:
121   A user calls xx_clnt:xx_proc1_1(Term) in some process.
122   xx_clnt:xx_proc1_1(Term) calls xx_xdr:enc() to encode the Term into
123   a io list.  This io list is passed to rpc_client:call(), which
124   performs a gen_server:call to the client process.
126   The client process constructs a rpc msg and sends it to the rpc
127   server over a socket.  The reply is decoded by xx_clnt before it is
128   returned to the user.
131       xx_clnt.erl        xx_xdr.erl         
132   +--------------+      +----------+
133   | xx_proc1_1() |  --> |   enc()  |         rpc_client 
134   |              |  <-- +----------+           process
135   |              |    gen_server:call      +--------------+
136   |              | --------------------->  | send rpc msg | ---> socket
137   |              | <--------------------   | reply        | <---
138   |              |       xx_xdr.erl        +--------------+
139   |              | -->  +----------+
140   |              | <--  | dec()    |
141   |              |      +----------+
142   |              |
143   | xx_proc2_1() | 
144   | ...          |
145   +--------------+
147 4.2 API
149 4.2.1.  rpc_client
151    open(Host, PrgNum, PrgVsn, Proto)
152    open(Host, PrgNum, PrgVsn, Proto, Port) ->
153        <suitable for a child to a supervisor>
154       Proto = tcp | udp
156       If no Port is given, the client contacts the port mapper daemon 
157       on the Host for the PrgNum and PrgVsn.
159       Note that this function returns a linked pid.  If the socket is
160       closed, the pid exits.
162    close(Pid)
163       Terminates the client.
164    
165    <lots of control and statistics functions, see the code for
166    details>
169 5.  svc routines
171   The library module rpc_server, and the generated xx_svc module
172   provides server implementations for TCP and UDP.
174   The server logic can be implemented in two different ways, either as
175   a gen_server process which receives all rpc requests as gen_server
176   calls, or as a rpc_server behaviour callback module.  These variants
177   are described below.
179   The user must start the rpc_server process explicitly.  Each
180   rpc_server process is capable of handling both TCP and UDP at the
181   same time.
183 5.1. Server Implementations
185 5.1.1 gen_server implementation
187   The following diagram illustrates the processes and modules
188   involved:
190   A RPC client sends a RPC call on a socket.  The rpc_server process
191   recieves the messages and decodes it.  Then it calls the xx_svc
192   module, providing the procedure number and arguments.  The xx_svc
193   module translates the procedure number to an erlang atom, calls
194   xx_xdr to decode parameters, then performs a gen_server:call to
195   the user defined server implementation.
197           rpc_server
198            process         
199          +----------+     xx_svc.erl      xx_xdr.erl
200  socket  |          |    +----------+    +----------+     user's
201     ---> |          | -> | xx_prog  | -> | dec()    |     server
202          |          |    |          | <- +----------+     process
203          |          |    |          |   gen_server:call  +--------+
204          |          |    |          |   -------------->  |        |
205          |          |    |          |   <--------------  +--------+
206          |          |    |          |     xx_xdr.erl
207          |          |    |          | -> +----------+
208          |          |    |          | <- | enc()    |
209          |          |    |          |    +----------+
210          |          | <- |          |
211  socket  |          |    +----------+
212     <--  |          |
213          +----------+  
215  Division of labor (on a per-process basis) (follow the arrows upward):
216         ^^                                              ^^
217  [--A---][------------------------B---------------------][---C----]
219  ... where A is the socket port, B is the generic rpc_server, and C is
220  the user-defined gen_server.
222  This is the most generic and transparent way of implementing an rpc
223  server.  The drawback is that each rpc request (and its reply) is
224  sent as a message to the user's process.  Furthermore, the user's
225  server process is a gen_server.  By default, gen_servers can only
226  process one call at a time; this is a performance bottleneck when
227  dealing with multiple RPC clients simultaneously.
229 5.1.2. rpc_server implementation
231   The following diagram illustrates the processes and modules
232   involved:
234   A RPC client sends a RPC call on a socket.  The rpc_server process
235   recieves the messages and decodes it.  Then it calls the xx_svc
236   module, providing the procedure number and arguments.  The xx_svc
237   module translates the procedure number to an erlang atom, calls
238   xx_xdr to decode parameters, then calls the user defined rpc_server
239   callback module.
241           rpc_server
242            process         
243          +----------+     xx_svc.erl      xx_xdr.erl
244  socket  |          |    +----------+    +----------+     user's
245     ---> |          | -> | xx_prog  | -> | dec()    |     rpc_server
246          |          |    |          | <- +----------+     module
247          |          |    |          |     apply          +--------+
248          |          |    |          |   ---------------> |        |
249          |          |    |          |   <--------------- +--------+
250          |          |    |          |     xx_xdr.erl
251          |          |    |          | -> +----------+
252          |          |    |          | <- | enc()    |
253          |          |    |          |    +----------+
254          |          | <- |          |
255  socket  |          |    +----------+
256     <--  |          |
257          +----------+  
259  Division of labor (on a per-process basis) (follow the arrows upward):
260         ^^                                                        ^^
261  [--A---][------------------------B-------------------------------]
263   ... where A is the socket port, B is the generic rpc_server.
265   The advantage of this model is that no copies are made for the rpc
266   requests.
268   The rpc_server behaviour is decribed in 5.2.2.2
271 5.2.1.1  Multi-threaded rpc_server implementation
273   rpc_server allows the callback function return {noreply, S}.
274   This can be used to implement a multi-threaded rpc server:
277   This diagram extends the diagram above, not showing the leftmost
278   part. 
280          user's
281          rpc_server
282          module
283          +--------+
284          |        | -----------------------------> spawn new proc
285          |        |           
286          +--------+                                +------------+
287                                                    |            |
288                     xx_xdr.erl   rpc_server:reply  |            |
289                     +--------+ <----------------   |            |
290                     | enc()  |                     +------------+
291    sock   <-------- +--------+
293  Division of labor (on a per-process basis) (follow the arrows upward):
294         ^^        ^^                                            ^^
295  [---A---][---B---]
296                    [-------------------C------------------------]
297                    [-------------------D------------------------]
298                    [-------------------E------------------------]
300   ... where C,D, and E are dynamically spwawned processes for each, or
301   some, requests.
303   Note that the reply is sent directly to the socket, to via the
304   rpc_server process.
307 5.2. API
309 5.2.1  rpc_server API
311   start_link(Protos, PrgNum, PrgName, PrgVsnLo, PrgVsnHi, Mod, InitArgs)
312   start_link(Name, Protos, PrgName, PrgNum, PrgVsnLo, PrgVsnHi, Mod, InitArgs) ->
313        <suitable for a child to a supervisor>
314     Name      = see gen_server(3)
315     Protos    = [{tcp|udp, Ip, Port, Pmap_p, SockOpts}]
316                 XXX SLF Yes, putting the tuple inside a list is annoying,
317                 but it's necessary unless I want to rip out the multiple
318                 protocol-handling stuff in the bowels of the socket handler,
319                 and since I don't fully understand how that stuff works,
320                 I'll just leave it in for now.  XXX SLF
321     Pmap_p    = bool() if true, the server registers itself with
322                   the local port mapper.
323     SockOpts  = list of extra socket options (see the code)
324     PrgNum    = int() RPC Program number
325     PrgName   = atom() RPC Program name, used to construct the callback
326                 function name in Mod to handle a particular RPC call.
327     PrgVsnLo  = int()
328     PrgVsnHi  = int() The server handles vsns in the interval Lo - Hi
329     Mod       = atom() Dispatch module.
330     InitArgs  = list(), passed to Mod:init/1.
331     Clnt      = client()
333       Note that the client() datatype might contain temporary data
334       associated with the current client call, such as Xid.  Thus, it
335       can't directly be used to identify a client.  Use the access
336       functions described below to extract information from the
337       datatype.  For example, client_ip() can be used to identify a
338       client program.
340     NOTE: The callback module described here is usually not written
341     by the user.  Instead, give the name of the generated xx_svc
342     module here; it conforms to the interface defined above.  For a
343     description of how to implement a server using xx_svc, see 5.2.2.
344     For completeness, the dispatch module API is described in 5.2.1.1.
346     Note on PrgName: This atom is used to construct the function name
347     in module Mod to handle an RPC call.  That function is named
348     PrgNum_PrgVsn, e.g. name_4 for version RPC program version 4.
349     See 5.2.2.1 below for more information.
350   
351   client_ip(Clnt) -> {ok, {Ip, Port}} | {error, Reason}
352     Clnt      = client()
354     Can be used by a server implementation to get the Ip and Port of
355     the current client.
357   client_socket(Clnt) -> Socket
358     Clnt      = client()
360     Can be used by a server implementation to get the socket of the
361     current client.  Note that for UDP, one socket is used for all
362     clients.
364   reply(Clnt, Reply) -> void()
365     Clnt      = client()
366   
367     Used to asynchronously send a rpc reply to a client.  Can only be
368     used when a server is implemented with the rpc_server behaviour,
369     and a callback function returned {noreply, S'}.
371 5.2.1.1  Dispatch module
373    This is the API the dispatch module must follow.  It's recommended
374    to use erpcgen to generate a xx_svc module (see 5.2.2), which is
375    used the dispatch module.  xx_svc conforms to the API described
376    here.
378       Mod:init/1, handle_call/3, handle_cast/2,
379                   handle_info/2, terminate/2  -- like gen_server
380               
381          These functions are called like the gen_server functions.
382          Specifically, the following functions are called:
383            Mod:handle_info({tcp_new, Sock}, State)
384            Mod:handle_info({tcp_closed, Sock}, State)
385          when a tcp client connects resp. disconnects.
387       Mod:ProgN(Proc,Bin,Offset,Clnt,State) ->
388           {success, Result, NState} |
389           {noreply, NState} | 
390           {error, NState} |
391           {garbage_args, Nstate} |
392           exit(Reason)
393        ProgN     = atom() on the form <program>_<program-vsn>
394        Result    = io_list()
396         This function is called when a request is received for the
397         program.
400 5.2.2  xx_svc callback API
402 5.2.2.1  gen_server implementation
404   If erpcgen is given the flag 'svc', the xx_svc module is generated
405   with functions that calls gen_server:call for each rpc request.
407   Thus, the user must define a gen_server process which must be
408   locally registered as xx_server.  The following calls are defined:
410    {Procedure_PrgVsn, Arg1, Arg2, ..., Clnt}
411          Called when a client makes a RPC request the reply value is
412          the erlang representation of the return value for the
413          procedure.  The reply is the return value of the rpc
414          procedure.
416          The "Procedure" portion of the function name is taken from the
417          "program" directive in the RPC specification file, e.g.
418                    program MOUNTPROG {
419                            version MOUNTVERS {
420                                    ...
421                            } = 3;
422                    } = 100005;
423          ... will create a callback function mountprog_3/5.
425   The following messages are sent directly to the process:
427    {tcp_new, Sock}
428          when a tcp client is connected
430    {tcp_closed, Sock}
431          when a tcp client closes it's socket
433   NOTE: The RPC server state variable State is not available to
434   gen_server implementations.
436 5.2.2.2  rpc_server implementation
438   If erpcgen is given the flag 'svc_callback', the xx_svc module is
439   generated with functions that calls a callback module each rpc
440   request.
442   The rpc_server behaviour is like gen_server, with the follwoing
443   differences:
445     o  The process must not change the trap_exit process flag.  The
446        process traps exists.
448     o  The process must not open tcp or udp sockets in active mode,
449        since the messages will interfere with the rpc messages.
450   
451     o  The callback module must be prepared to handle the messages
452        {tcp_new, Sock}, {tcp_closed, Sock}, and {tcp_error, Sock} in
453        its handle_info/2 function.
455   The callback module must export a function for each rpc procedure it
456   implements, in addition to the normal gen_server callbacks:
458     Procedure_PrgVsn({Arg1, ..., ArgN}, Clnt, S) ->
459          {reply, Reply, S'} | 
460          {noreply, S'}      | 
461          {error, S'}
463   If {noreply, S'} is returned, the function rpc_server:reply() must
464   be called, not necessarily by the same process, to reply to the rpc
465   request.
467   Typically, this method would be used by invoking erpcgen as:
469         erpcgen -a '[svc_callback,xdr]' foo.x
471   ... which will create foo_svc.erl and foo_xdr.erl.
472   rpc_server:start_link/7 would then be called with PrgName argument as
473   'ProgramDirective_PrgVsn'.  XXX SLF This is complicated.  Perhaps a
474   definition of terms at the beginning of this doc would help clear up which
475   name to use, the basename of the RPC spec file vs. the name specified by
476   the "program" directive inside the RPC spec file.  XXX SLF
478   The foo_svc.erl file provides a layer of code that 
480 Writing a client
481 ----------------
483 1. Generate xx_clnt.erl, xx_xdr.erl, xx.hrl
485 2. Start the client:
486       rpc_client:open(Host, Program, Version, Proto)
487       rpc_client:open(Host, Program, Version, Proto, Port) ->
488          {ok, LinkedPid} | {error, Reason}
490    Note that the client pid is linked.  The client exits if
491    the socket is closed or if there is any socket error.
493 3.