mirror of
https://github.com/brazilofmux/tinymux
synced 2026-08-13 00:23:11 -04:00
149 lines
5.8 KiB
Text
149 lines
5.8 KiB
Text
I. Summary.
|
|
|
|
Custom marshaling uses mux_IMarshal to turn an interface pointer in one
|
|
process into a buffer that another process can use to create a proxy. As a
|
|
side-effect of doing this, a new association between proxy and server is
|
|
created.
|
|
|
|
How the request to create a server is propagated from client to server, the
|
|
communication mechanism, and how new associations are created is much less
|
|
specified. These could be anything, but our design needs to be more specific.
|
|
|
|
Our approach to the design will take two steps:
|
|
|
|
1. Ignore the communication channel for a moment by going through the
|
|
marshaling steps within the same process. The interfaces for doing this
|
|
must use only fundamental data types -- no interface pointers.
|
|
|
|
2. Assume when the communication channel is first established, an instance
|
|
of these components and all the associations between them exist a priori.
|
|
This first connection is not created. It simply exists.
|
|
|
|
|
|
II. Design Increments.
|
|
|
|
A. Ignore the real channel.
|
|
|
|
i. Sequence.
|
|
|
|
- Call QueryInterface() and get the object's mux_IMarshal interface.
|
|
- Call mux_IMarshal::GetUnmarshalClass() to get the proxy CID.
|
|
- Call mux_IMarshal::MarshalInterface().
|
|
- This allocates a buffer and sets up a callback function. A pointer to
|
|
both are included in the marshaled interface packet.
|
|
- mux_CreateInstance the proxy with the proxy CID.
|
|
- Get the proxy's mux_IMarshal interface.
|
|
- Call mux_IMarshal::UnmarshalInterface to obtain the proxy interface.
|
|
- The proxy places parameters as necessary in the buffer and calls the
|
|
'SendReceive' callback function.
|
|
|
|
ii. Interfaces.
|
|
|
|
interface mux_IBootstrap : public mux_IUknown
|
|
{
|
|
(MUX_CID cidProxy, Custom Marshal Data) RemoteCreateInstance(MUX_CID cid, MUX_IID iid);
|
|
};
|
|
|
|
B. A priori setup.
|
|
|
|
i. Sequence.
|
|
|
|
- Setup channel 0 to listen for call frames. This is the a priori
|
|
channel.
|
|
- When a call frame to channel 0 is received, it will contain cid and iid.
|
|
Create the requested object, and get its mux_IMarshal interface. Since
|
|
we are using custom marshaling, we assume the mux_IMarshal interface
|
|
must exist.
|
|
- Get the proxy CID.
|
|
- mux_IMarshal::MarshalInterface() allocates a new channel (e.g., 1)
|
|
and sets up a callback function to receive data from that channel.
|
|
- The interface pointer for the created object is saved as a channel
|
|
attribute.
|
|
- The allocated channel number is included in the Custom Marshal Data.
|
|
- A return frame is constructed which includes the proxy CID and the new
|
|
channel number. The ToChannel of this return frame is 0. The new
|
|
channel number is contained in the Custom Marshaled Data.
|
|
- mux_CreateInstance the proxy with the proxy CID.
|
|
- Call mux_IMarshal::UnmarshalInterface with the new channel number.
|
|
- Depending on how the low-level transport is implemented, it may need the
|
|
new channel number. The proxy would inform the lower-level of the new
|
|
channel at this time.
|
|
- The proxy is now able to communicate with its component.
|
|
|
|
Notice that the receiver assigns the channel number. The sender and
|
|
receiver always use the receiver-assigned channel number. The two
|
|
processes maintain their channel numbers indepdendently. For example,
|
|
they could both assign channel 10 to different associations. Channel 10
|
|
in netmux would have nothing to do with channel 10 in the stubslave.
|
|
|
|
A return frame should necessarily match the last outstanding call frame.
|
|
|
|
This design does not support Message Frames to callers. There's no
|
|
associated function to handle an unexpected incoming frame. Only callees
|
|
can receive Message Frames.
|
|
|
|
C. Standard Marshaling.
|
|
|
|
As discussed above, while custom marshaling leaves the transport details
|
|
out, a minimum implementation across a Unix pipe requires channels and a
|
|
callback function on the callee side.
|
|
|
|
We can implement standard marshaling on top of this using one callback
|
|
function for the stub manager, and there needs to be only one stub
|
|
manager. The stub manager is part of the standard marshaling, there is
|
|
only one, and it isn't used by anyone else directly.
|
|
|
|
One could argue that either type of marshaling can be built on top of the
|
|
other, but it is helpful at this stage of development to see that our
|
|
implementation of custom marshaling supports interfaces while depending
|
|
only on transport-related function calls. Likewise, our implementation
|
|
of standard marshaling provides a transport-independent framework while
|
|
depending on an internal instance of custom marshaling.
|
|
|
|
In other words, we enable others to marshal their interfaces with our
|
|
custom or standard marshaling interfaces, but we are using custom marshaled
|
|
interfaces ourselves to provide standard marshaling, we can't share it,
|
|
and we don't need to share it.
|
|
|
|
|
|
III. Packet Format.
|
|
|
|
A. Call Frame.
|
|
|
|
CallMagic 0xC39B71F9
|
|
Length 0x--------
|
|
ToChannel 0x--------
|
|
Data..................
|
|
......................
|
|
......................
|
|
EndMagic 0x27118B26
|
|
|
|
B. Return Frame.
|
|
|
|
ReturnMagic 0x35972DD0
|
|
Length 0x--------
|
|
ToChannel 0x--------
|
|
Data..................
|
|
......................
|
|
......................
|
|
EndMagic 0x27118B26
|
|
|
|
C. Message Frame (non-blocking).
|
|
|
|
MsgMagic 0xF69E1836
|
|
Length 0x--------
|
|
ToChannel 0x--------
|
|
Data..................
|
|
......................
|
|
......................
|
|
EndMagic 0x27118B26
|
|
|
|
D. Disconnect Frame.
|
|
|
|
DiscMagic 0x960AA381
|
|
Length 0x--------
|
|
ToChannel 0x--------
|
|
Data..................
|
|
......................
|
|
......................
|
|
EndMagic 0x27118B26
|