Sophie

Sophie

distrib > Mandriva > 8.2 > i586 > media > contrib > by-pkgid > 211238da6d926d1ca4390483bb29f586 > files > 59

coda-doc-5.2.0-4mdk.noarch.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
 <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9">
 <TITLE> RPC2 User Guide and Reference Manual: RPC2 Runtime System</TITLE>
 <LINK HREF="rpc2_manual-5.html" REL=next>
 <LINK HREF="rpc2_manual-3.html" REL=previous>
 <LINK HREF="rpc2_manual.html#toc4" REL=contents>
</HEAD>
<BODY>
<A HREF="rpc2_manual-5.html">Next</A>
<A HREF="rpc2_manual-3.html">Previous</A>
<A HREF="rpc2_manual.html#toc4">Contents</A>
<HR>
<H2><A NAME="s4">4. RPC2 Runtime System</A></H2>

<P>
<A NAME="RuntimeSystem"></A> <P>The purpose of this section is to describe the calls provided by the
RPC2 library.
These calls deal with contiguous <EM>Packet Buffers</EM>
each of which consists of a:
<DL>
<DT><B><EM>Prefix</EM>.</B><DD><P>which is of fixed length, and is used internally by the runtime
system.  It is NOT transmitted.
<P>
<DT><B><EM>Header</EM>.</B><DD><P>which is also of fixed length, and whose format is understood by
the runtime system. The<CODE> opcode</CODE> associated with the RPC, sequencing 
information, and the completion code returned by the remote site are the kinds
of information found here.
<P>
<DT><B><EM>Body</EM>.</B><DD><P>of arbitrary size.  It is NOT interpreted by the runtime system,
and is used to transmit the input and output parameters of an RPC.
</DL>
<P>
<P>
<P>Appendix 
<@@ref>rpc2.hXXX</A> contains the header file, <EM>rpc2.h</EM>, that defines the packet format as well as numerous other definitions used in the call
descriptions that follow.
Of course, the actual header files are the authoritative source of
these definitions, and will be more up-to-date than this manual.
<P>The following sections define the RPC2 runtime calls.  Some of these
calls are not relevant to you if you use RP2Gen.
Others, such as the initialization and export calls,
are pertinent to all users of RPC2.
<P>
<P>
<P>
<H2><A NAME="ss4.1">4.1 Client-related Calls</A>
</H2>

<P>
<P>
<H3>ROC2_NewBinding -- <EM>Create a new connection</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_NewBinding</EM>(<B>in</B> RPC2_HostIdent*Host;<B> in</B> RPC2_PortalIdent *Portal;<B> in</B> RPC2_SussysIdent *Subsys;<B> in</B> RPC2_BindParms *Bparms;<B> out</B> RPC2_Handle *ConnHandle).
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>Host</B><DD><P>The identity of the remote host on which the server to be contacted is located.  This may be specified as a string name or as an Internet address.  In the former case the RPC runtime system will do the necessary name resolution.
<P>
<DT><B>Portal</B><DD><P>An identification of the server process to be contacted at the remote site. Portals are unique on a given host.  A portal  may be specified as a string name or as an Internet port value.  In the former case the RPC runtime system will do the necessary name to port number conversion.  Support for other kinds of portals (such as Unix domain) may be available in future.
<P>
<DT><B>Subsys</B><DD><P>Which of the potentially many subsystems supported by the remote server is desired.  May be specified as a number or as a name.  In the latter case, the RPC runtime system will do the translation from name to number.
<P>
<DT><B>Bparms</B><DD><P>Type RPC2_BindParms is a struct containing 5 fields. The first field SecurityLevel is one of the constants RPC2_OPENKIMONO, RPC2_ONLYAUTHENTICATE, RPC2_HEADERSONLY or RPC2_SECURE. The second field, EncryptionType, describes what kind of encryption to be used on this connection.  For example, RPC2_XOR, RPC2_DES, etc. is ignored if, SecurityLevel, is RPC2_OPENKIMONO.  The bind will fail if the remote site does not support the requested type of encryption. The third field, SharedSecret, is an encryption key known by the callback procedure on the server side to be uniquely associated with, ClientIdent. Used by the RPC runtime system in the authentication handshakes.  May be NULL if, SecurityLevel, is RPC2_OPENKIMONO. The fourth field, ClientIdent, provides the information for the server to uniquely identify this client and to obtain, SharedKey. Not interpreted by the RPC runtime system. Only the GetKeys callback procedure on the server side need understand the format of ClientIdent.  May be NULL if SecurityLevel is RPC2_OPENKIMONO. The fifth field, SideEffectType, describes what kind of side effects are to be associated with this connection.  The only side effects intially supported are bulk-transfers of files, identified by type, SMARTFTP. May be 0 if no side effects are ever to be attempted on this connection.
<P>
<DT><B>ConnHandle</B><DD><P>An unique integer returned by the call, identifying this connection. This is not necessarily a small-valued integer.
</DL>
<P>
<P>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>All went well.
<DT><B>RPC2_NOBINDING</B><DD><P>The specified host, server or subsystem could not be contacted.
<DT><B>RPC2_WRONGVERSION</B><DD><P>The client and server runtime systems are  incompatible.  Note that extreme incompatibilty may result in the server being unable to respond even with this error code.  In such a case, the server will appear to be down, resulting in an RPC_NOBINDING return code.
<DT><B>RPC2_OLDVERSION</B><DD><P>This is a warning.  The, RPC2_VERSION, values on client and server sides are different.  Normal operation is still possible, but one of you is running an obsolete version of the runtime system.  You should obtain the latest copy of the RPC runtime system and recompile your code.
<DT><B>RPC2_NOTAUTHENTICATED</B><DD><P>A SecurityLevel other than, RPC2_OPENKIMONO, was specified, and the server did not accept your credentials.
<DT><B>RPC2_SEFAIL1</B><DD><P>The associated side effect routine indicated a minor failure.  The connection is established, and usable.
<DT><B>RPC2_SEFAIL2</B><DD><P>The associated side effect routine indicated a serious failure.  The connection is not established.
<DT><B>RPC2_FAIL</B><DD><P>Some other mishap occurred.
</DL>
<P>
<P>
<H3>Description:</H3>

<P>Creates a new connection and binds to a remote server on a 
remote host.  The subsystem information is passed on to that server to alert it to the kind of remote procedure calls that it may expect on this connection../
<P>A client-server version check is performed to ensure that
the runtime systems are compatible.  Note that there are really two version checks.         One is for the RPC network protocol
and packet formats, and this must succeed.  The other check reports a warning if you have a different RPC runtime system
from the server.  You may also wish to do a higher-level check, to ensure that the client and server application code are compatible../
<P>
<P>The SecurityLevel parameter determines the degree to which you can
trust this connection.  If RPC2_OPENKIMONO is specified, the 
connection is not authenticated and no encryption is done on future
requests and responses.  If RPC2_ONLYAUTHENTICATE is specified, an
authentication handshake is done to ensure that the client and the 
server are who they claim to  to be (the fact that the server can 
find SharedSecret from ClientIdent is assumed to be proof of its
identity.  If RPC2_SECURE is specified, the connection is 
authenticated and all future transmissions on it are encrypted using
a session key generated during the authentication handshake. 
RPC2_HEADERSONLY is similar
to RPC2_SECURE, except that only RPC headers are encrypted.
<P>The kind of encryption used is specified in EncryptionType.  The remote site must specify
an RPC2_GetRequest with an EncryptionTypeMask that includes this encryption type.
<P>
<P>
<H3>RPC2_Bind -- <EM>Obsolete: use RPC2_NewBinding</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_Bind</EM>(<B>in</B> long SecurityLevel,  <B>in</B> long EncryptionType, <B>in</B> RPC2_HostIdent *Host, <B>in</B> RPC2_PortalIdent *Portal, <B>in</B> RPC2_SubsysIdent *Subsys,  <B>in</B> long SideEffectType, <B>in</B> RPC2_CountedBS *ClientIdent, <B>in</B> RPC2_EncryptionKey *SharedSecret, <B>out</B> RPC2_Handle *ConnHandle.
<H3>Parameters:</H3>

<P><EM>N/A</EM>
<H3>Completion Codes:</H3>

<P><EM>None.</EM>
<H3>Description:</H3>

<P>Obsolete.
<P>
<H3>RPC2_MakeRPC -- <EM>Make a remote procedure call (with possible side-effect)</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_MakeRPC</EM>(<B>in</B> RPC2_Handle ConnHandle, <B>in</B>  RPC2_PacketBuffer *Request, <B>in</B> Descriptor *SDesc, <B>out</B>  RPC2_PacketBuffer **Reply, <B>in</B> struct timeval *Patience, <B>in</B> long EnqueueRequest.
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>ConnHandle</B><DD><P>Identifies the connection on which the call is to be made
<DT><B>Request</B><DD><P>A properly formatted request buffer.
<DT><B>SDesc</B><DD><P>A side effect descriptor with local fields filled in.  May be NULL if no side effects will occur as a result of this call.
<DT><B>Reply</B><DD><P>On return, it will point to a response buffer
holding the response from the server.  You should free this buffer when you are done with it.
<DT><B>Patience</B><DD><P>Maximum time to wait for remote site to 
respond.  A NULL pointer indicates infinite patience.
<DT><B>EnqueueRequest.</B><DD><P>Specifies whether the caller should be blocked if ConnHandle is already servicing an RPC request from some other lwp.  If this variable is 1 the caller is blocked.  Otherwise a return code of RPC2_CONNBUSY is returned.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>All went well. 
<DT><B>RPC2_NOCONNECTION</B><DD><P>ConnHandle does not refer to a valid connection.
<DT><B>RPC2_TIMEOUT</B><DD><P>A response was not received soon enough. Occurs only if the Patience parameter was non-NULL.
<DT><B>RPC2_SEFAIL1</B><DD><P>The associated side effect resulted in a minor failure.  Future calls on this connection will still work.
<DT><B>RPC2_SEFAIL</B><DD><P>The associated side effect resulted in a serious failure.  Future calls on this connection will fail.
<DT><B>RPC2_DEAD</B><DD><P>The remote site has been deemed dead or unreachable.  Note that this is orthogonal to an RPC2_TIMEOUT return code.
<DT><B>RPC2_NAKED</B><DD><P>The remote site sent an explicit negative acknowledgement.  This can happen if that site thought you were dead, or if someone at that site unbound your connection.
<DT><B>RPC2_CONNBUSY</B><DD><P>EnqueueRequest specified 0 and ConnHandle is currently servicing a call. Try again later. .
<DT><B>RPC2_FAIL</B><DD><P>Other assorted calamities, such as attempting to use a connection already declared broken.
</DL>
<H3>Description:</H3>

<P>The workhorse routine, used to make remote calls after establishing a connection.
The call is sequential and the calling lwp is blocked until the call completes.
The associated side effect, if any, is finished before the call completes.
The listed completion codes are from the local RPC stub.
Check the RPC2_ReturnCode fields of the reply  and the status fields of SDesc to see what the remote
site thought of your request.  Without an explicit timeout interval the remote site can take as long as it
wishes to perform the requested operation and associated side effects.  The RPC protocol checks periodically
to ensure that the remote site is alive.  If an explicit  Patience timeout interval is specified,  
the call must complete within that time.
<P>
<P>
<H3>RPC2_MultiRPC -- <EM>Make a collection of remote procedure calls</EM></H3>

<P>
<H3>Calls:</H3>

<P><EM>int RPC2_MultiRPC</EM>(<B>in</B> int HowMany, <B>in</B> RPC2_Handle ConnHandleList[ ], <B>out</B> RPC2_Integer *RCList, <B>in out</B> RPC2_Multicast *MCast, <B>in</B> RPC2_PacketBuffer *Request, <B>in</B> Descriptor SDescList[ ], <B>in</B> long (*UnpackMulti (), <B>in out</B> ARG(INFO) *ArgInfo, <B>in</B> struct timeval *Patience.
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>HowMany</B><DD><P>How many servers to contact.
<DT><B>ConnHandleList.</B><DD><P>Array of length HowMany, containing the handles of the connections on which calls are to be made.
<DT><B>Request</B><DD><P>A properly formatted request buffer.
<DT><B>RCList</B><DD><P>Array of length HowMany, into which RPC2 will place return codes for each of the connections specified in ConnHanleList.  May be specified as NULL if return codes will not be examined.
<DT><B>MCast</B><DD><P>Pointer to multicast sturcture.  Set to NULL for now.
<DT><B>SDescList</B><DD><P>Array of length HowMany, containing side effect descriptors for each of the connections specified in ConnHandleList.
<DT><B>UnpackMulti</B><DD><P>Pointer to unpacking routine called by RPC2
when each server response as received. If RP2Gen is used, this will be
supplied by MRPC(MakeMulti. Otherwise, it must be supplied by the client.
<DT><B>ArgInfo</B><DD><P>A pointer to a structure containing argument information. This structure is not examined by RPC2; it is passed untouched to 
UnpackMulti. If RP2Gen is used, this structure will be supplied by
MRPC(MakeMulti. Otherwise, it can be used to pass any structure desired by the
client or supplied as NULL.
<DT><B>Patience</B><DD><P>Maximum time to wait for remote sites to respond. A NULL pointer indicates infinite patience as long as RPC2 believes that the server is alive. Note that this timeout value is orthogonal to the RPC2 internal timeout for determining connection death.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS.</B><DD><P>All servers returned successfully, or all servers until client-initiated abort returned successfully. Individual server response information is supplied via UnpackMulti to the user handler routine supplied in the ArgInfo structure.
<DT><B>RPC2_TIMEOUT.</B><DD><P>The user specified timeout expired before all the servers responded.
<DT><B>RPC2_FAIL.</B><DD><P>Something other than SUCCESS or TIMEOUT occurred. More detailed information is supplied via UnpackMulti to the user handler routine supplied in the ArgInfo structure.
</DL>
<H3>Description:</H3>

<P>Logically identical to iterating through ConnHandleList and making RPC2_MakeRPC calls to each specified
connection using Request as the request block, but this call will be considerably faster than explicit
iteration. The calling lightweight process
blocks until either the client requests that the call abort or one of the following is true about each of
the connections specified in ConnHandleList: a reply has been received, a hard error has been detected for
that connection, or the specified timeout has elapsed.
<P>The ArgInfo structure exists to supply argument packing and
unpacking information in the case where RP2Gen is used. Since its value is
not examined by RPC2, it can contain any pointer that a non-RP2Gen generated
client wishes to supply.
<P>Similarly, UnpackMulti will point to a specific unpacking routine in
the RP2Gen case. If the RP2Gen interface is not used, you should assume that the return
codes of the supplied routine must conform to the specifications in section
<A HREF="rpc2_manual-18.html#UnpackMultiInfo">XXX</A>.
<P>Side effects are supported as in the standard RPC2 case except that the
client must supply a separate <B>SE[Descriptor]</B> for each connection. The
format for the <B>SE[Descriptor]</B>argument is described in Section
<A HREF="rpc2_manual-6.html#interface">XXX</A>.
It will often be useful to supply
connection specific information such as unique file names in the
<B>SE[Descriptor]</B>.
<P>
<P>
<H2><A NAME="ss4.2">4.2 Server-related RPC Calls</A>
</H2>

<P>
<H3>RPC2_Export -- <EM>Indicate willingness to accept calls for a subsystem</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_Export</EM>(<B>in</B> <EM>RPC2_SubsysIdent *Subsys</EM>)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>Subsys</B><DD><P>Specifies a subsystem that will be henceforth recognized by this server.  This is either an integer or a symbolic name that can be translated to the unique integer identifying this subsystem.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>All went well.
<DT><B>RPC2_DUPLICATESERVER</B><DD><P>Your have already exported Subsys.
<DT><B>RPC2_BADSERVER</B><DD><P>Subsys is invalid.
<DT><B>RPC2_FAIL</B><DD><P>Something else went wrong.
</DL>
<H3>Description:</H3>

<P>Sets up internal tables so that when a remote client performs an RPC2_Bind( operation specifying this host-portal-subsystem triple, the RPC runtime system will accept it. A server may declare itself to be serving more than one subsystem by making more than one RPC2_Export calls.
<P>
<P>
<H3>RPC2_DeExport -- <EM>Stop accepting new connections for one or all subsystems</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_Export</EM>(<B>in</B> RPC2_SubsysIdent *Subsys)
<H3>Parameters:</H3>

<P> 
<DL>
<DT><B>Subsys.</B><DD><P>Specifies the subsystem  to be deexported. This is either an integer or a symbolic name that can be translated to the unique integer identifying this subsystem. A value of NULL deexports all subsystems.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>All went well.
<DT><B>RPC2_BADSERVER</B><DD><P>Subsys is not a valid subsystem, or has not been previously exported.
<DT><B>RPC2_FAIL</B><DD><P>Something else went wrong.
</DL>
<H3>Description:</H3>

<P>After this call, no new connections for subsystem Subsys will be accepted.  The subsystem may, however, be exported again at a later time.  Note that existing connections are not broken by this call.
<P>
<P>
<H3>RPC2_GetRequest --  <EM>Wait for an RPC request or a new connection</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_GetRequest</EM>(<B>in</B>RPC2_RequestFilter *Filter, <B>out</B> RPC2_Handle *ConnHandle, <B>out</B>  RPC2_PacketBuffer **Request, <B>in</B> struct timeval *Patience, <B>in</B> long (*GetKeys) (), <B>in</B> long EncryptionTypeMask, <B>in</B> long (*AuthFail) ()) 
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>Filter</B><DD><P>A filter specifying which requests are acceptable.  See description below.
<DT><B>ConnHandle</B><DD><P>Specifies the connection on which the request was received.
<DT><B>Request</B><DD><P>Value ignored on entry. On return, it will point to a buffer
holding the  response from the client.  Free this buffer after you are done with it.
<DT><B>Patience</B><DD><P>A timeout interval specifying how long to wait for a request. 
If NULL, infinite patience is assumed.
<DT><B>GetKeys</B><DD><P>Pointer to a callback procedure to obtain authentication and session keys. See description below.
May be NULL if no secure bindings to this server are to be accepted.
<DT><B>EncryptionTypeMask</B><DD><P>A bit mask specifying which types of encryption is supported. Binds from clients who request an encryption type not specified in this mask will fail.
<DT><B>AuthFail</B><DD><P>Pointer to a callback procedure to be called when an authentication failure occurs. See description below.  May be NULL if server does not care to note such failures.
</DL>
<H3>Completion Codes:</H3>

<P> 
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>I have a request for you in Request.  New connections result in a fake request.
<DT><B>RPC2_TIMEOUT</B><DD><P>Specified time interval expired.
<DT><B>RPC2_BADFILTER</B><DD><P>A nonexistent connection or subsystem was specified in Filter.
<DT><B>RPC2_SEFAIL1</B><DD><P>The associated side effect routine indicated a minor failure.  Future calls on this connection will still work.
<DT><B>RPC2_SEFAIL2</B><DD><P>The associated side effect routine indicated a serious failure.  Future calls on this connection will fail too.
<DT><B>RPC2_DEAD</B><DD><P>You were waiting for requests on a specific connection and that site has been deemed dead or unreachable.
<DT><B>RPC2_FAIL</B><DD><P>Something irrecoverable happened.
</DL>
<H3>Description:</H3>

<P>The call blocks the calling lightweight process until a request is available, a new connection is made, or until the specified timeout period has elapsed.  The Filter parameter allows a great deal of flexibility in selecting precisely which calls are acceptable.  New connections result in a fake request with a body of type RPC2_NewConnection. Do not try to do a RPC2_SendResponse to this call.  All other RPC2_GetRequest calls should be eventually matched with a corresponding RPC2_SendResponse call.
<P>The fields of RPC2_NewConnection are self-explanatory.  Note that you must invoke RPC2_Enable() after you have handled the new connection packet for further requests to be visible.  If you are using RP2Gen, this is done for you automatically by the generated code that deals with new connections. 
<P>The callback procedure for key lookup should be defined as follows 
<BLOCKQUOTE><CODE>
<EM>long GetKeys (<B>in</B> RPC2_CoundedBS *ClientIdent,
<B>out</B> RPC2_EncryptionKey *IdentKey,
<B>out</B> RPC2_EncryptionKey *SessionKey)</EM>
</CODE></BLOCKQUOTE>
<P>GetKeys ( will be called at some point in the 
authentication handshake.  It should return 0 if 
ClientIdent is successfully looked up, and -1 if the
handshake is to be terminated.  It should fill IdentKey
with the key to be used in the handshake, and SessionKey
with an arbitrary key to be used for the duration of this
connection.  You may, of course, make SessionKey the same as IdentKey.
<P>The callback procedure for noting authentication failure should be defined as follows:
<BLOCKQUOTE><CODE>
<EM>long AuthFail (<B>in</B> RPC2_CoundedBS *ClientIdent,
<B>in</B> RPC2_Integer EncryType,
<B>in</B> RPC2_HostIdent *PeerHost,
<B>in</B> RPC2_PortalIdent *PeerPortal)</EM>
</CODE></BLOCKQUOTE>
<P>AuthFail ()will be called after an RPC2_NOTAUTHENTICATED packet 
has been sent to the client. The parameters give information about
the client who was trying to authenticate himself, the type of encryption
requested, and the site from which the RPC2_Bind( was attempted.
The callback procedure will typically record this in a log file somewhere.
<P>
<P>
<P>
<H3>RPC2_Enable -- <EM>Allow servicing of requests on a new connection</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int32_t RPC2_Enable(<B>in</B> RPC2_Handle ConnHandle)</EM>
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>ConnHandle.</B><DD><P>Which connection is to be enabled.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>Enabled the connection.
<DT><B>RPC2_NOCONNECTION</B><DD><P>A bogus connection was specified.
</DL>
<H3>Description:</H3>

<P>Typically invoked  by the user at the end of his NewConnection routine, after setting up his higher-level data structures appropriately.  Until a connection is enabled, RPC2 guarantees that no requests on that connection will be returned in a RPC2_GetRequest call. Such a request from a client will, however, be held and responded to with RPC2_BUSY signals until the connection is enabled.  This call is present primarily to avoid race hazards in higher-level connection establishment.  Note that RP2Gen automatically generates this call after a NewConnection routine.
<P>
<P>
<H3>RPC2_SendResponse -- <EM>Respond to a request from my client</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int32_t RPC2_SendResponse</EM>(<B>in</B> RPC2_Handle ConnHandle, <B>in</B>  RPC2_PacketBuffer *Reply)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>ConnHandle</B><DD><P>hich connection the response is to be sent on.,
<DT><B>Reply</B><DD><P>A filled-in buffer containing the reply to be sent to the client.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>I sent your response.
<DT><B>RPC2_NOTWORKER</B><DD><P>You were not given a request to service.
<DT><B>RPC2_SEFAIL1</B><DD><P>The associated side effect routine indicated a minor failure.  Future calls on this connection will still work.
<DT><B>RPC2_SEFAIL2</B><DD><P>The associated side effect routine indicated a serious failure.  Future calls on this connection will fail too.
<DT><B>RPC2_FAIL</B><DD><P>Some irrecoverable failure happened.
</DL>
<H3>Description:</H3>

<P>Sends the specified reply to the caller.  Any outstanding side effects are completed before Reply is sent.
Encryption, if any, is done in place and will clobber the Reply buffer.  Note that this call returns immediately after sending the reply; it does not wait for an acknowledgement from the client.
<P>
<P>
<H3>RPC2_InitSideEffect -- <EM>Initiate side effect</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int32_t RPC2_InitSideEffect<B>in</B> RPC2_Handle ConnHandle, <B>in</B>  *SDesc)</EM>
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>ConnHandle</B><DD><P>The connection on which the side effect is to be initiated.,
<DT><B>SDesc</B><DD><P>A filled-in side effect descriptor.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>The side effect has been initiated.
<DT><B>RPC2_NOTSERVER</B><DD><P>Only one side effect is allowed per RPC call. This has to be initiated between the GetRequest and SendResponse of that call.  You are violating one of these restrictions.
<DT><B>RPC2_SEFAIL1</B><DD><P>The associated side effect routine indicated a nonfatal failure.  Future calls on this connection will work.
<DT><B>RPC2_SEFAIL2</B><DD><P>The associated side effect routine indicated a serious failure.  Future calls on this connection will fail too.
<DT><B>RPC2_FAIL</B><DD><P>Other assorted calamities,
</DL>
<H3>Description:</H3>

<P>Initiates the side effect specified by SDesc on ConnHandle.  The call does not wait for the completion of the side effect.
If you need to know what happened to the side effect, do a RPC2_CheckSideEffect call with appropriate flags.
<P>
<P>
<P>
<H3>RPC2_CheckSideEffect -- <EM>Check progress of side effect</EM></H3>

<P>
<H3>Call:        <EM>int32_t RPC2_CheckSideEffect</EM>(<B>in</B> RPC2_Handle ConnHandle, <B>inout</B>  *SDesc, <B>in</B> long Flags)  </H3>

<H3>Parameters:</H3>

<P>
<DL>
<DT><B>ConnHandle</B><DD><P>The connection on which the side effect has been initiated.
<DT><B>SDesc</B><DD><P>The side effect descriptor as it was returned by the previous RPC2_InitSideEffect
or RPC2_CheckSideEffect call on ConnHandle.  On output, the status fields are filled in.
<DT><B>Flags.</B><DD><P>Specifies what status is desired.  This call will block until the requested status is available.
This is a bit mask, with RPC2_GETLOCALSTATUS and RPC2_GETREMOTESTATUS bits indicating local and remote status.
A Flags value of 0 specifies a polling status check: no blocking will occur and the currently known local
and remote status will be returned.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>The requested status fields have been made available.
<DT><B>RPC2_NOTSERVER</B><DD><P>No side effect is ongoing on ConnHandle.
<DT><B>RPC2_SEFAIL1</B><DD><P>The associated side effect routine indicated a nonfatal failure.  Future calls on this connection will work.
<DT><B>RPC2_SEFAIL2</B><DD><P>The associated side effect routine indicated a serious failure.  Future calls on this connection will fail too.
<DT><B>RPC2_FAIL</B><DD><P>Other assorted calamities.
</DL>
<H3>Description:</H3>

<P>Checks the status of a previously initiated side effect.
This is a (potentially) blocking call, depending on the specified flags.
<P>
<P>
<P>
<P>
<H2><A NAME="ss4.3">4.3 Miscellaneous Calls</A>
</H2>

<P>
<H3>RPC2_Init -- <EM>Perform runtime system initialization</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_Init</EM>(<B>in</B> char *VersionId, <B>in</B> long Options, <B>in</B> RPC2_PortalIdent *PortalList[], <B>in</B> long HowManyPortals,  <B>in</B> long RetryCount, <B>in</B> struct timeval *KeepAliveInterval)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>VersionId</B><DD><P>Set this to the constant RPC2_VERSION.  The current value of this string  constant must be identical to the value at the time the client runtime system was compiled.
<DT><B>Options</B><DD><P>Right now there are no options.
<DT><B>PortalList</B><DD><P>An array of unique network addresses within this machine, on which requests can be listened for, and to which responses to
outgoing calls can be made.  In the Internet domain this translates into a port number or a symbolic name
that can be mapped to a port number.   You need to specify this parameter even if you are only going to be a
client and not export any subsystems.  A value of NULL will cause RPC2 to select an arbitrary, nonassigned portal.
<DT><B>HowManyPortals</B><DD><P>Specifies the number of elements in the array PortalList.
<DT><B>RetryCount</B><DD><P>How many times to retransmit a packet before giving up all hope of receiving acknowledgement of its receipt.  Should be in the range 1 to 30. Use a value of -1 to obtain the  default.
<DT><B>KeepAliveInterval</B><DD><P>How often to probe a peer during a long RPC call.  This value is also used to calculate the retransmission intervals when packet loss is suspected by the RPC runtime system.  Use NULL to obtain the default.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>All went well, 
<DT><B>RPC2_FAIL</B><DD><P>Unable to initialize client. Check for bogus parameter values.
<DT><B>RPC2_WRONGVERSION</B><DD><P>The header file and the library have different versions.  This should never happen in a properly administered system.
<DT><B>RPC2_LWPNOTINIT</B><DD><P>The LWP package has not been properly initialized.  Be sure to call LWP(Init( before calling RPC2_Init(.
<DT><B>RPC2_BADSERVER</B><DD><P>The PortalList field specifies an invalid address.
<DT><B>RPC2_DUPLICATESERVER</B><DD><P>An entry in PortalList specifies an address which is already in use on this machine.
<DT><B>RPC2_SEFAIL1</B><DD><P>The associated side effect routine indicated a minor failure.
<DT><B>RPC2_SEFAIL2</B><DD><P>The associated side effect routine indicated a serious failure.
</DL>
<H3>Description:</H3>

<P>Initializes the RPC runtime system in this process.  This call should be made before any other call in this package is made.  It should be preceded by an initialization call to the LWP package and a call to SE(SetDefaults) with InitialValues as argument. If you get a wrong version indication, obtain a consistent version of the header files and the RPC runtime library and recompile your code. Note that this call incorporates a call to initialize IOMGR. RetryCount and KeepAliveInterval together define what it means for a remote site to be dead or unreachable.  Packets are retransmitted at most RetryCount times until positive acknowledgement of their receipt is received.  This is usually piggy-packed with useful communication, such as the reply to a request.  The KeepAliveInterval is used for two purposes: to determine how often to check a remote site
during a long RPC call, and to calculate the intervals between the RetryCount retransmissions of a packet.
The RPC runtime system guarantees detection of remote site failure or network partition within a time
period in the range  KeepAliveInterval to twice KeepAliveInterval.  See Chapter 
<A HREF="rpc2_manual-15.html#RetryChapter">XXX</A> for further information on the retry algorithm.
<P>Remember to activate each side effect, XXX, that you are interested in by invoking the
corresponding XXX()Activate () call, prior to calling RPC2_Init.
<P>You may get a warning about SOux[ ]GREEDY being undefined, if your kernel does not have an ITC bug fix.  RPC2 will still work but may be slower and more likely to drop connections during bulk transfer.  This is because of insufficient default packet buffer space  within the Unix kernel.
<P>
<P>
<H3>RPC2_Unbind -- <EM>Terminate a connection by client or server</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_Unbind</EM>(<B>in</B> RPC2_Handle ConnHandle)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>ConnHandle</B><DD><P>identifies the connection to be terminated,
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>All went well.
<DT><B>RPC2_NOCONNECTION</B><DD><P>ConnHandle is bogus.
<DT><B>RPC2_SEFAIL1</B><DD><P>The associated side effect routine indicated a minor failure.
<DT><B>RPC2_SEFAIL2</B><DD><P>The associated side effect routine indicated a serious failure.
<DT><B>RPC2_FAIL</B><DD><P>Other assorted calamities.
</DL>
<H3>Description</H3>

<P>Removes the binding associated with the specified connection.  Normally
a higher-level  disconnection should be done by an RPC just prior to
this call.  Note that this call may be used both by a server and a client, and that
no client/server communication occurs: the unbinding is unilateral.
<P>
<P>
<H3>RPC2_AllocBuffer -- <EM>Allocate a packet buffer</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_AllocBuffer</EM>(<B>in</B> long MinBodySize, <B>out</B> RPC2_PacketBuffer **Buff)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>MinBodySize</B><DD><P>Minimum acceptable body size for the packet buffer.
<DT><B>Buff</B><DD><P>Pointer to the allocated buffer.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>Buffer has been allocated and *Buff points to it.
<DT><B>RPC2_FAIL</B><DD><P>Could not allocate a buffer of requested size.
</DL>
<H3>Description:</H3>

<P>Allocates a packet buffer of at least the requested size.  The BodyLength field in the header of the
allocated packet is set to MinBodySize.  The RPC runtime system maintains its own free list of buffers.
Use this call in preference to malloc ().
<P>
<H3>RPC2_FreeBuffer -- <EM>Free a packet buffer</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_FreeBuffer</EM>(<B>inout</B> RPC2_PacketBuffer **Buff)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>Buff</B><DD><P>Pointer to the buffer to be freed. Set to NULL by the call.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>Buffer has been freed. *Buff has been set to NULL.
<DT><B>RPC2_FAIL</B><DD><P>Could not free buffer.
</DL>
<H3>Description:</H3>

<P>Returns a packet buffer to the internal free list.  Buff is set to NULL specifically
to simplify locating bugs in buffer usage.
<P>
<P>
<H3>RPC2_GetPrivatePointer -- <EM>Obtain private data mapping for a connection</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_GetPrivatePointer</EM>(<B>in</B> RPC2_Handle WhichConn, <B>out</B> char **PrivatePtr)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>WhichConn</B><DD><P>Connection whose private data pointer is desired.
<DT><B>PrivatePtr</B><DD><P>Set to point to private data.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>*PrivatePtr now points to the private data associated with this connection.
<DT><B>RPC2_FAIL</B><DD><P>Bogus connection specified.
</DL>
<H3>Description:</H3>

<P>Returns a pointer to the private data associated with a connection.  No attempt is made to validate
this pointer.
<P>
<H3>RPC2_SetPrivatePointer -- <EM>Set private data mapping for a connection</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_SetPrivatePointer</EM>(<B>in</B> RPC2_Handle WhichConn, <B>in</B> char *PrivatePtr)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>WhichConn</B><DD><P>Connection whose private data pointer is to be set.
<DT><B>PrivatePtr</B><DD><P>Pointer to private data.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>Private pointer set for this connection.
<DT><B>RPC2_FAIL</B><DD><P>, Bogus connection specified.
</DL>
<H3>Description:</H3>

<P>Sets the private data pointer associated with a connection.  No attempt is made to validate this pointer.
<P>
<H3>RPC2_GetSEPointer -- <EM>Obtain per-connection side-effect information</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_GetSEPointer</EM>(<B>in</B> RPC2_Handle WhichConn, <B>out</B> char **SEPtr)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>WhichConn</B><DD><P>Connection whose side-effect data pointer is desired.
<DT><B>SEPtr</B><DD><P>Set to point to side-effect data.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>*SEPtr now points to the side effect data associated with this connection.
<DT><B>RPC2_FAIL</B><DD><P>Bogus connection specified.
</DL>
<H3>Description</H3>

<P>Returns a pointer to the side effect data associated with a connection.  No attempt is made to validate this pointer.  This call is should only by the side effect routines, not by clients.
<P>
<P>
<H3>RPC2_SetSEPointer -- <EM>Set per-connection side-effect connection</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_SetSEPointer</EM>(<B>in</B> RPC2_Handle WhichConn, <B>in</B> char *SEPtr)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>WhichConn</B><DD><P>Connection whose side effect pointer is to be set.
<DT><B>SEPtr</B><DD><P>Pointer to side effect data.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>Side effect pointer set for this connection.
<DT><B>RPC2_FAIL</B><DD><P>Bogus connection specified.
</DL>
<H3>Description:</H3>

<P>Sets the side effect data pointer associated with a connection.  No attempt is made to validate this pointer.  This call should only be used by the side effect routines, not by clients.
<P>
<H3>RPC2_GetPeerInfo -- <EM>Obtain miscellaneous connection information</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_GetPeerInfo</EM>(<B>in</B> RPC2_Handle WhichConn, <B>out</B> RPC2_PeerInfo *PeerInfo)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>WhichConn</B><DD><P>Connection whose peer you wish to know about.
<DT><B>PeerInfo</B><DD><P>Data structure to be filled.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>Peer information has been obtained for this connection.
<DT><B>RPC2_FAIL</B><DD><P>Bogus connection specified.
</DL>
<H3>Description:</H3>

<P>Returns the peer information for a connection.  Also returns other miscellaneous connection-related information, such as the securrity level in use. This information may be used by side-effect routines or high-level server code to perform RPC bindings in the opposite direction. The RemoteHandle and Uniquefier  information are  useful as end-to-end identification between client code and server code.
<P>
<P>LamportTime.
RPC2_LamportTime, Get Lamport time.
,
Returns the current Lamport time.  Bears no resemblance to the actual time of day. Each call
is guaranteed to return a value at least one larger than the preceding call.  Every RPC packet sent
and received by this Unix process has a Lamport time field in its header.  The value returned by this
call is guaranteed to be  greater than any  Lamport time field received or sent before now.  Useful
for generating unique timestamps in a distributed system.
<P>
<P>
<H3>RPC2_DumpState -- <EM>Dump internal RPC state</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_DumpState</EM>(<B>in</B> FILE *OutFile, <B>in</B> long Verbosity)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>OutFile</B><DD><P>File on which the trace is to be produced.  A value of NULL implies stdout.
<DT><B>Verbosity</B><DD><P>Controls the amount of information dumped.  Right now two values 0 and 1 are meaningfull.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>The dump has been produced.
</DL>
<H3>Description:</H3>

<P>You should typically call this routine after calling RPC(DumpTrace).
<P>
<H3>RPC2_InitTraceBuffer -- <EM>Set trace buffer size</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_InitTraceBuffer</EM>(<B>in</B> long HowMany)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>HowMany</B><DD><P>How many entries the trace buffer should have.  Set it to zero to delete trace buffer.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>The trace buffer has been adjusted appropriately.
</DL>
<H3>Description:</H3>

<P>Allows you to create and change the trace buffer at runtime.  All existing trace entries are lost.
<P>
<H3>RPC2_DumpTrace -- <EM>Print a trace of recent RPC calls and packets received</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_DumpTrace</EM>(<B>in</B> FILE *OutFile, <B>in</B> long HowMany)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>OutFile</B><DD><P>File on which the trace is to be produced.  A value of NULL implies stdout.
<DT><B>HowMany</B><DD><P>The HowMany most recent trace entries are printed.  A value of NULL implies as many trace entries
as possible.  Values larger than TraceBufferLength specifed in RPC2_Init are meaningless.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>The requested trace has been produced.
<DT><B>RPC2_FAIL</B><DD><P>The trace buffer had no entries.
</DL>
<H3>Description:</H3>

<P>Note that it is not necessary for RPC2_Trace to be currently set.  You can collect a trace and defer calling RPC2_DumpTrace until a convenient time.  This call does not alter the current value of RPC2_Trace.
<P>
<H3>RPC2_SetLog -- <EM>Set the logfile and debug level to use</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>void RPC2_SetLog</EM>(<B>in</B> FILE * file, <B>int level</B>)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>file</B><DD><P>File to send trace dumps and log entries to.
<DT><B>level</B><DD><P>Value to set the debug level to.
</DL>
<H3>Completion Codes:</H3>

<P><EM>None.</EM>
<H3>Description:</H3>

<P>The debug level defines the verbosity of trace and log entries that will be written by a RPC2_DumpTrace.
<P>
<P>
<H3>XXX_SetDefaults -- <EM>Set an SE initializer to its default values</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int XXX_SetDefaults</EM>(<B>out</B> XXX_Initializer *Initializer)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>Initializer</B><DD><P>, Initializer for side effect XXX which you wish to set to default values.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>Initialization Succeeded.
</DL>
<H3>Description:</H3>

<P>Each side effect type, XXX,  defines an initialization structure type, XXX()Initializer,and an initialization routine, XXX()SetDefaults ().
<P>
<P>A typical initialization sequence consists of the following: for each side effect, XXX, that you care about,
<OL>
<LI> declare a local variable of type XXX()Initializer.</LI>
<LI> call XXX_SetDefaults () with this local variable as argument.</LI>
<LI> selectively modify those initial values you care about in the local variable, and</LI>
<LI> call XXX_Activate () with this local variable as argument.
end(format</LI>
</OL>
        
Finally call RPC2_Init.
<P>
<P>This allows you to selectively set parameters of XXX without having to know the  proper values for all of the possible parameters. Alas, if only C allowed initialization in type declarations  this routine would be unnecessary.
<P>
<P>
<H3>XXX_Activate -- <EM>Activates a side effect type and initializes it</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int XXX_Activate</EM>(<B>in</B> XXX_Initializer *Initializer)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>Initializer</B><DD><P>Initializer for side effect XXX.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>Activation Succeeded.     
</DL>
<H3>Description:</H3>

<P>Activates side effect XXX.  Code corresponding to this side effect will not be linked in otherwise. See comment for XXX()SetDefaults () for further details.
<P>
<H3>RPC2_ErrorMsg -- <EM>Describe RPC2 error code</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>char * RPC2_ErrorMsg</EM>(<B>in</B> long ReturnCode)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>ReturnCode</B><DD><P>Error code returned by any RPC2 call.,
</DL>
<H3>Description:</H3>

<P>Converts ReturnCode into a string that can be used for printing error messages.  Note that this is the only RPC2 call that returns a non-integer value.
<P>
<P>
<P>
<H3>RPC2_SetColor -- <EM>Set the color of a connection</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_SetColor</EM>(<B>in</B> RPC2_Handle *Conn, <B>in</B> RPC2_Integer NewColor)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>Conn</B><DD><P>Connection whose color is to be changed.
<DT><B>NewColor</B><DD><P>The lowest-order byte of this value is used as the new color for this connection.
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS</B><DD><P>The connection has been colored as requested.
<DT><B>RPC2_NOCONNECTION</B><DD><P>Connection specified is bogus.
</DL>
<H3>Description:</H3>

<P>A color is an integer between 0 and 255 that is associated with a connection.  When a packet is sent out on a connection, it acquires this color.  Colors have no implicit significance to RPC2.  But they can be used by other packages such as the Coda failure emulator package cite[CodaManual] to selectively induce failures.  For example, in debugging an implementation of a two-phase commit protocol, one needs to test the situation where a failure occurs between the two phases. This situation can be detected by the failure emulator by using packets of different colors for the different phases.  A change in color of a connection takes effect with the next packet that is sent out.
<P>
<P>
<H3>RPC2_GetColor -- <EM>Obtain current color of a connection</EM></H3>

<P>
<H3>Call:</H3>

<P><EM>int RPC2_GetColor</EM>(<B>in</B> RPC2_Handle *Conn, <B>out</B> RPC2_Integer *Color)
<H3>Parameters:</H3>

<P>
<DL>
<DT><B>Conn.</B><DD><P>Connection whose color is to be obtained.
<DT><B>Color,</B><DD><P>Current color of connection./
</DL>
<H3>Completion Codes:</H3>

<P>
<DL>
<DT><B>RPC2_SUCCESS.</B><DD><P>Color obtained.
<DT><B>RPC2_NOCONNECTION.</B><DD><P>Conn is bogus.
</DL>
<H3>Description:</H3>

<P>Useful if a package using RPC2 wants to save current color, set new color, then restore original color.
<P>
<P>
<P>
<P>
<P>
<P>
<P>
<P>  
<HR>
<A HREF="rpc2_manual-5.html">Next</A>
<A HREF="rpc2_manual-3.html">Previous</A>
<A HREF="rpc2_manual.html#toc4">Contents</A>
</BODY>
</HTML>