Adding New Kinds of Side Effects
This chapter is not intended for the average user. Rather, it is meant for a system programmer who intends to add support for a new kind of side effect. To do this, the system programmer must do the following:
-
Define an appropriate side effect descriptor, add it to the header file se.h and to the discriminated union in the definition of
SE_Descriptor
. -
Define an appropriate Initializer structure and a corresponding component in the
SE_Initializer
structure in filese.h
. -
Write a set of routines corresponding to each of the
SE_XXX
routines described in the following pages. This includes aSE_Activate()
routine to enlarge the table in file se.c, and aSE_SetDefaults()
routine to deal withSE_Initializer
structures.
Usage Notes
-
You will modify two RPC2 files (se.h and se.c), and add one more file containing the code implementing your new side effect. Also modify the Makefile to compile and link in your new file.
-
Client and server programs will cause the appropriate side effect routines to be linked in by calling the appropriate
SE_Activate()
for each side effect they are interested in. Note that these calls must precedeRPC_Init()
. -
None of these procedures will be called for a connection, if the
RPC2_Bind
that created the connection specified NULL for the SideEffectType parameter. -
In each of the calls, ConnHandle is the handle identifying the connection on which the side effect is desired. It is not likely to be a small integer. Since you cannot access the internal data structures of the RPC2 runtime system, you cannot use this for much. It is passed to you primarily for identification.
-
You can use
RPC2_GetSEPointer()
andRPC2_SetSEPointer()
to associate per-connection side effect data structures. -
Use
RPC2_GetPeerInfo()
to get the identity of a connections peer. -
Three return codes: RPC2_SUCCESS and RPC2_SEFAIL1 and RPC2_SEFAIL2 are recognized for each of the calls. The successful return causes the RPC runtime system to resume normal execution from the point at which the side effect routine was invoked. The failure returns abort the call at that point and returns RPC2_SEFAIL1 or RPC_SEFAIL2 to the client or server code that invoked the RPC system call. RPC2_SEFAIL1 is an error, but not a fatal error. Future RPC calls on this connection will still work. RPC2_SEFAIL2 is a fatal error.
Entry Point Templates
SE_Init
int SE_Init(void);
Called just prior to return from RPC2_Init
.
- Completion Codes:
-
RPC2_SUCCESS
-
RPC2_SEFAIL1
-
RPC2_SEFAIL2
SE_Bind1
int SE_Bind1(
in RPC2_Handle ConnHandle,
in RPC2_CountedBS *ClientIdent
);
Called on RPC2_Bind
on client side. The call is made just prior to sending
the first connection-establishment packet to the server. The connection
establishment is continued only if RPC2_SUCCESS is returned.
- Parameters
-
ConnHandle
-
Handle identifying the connection on which the side effect is desired.
-
ClientIdent
-
The client identifier passed in the
RPC2_Bind
call.
- Completion Codes:
-
RPC2_SUCCESS
-
RPC2_SEFAIL1
-
RPC2_SEFAIL2
SE_Bind2
int SE_Bind2(
in RPC2_Handle ConnHandle,
in struct timeval *BindTime
);
Called on RPC2_Bind
on client side. The call is made just after the
connection is successfully established, before control is returned to the
caller. BindTime
is the amount of time the bind took because of the network.
If SE_Bind2
returns RPC2_SEFAIL1
or RPC2_SEFAIL2
, that code is returned
as the result of the RPC2_Bind
. Otherwise the usual code is returned.
- Parameters
-
ConnHandle
-
Handle identifying the connection on which the side effect is desired.
-
BindTime
-
The amount of time the bind took because of the network.
- Completion Codes:
-
RPC2_SUCCESS
-
RPC2_SEFAIL1
-
RPC2_SEFAIL2
SE_Unbind
int SE_Unbind(in RPC2_Handle ConnHandle);
Called when RPC2_Unbind
is executed on the client or server side. You are
expected to free any side effect storage you associated with this connection,
and to do whatever cleanup is necessary. Note that the connection state is
available to you and is not destroyed until you return RPC2_SUCCESS
.
- Parameters
-
ConnHandle
-
Handle identifying the connection on which the side effect is desired.
- Completion Codes:
-
RPC2_SUCCESS
-
RPC2_SEFAIL1
-
RPC2_SEFAIL2
SE_NewConnection
int SE_NewConnection(
in RPC2_Handle ConnHandle,
in RPC2_CountedBS *ClientIdent
);
Called on RPC2_NewConnection
on server side. The call is made just after the
connection is successfully established, before control is returned to the caller.
- Parameters
-
ConnHandle
-
Handle identifying the connection on which the side effect is desired.
-
ClientIdent
-
The client identifier passed in the
RPC2_Bind
call.
- Completion Codes:
-
RPC2_SUCCESS
-
RPC2_SEFAIL1
-
RPC2_SEFAIL2
SE_MakeRPC2
int SE_MakeRPC2(
in RPC2_Handle ConnHandle,
in SE_Descriptor *SDesc,
in RPC2_PacketBuffer *Reply
);
Called just after Reply
has been received, after decryption and host ordering
of header fields. Examine the SideEffectFlags and SideEffectDataOffset fields
to determine if there is piggy-backed side effect data for you in Reply. If
you remove data, remember to update the BodyLength field of the header in
Reply
. SDesc points to the side effect descriptor. You will probably wish
to fill in the status fields of this descriptor. If the MakeRPC call fails for
some reason, this routine will be called with a Reply
of NULL. This allows
you to take suitable cleanup action.
- Parameters
-
ConnHandle
-
Handle identifying the connection on which the side effect is desired.
-
SDesc
-
The side effect descriptor.
-
Reply
-
The reply packet.
- Completion Codes
-
RPC2_SUCCESS
-
RPC2_SEFAIL1
-
RPC2_SEFAIL2
SE_GetRequest
int SE_GetRequest(
in RPC2_Handle ConnHandle,
inout RPC2_PacketBuffer *Request
);
Called just prior to successful return of Request to the server. You should look at Request, extract side effect data if any, modify the header fields appropriately.
Called after a request has been completely filled, just prior to network
ordering of header fields, encryption and transmission. You may use the Prefix
information to determine the actual size of the buffer corresponding to
*RequestPtr
. If you add data, remember to update the BodyLength field of the
header in *RequestPtr
. You also probably wish to update the SideEffectFlags
and SideEffectDataOffset fields of the header. SDesc points to the side effect
descriptor passed in by the client.
If you need more space than available in the buffer passed to you, you may allocate a larger packet, copy the current contents and add additional data. Return a pointer to the packet you allocated in RequestPtr: this is the packet that will actually get sent over the wire. DO NOT free the buffer pointed to by RequestPtr initially. If you allocate a packet, it will be freed immediately after successful transmission.
- Parameters
-
ConnHandle
-
Handle identifying the connection on which the side effect is desired.
-
Request
-
The request packet.
- Completion Codes
-
RPC2_SUCCESS
-
RPC2_SEFAIL1
-
RPC2_SEFAIL2
SE_InitSideEffect
int SE_InitSideEffect(
in RPC2_Handle ConnHandle,
inout SE_Descriptor *SDesc
);
Called when the server does an RPC2_InitSideEffect
call. You will probably
want to examine some fields of SDesc and fill in some status-related fields.
Note that there is no requirement that you should actually initiate any side
effect action. You may choose to piggy back the side effect with the reply
later.
- Parameters
-
ConnHandle
-
Handle identifying the connection on which the side effect is desired.
-
SDesc
-
The side effect descriptor.
- Completion Codes
-
RPC2_SUCCESS
-
RPC2_SEFAIL1
-
RPC2_SEFAIL2
SE_CheckSideEffect
int SE_CheckSideEffect(
in RPC2_Handle ConnHandle,
inout SE_Descriptor *SDesc,
in long Flags
);
Called when the server does an RPC2_CheckSideEffect
call. The Flags
parameter will specify what status is desired. You may have to actually
initiate the side effect, depending on the circumstances.
- Parameters
-
ConnHandle
-
Handle identifying the connection on which the side effect is desired.
-
SDesc
-
The side effect descriptor.
-
Flags
-
The flags.
- Completion Codes
-
RPC2_SUCCESS
-
RPC2_SEFAIL1
-
RPC2_SEFAIL2
SE_SendResponse
int SE_SendResponse(
in RPC2_Handle ConnHandle,
inout RPC2_PacketBuffer **ReplyPtr
);
Called just before the reply packet is network-ordered, encrypted and transmitted. You may wish to add piggy-back data to the reply; modify the BodyLength field in that case. If you are not piggybacking data, make sure that the side effect is complete before returning from this call.
If you need more space than available in the buffer passed to you, you may allocate a larger packet, copy the current contents and add additional data. Return a pointer to the packet you allocated in ReplyPtr: this is the packet that will actually get sent over the wire. DO NOT free the buffer pointed to by ReplyPtr initially. If you allocate a packet, it will be freed immediately after successful transmission.
- Parameters
-
ConnHandle
-
Handle identifying the connection on which the side effect is desired.
-
ReplyPtr
-
The reply packet.
- Completion Codes
-
RPC2_SUCCESS
-
RPC2_SEFAIL1
-
RPC2_SEFAIL2
SE_PrintSEDescriptor
int SE_PrintSEDescriptor(
in SE_Descriptor *SDesc,
in FILE *outFile
);
Called when printing debugging information. You should print out SDesc, suitably formatted, on outFile.
- Parameters
-
SDesc
-
The side effect descriptor.
-
outFile
-
The output file.
- Completion Codes
-
RPC2_SUCCESS
-
RPC2_SEFAIL1
-
RPC2_SEFAIL2
SE_SetDefaults
int SE_SetDefaults(
out XXX_Initializer *SInit
);
Called to set SInit to appropriate default values.
- Parameters
-
SInit
-
The initializer.
- Completion Codes
-
RPC2_SUCCESS
-
RPC2_SEFAIL1
-
RPC2_SEFAIL2
SE_Activate
int SE_Activate(
in XXX_Initializer *SInit
);
Called to activate this side effect type. The body of this procedure should
allocate and fill in a routine vector in the side effect table in file se.c
.
It should also obtain its initialization parameters from SInit.
- Parameters
-
SInit
-
The initializer.
- Completion Codes
-
RPC2_SUCCESS
-
RPC2_SEFAIL1
-
RPC2_SEFAIL2