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
