[comp.sys.amiga] IPC: Messages

pete@violet.berkeley.edu (Pete Goodeve) (03/15/88)

Sorry to keep banging away at IPC message structure, but I just feel that a
lot of people aren't taking a wide enough look at things. There are several
perhaps subtle points that I think we have to keep in mind when designing a
general format.


ReplyMessages
_____________

Many want to insist that ALL messages should be replied, but this really
doesn't work.  You can't always expect the client to still be around when
the message has been processed.  A likely case is a program that wants to
send messages to the shell that invoked it, which won't resume processing
until the sending program terminates. Also, you might want to "plant" a
port and go away, leaving it without an owner for a while, letting it
collect messages that will be handled when the owner returns to memory.

More urgently (for those who think the previous scenarios too fanciful), if
you are sending MIDI messages or some other time-critical type of data, the
last thing you want is to burden yourself with replying and handling
replies.  (FreeMem probably takes as much time as Replying, but it doesn't
involve the scheduler, and anyway in a situation like that you would quite
likely have fixed-size messages that the server could in turn pass on
somewhere else.)

My philosophy is to try and hammer out a protocol that won't prove
restrictive for future applications and extensions, so I think we have to
allow for the possibility that a client won't want its message back.  A
server therefore must be prepared to deallocate that memory block if no
ReplyPort is given.


Data ownership and pointers
___________________________

This is linked to the previous topic, because if a message always returns
to its origin we can assume that it owns all the data it references.  If we
pass a message one way only, though, the server becomes responsible for the
memory involved.

This means we must take more care with pointers in this situation.  Any
data that is pointed to must become the "property" of the server as well as
the message itself, and will be deallocated along with the message.
It MUST of course have been obtained with AllocMem by the client.  Things
are a lot simpler if the message block itself is the only memory involved;
then we can just use the mn_Length field (adjusted suitably) for FreeMem.
This is why I think we shouldn't always use pointers where they otherwise
might look appropriate.  I don't think we can make any general rule here:
just be aware of the requirements of a particular application.

A specially awkward case is the ln_Name field of a message.  If we use this
as a pointer to an identifying string we could get a little stuck.  Unless
we followed the cumbersome route of allocating space for the name string
(when no doubt we would rather point directly to a string constant), the
name would go away with the client.  For this reason I suggested that it
probably was NOT a good idea to use this as a pointer, and that would leave
it free as our ID word.  I was immediately flamed for this, so perhaps to
keep everyone happy we should just ignore this field: anything it points
to is not part of the message space (and may no longer exist).


Altering message contents
_________________________

It has also been suggested that message contents shouldn't be changed
except for a status word, but again this is unnecessarily restricting the
ways a message might be used.  After all, one of its main purposes is to
request and return data!  A client should expect that any part of the
message data area may have been rewritten (meaningfully of course!) on
reply.

The only item that should absolutely NOT be altered is the length field,
and I can't see any reason to muck with the ReplyPort. Probably the ID word
should be inviolate also; there might be some situations though where you
would want to mark a change in structure by a change in ID.


"Serial" message contents
_________________________

One of the major advantages of messages is that they require little
overhead to pass.  We should therefore avoid formats that add to the
overhead unless they are particularly appropriate for that task.  My
picture of the ideal message is a simple fixed structure that gives you
direct access to any item within it, and my reaction to a couple of the
recent proposals is that they rather violate this principle unnecessarily
by using multiple chunks that can only be reached by scanning from the
beginning.

There's nothing at all inherently wrong with multiple chunks, but because
most applications won't need them I don't think they ought to be part of
the fundamental IPC message structure -- unnecessary overhead again.  If
they are used in a particular format, the first part of the data section
should be a set of pointers to the individual blocks, so access is direct
rather than sequential.


Message status
______________

I touched on this in another article, but I include it here for
completeness.  It's a good idea to keep the generic "outcome" report in a
replied message separate from application specific status flags.  There are
really very few possible outcomes, which I would flag as follows in the
ln_Type byte:

    NT_MESSAGE      --  as originally sent by the client
    NT_REPLYMSG     --  normal reply after processing
    NT_UNKNOWN      --  (= 0) the server couldn't handle this type
    NT_NOSERVER     --  (new type = 0xFF) returned by a port broker that
                        handles the message in lieu of an owner

If there are any I've left out, there's lots of spare codes, and no real
way any particular choice could conflict with other uses.


Standard IPC Message Format
___________________________

So I come back pretty much to my original absolutely fundamental IPC
message format, on which we can build applications without getting
hamstrung by hidden assumptions.

        struct IPCMessage {
            struct Message ipc_Msg;
            ULONG   ipc_ID; /* four characters or integer < 1<<24 */
            /* data follows -- structure determined by ipc_ID */
        };

All entries in the ipc_Msg structure must be filled in appropriately,
except that ln_Name should normally be NULL.  If ReplyPort is NULL, the
server will deallocate the message up to the end of the data as indicated
by ipc_Msg.mn_Length.

Publicly defined ID codes will have a non-zero ASCII character in the first
byte.  Codes agreed on privately between client and server should have the
high byte zero.  Publicly defined IDs to be shared between applications
have associated unambiguous data structure definitions that anyone can use
to get at the data.

Then we can consider a common extension that would be shared by a number of
IDs (swiped totally without shame from Peter da Silva's BRWS structure --
only the names have been changed to protect something or other...):

        struct StdIPCMessage {
            struct Message ipc_Msg;
            ULONG   ipc_ID;
            ULONG   ipc_Status;  /* application specific */
            ULONG   ipc_Func;    /* specific nature of this message */
            SHORT   ipc_Entries; /* number of items following */
            APTR ipc_Items[];    /* data items OR pointers to items
                                    depending on the ID */
            /* Any data items pointed to will follow message AND be
            included in the mn_Length */
        };

I've suggested a two level naming structure here: ipc_ID and ipc_Func.
ipc_ID is the primary identification of the class and structure of the
message; ipc_Func is used to break it down into application specific
actions.  In Peter's Browser example, ipc_ID = 'BRWS; and ipc_Func =
'ADDF', 'DELF', and so on.

Note that the ipc_Items array might contain simple long values, or it could
as shown here contain pointers to the actual data items (Peter's
"IPCEntry"s) so we can access them without sequential search.  Such data
items would normally be included in the message block to keep memory
management simple. There might be occasions where they would be external to
the message, but the ID would have to indicate this.

Actually if you look carefully at Peter's Browser structure, although there
are a variable number of entries, the format for each action is strict
enough that you would know where everything was without searching.  You
could do without the pointers in this case (so our only real disparity is
in the function and positioning of the ID words.  Can we get together on
this Peter?)  If the data items were something like IFF chunks, though, I
think the pointer scheme would be well worth the slight extra space.

dillon@CORY.BERKELEY.EDU (Matt Dillon) (03/16/88)

:ReplyMessages
:_____________
:
:Many want to insist that ALL messages should be replied, but this really
:doesn't work.  You can't always expect the client to still be around when

	You are out of your mind.  OF COURSE THE MESSAGES HAVE TO BE REPLIED!
I want to statically allocate my messages.  I want to know when the pointers
I passed are no longer being used.  If you insist that replying messages
would be wasteful, I would like to point out that one can set the replyport
to "call a function" instead of "signal a task", so the guy sending the message
has full control over whether he wants to handle replies or wants to just
FreeMem() the message.

	You are making that assumption that you have thought of everything
anyone will ever want to do.  That is a bad assumption to make.

	As far as the client going away before the message is replied.
Since the client (who sent the message) KNOWS it intends to go away, it
will AllocMem() the message AND replyport, and will turn of PA_SIGNAL when
it leaves... or use a 'standard' sink-null port which deallocates messages
automatically (via the function-call-on-reply mode you can stick ports in).

>My philosophy is to try and hammer out a protocol that won't prove
>restrictive for future applications and extensions, so I think we have to
>allow for the possibility that a client won't want its message back.  A
>server therefore must be prepared to deallocate that memory block if no
>ReplyPort is given.

	See above.  But what you described was *VERY* restrictive.

:A specially awkward case is the ln_Name field of a message.  If we use this
:as a pointer to an identifying string we could get a little stuck.  Unless
:we followed the cumbersome route of allocating space for the name string
:(when no doubt we would rather point directly to a string constant), the
:name would go away with the client.  For this reason I suggested that it
:probably was NOT a good idea to use this as a pointer, and that would leave
:it free as our ID word.  I was immediately flamed for this, so perhaps to
:keep everyone happy we should just ignore this field: anything it points
:to is not part of the message space (and may no longer exist).

	What you do is say "the ln_Name field is not used by the receiver
of the message, but rather is reserved for whatever purpose the client
wishes".

:Message status
:______________
:
:I touched on this in another article, but I include it here for
:completeness.  It's a good idea to keep the generic "outcome" report in a
:replied message separate from application specific status flags.  There are
:really very few possible outcomes, which I would flag as follows in the
:ln_Type byte:
:
:    NT_MESSAGE      --  as originally sent by the client
:    NT_REPLYMSG     --  normal reply after processing
:    NT_UNKNOWN      --  (= 0) the server couldn't handle this type
:    NT_NOSERVER     --  (new type = 0xFF) returned by a port broker that
:                        handles the message in lieu of an owner

	NO NO NO!  the ln_Type field should be used only for NT_MESSAGE
	and NT_REPLYMSG.  Take another byte of your precious message format
	for an error field.  How do you intend to atomically set the message
	type to NT_NOSERVER when ReplyMsg() automatically sticks an
	NT_REPLYMSG in the field???????  

				-Matt

peter@nuchat.UUCP (Peter da Silva) (03/17/88)

In article ... pete@violet.berkeley.edu (Pete Goodeve) writes:
> Many want to insist that ALL messages should be replied, but this really
> doesn't work.  You can't always expect the client to still be around when
> the message has been processed.

Yes you can. I do. Programs should not go away and leave things hanging.
If you need to do this, reply to the message after squirreling away the
data in the message.

> More urgently (for those who think the previous scenarios too fanciful), if

I don't think they're fanciful. I just think they're dangerous.

> you are sending MIDI messages or some other time-critical type of data, the
> last thing you want is to burden yourself with replying and handling
> replies.

This is a good reason for having them, though. So, let's define a message type
that's exempt from this restriction. We'll call it a timing message. A timing
message doesn't contain any data outside the message itself (no pointers), and
it doesn't contain anything that requires special handling (locks, etc).

> It MUST of course have been obtained with AllocMem by the client.  Things
> are a lot simpler if the message block itself is the only memory involved;
> then we can just use the mn_Length field (adjusted suitably) for FreeMem.
> This is why I think we shouldn't always use pointers where they otherwise
> might look appropriate.  I don't think we can make any general rule here:
> just be aware of the requirements of a particular application.

This isn't necessary nor sufficient. As I noted before, pointers aren't the
only thing that require special handling. Locks, Ports, Handles, and so on
can't be handled just by freeing the memory involved.

Also, by requiring messages be contiguous you radically increase the amount
of copying that's going on.

> A specially awkward case is the ln_Name field of a message....
> we should just ignore this field: anything it points
> to is not part of the message space (and may no longer exist).

Good point. It's forgotten :->.

> It has also been suggested that message contents shouldn't be changed
> except for a status word, but again this is unnecessarily restricting the
> ways a message might be used.  After all, one of its main purposes is to
> request and return data!  A client should expect that any part of the
> message data area may have been rewritten (meaningfully of course!) on
> reply.

I wasn't saying that things entries point to wouldn't be overwritten, just
that the entry list itself be inviolate. After all, it might not be big
enough for the reply. Also, you might get more than one reply to a given
message. For example, in my browser messages... if you send an ADDT message,
you will get a reply every time the user selects you from his tools menu.
For anything more complex than a status, the client should supply the server
a port to send its data to. This can be the reply port (after all, the reply
is an IPC message and won't be confused with any extra messages).

> One of the major advantages of messages is that they require little
> overhead to pass.  We should therefore avoid formats that add to the
> overhead unless they are particularly appropriate for that task.  My
> picture of the ideal message is a simple fixed structure that gives you
> direct access to any item within it, and my reaction to a couple of the
> recent proposals is that they rather violate this principle unnecessarily
> by using multiple chunks that can only be reached by scanning from the
> beginning.

As an alternative you could send several messages, but this would have more
overhead than scanning a single message. Since the Entries are an array, you
don't have much overhead at all in scanning them.

> There's nothing at all inherently wrong with multiple chunks, but because
> most applications won't need them I don't think they ought to be part of
> the fundamental IPC message structure -- unnecessary overhead again.  If
> they are used in a particular format, the first part of the data section
> should be a set of pointers to the individual blocks, so access is direct
> rather than sequential.

Just send a single Entry in a message, pointing to the data immediately after
the message itself. Absolutely minimal overhead, and completely compatible.

> If there are any I've left out, there's lots of spare codes, and no real
> way any particular choice could conflict with other uses.

Are you sure that this is safe? What if C= implements NT_NETWORK in Kickstart
1.7?

>         struct StdIPCMessage {
>             struct Message ipc_Msg;
>             ULONG   ipc_ID;
>             ULONG   ipc_Status;  /* application specific */
>             ULONG   ipc_Func;    /* specific nature of this message */
>             SHORT   ipc_Entries; /* number of items following */
>             APTR ipc_Items[];    /* data items OR pointers to items
>                                     depending on the ID */

Why complicate things by adding this extra level of indirection? Making
it "struct { ULONG ie_ID; void *ie_PTR; } ipc_Items[]" would speed
things up, and allow programs to pick and choose what parts of the
structure the dealt with.

>             /* Any data items pointed to will follow message AND be
>             included in the mn_Length */
>         };

Why? Does this include RastPorts, BitMaps, etc...? This requirement will
force copying of large structures.

> Actually if you look carefully at Peter's Browser structure, although there
> are a variable number of entries, the format for each action is strict
> enough that you would know where everything was without searching.

You could, but I'd rather keep the format general and intelligable. This
might not seem a big deal with the Browser case, but what about more
complex structures? After all, the internal IDs in IFF files aren't
strictly necessary either... they sure make it easier to deal with
lots of programs with slightly different requirements, though.

> You
> could do without the pointers in this case (so our only real disparity is
> in the function and positioning of the ID words.  Can we get together on
> this Peter?)  If the data items were something like IFF chunks, though, I
> think the pointer scheme would be well worth the slight extra space.

I don't see why you can't put the IDs in there. The overhead is minimal,
and it allows you to add extra data. For example, what if I came up with
a new version of thr Browser that handled messages that contained something
more than just the names and ports... say I added an extra text item to each
'ADDT' message to allow you to specify the menu as well as the menu item
for your message, and then allowed you to provide several name/port pairs.
New programs could deal with the old browser (they'd just all show up
under tools) and the new Browser could deal with old programs.
-- 
-- a clone of Peter (have you hugged your wolf today) da Silva  `-_-'
-- normally  ...!hoptoad!academ!uhnix1!sugar!peter                U
-- Disclaimer: These aren't mere opinions... these are *values*.

pete@violet.berkeley.edu (Pete Goodeve) (03/21/88)

In article <8803151957.AA11010@cory.Berkeley.EDU> dillon@CORY.BERKELEY.EDU (Matt Dillon) writes:

>         You are out of your mind.  OF COURSE THE MESSAGES HAVE TO BE REPLIED!
> [..... etc. and so forth.  And on and on, laying down the law...]

Your hysterics are getting tiresome, Matt.  Why is it that other people can
disagree without blasting the other guy, but your messages always seem to
be written with smoke coming out of your ears?  This is supposed to be a
discussion, not a courtroom.  It would help too if you showed signs of
actually having read -- and understood -- the various notions that people
have put forward, but it looks more as if you latch on to a bit out of
every third sentence and attach your own meaning to it.  Case in point:

>         You are making that assumption that you have thought of everything
> anyone will ever want to do.  That is a bad assumption to make.

Now go back and actually read what I (and other people) have been saying.
I'm not going to repeat it all yet again.

> .........
And I really can't be bothered to go round in circles again on the other
points, except this:

>         [.......]   How do you intend to atomically set the message
>         type to NT_NOSERVER when ReplyMsg() automatically sticks an
>         NT_REPLYMSG in the field???????

Yes you're right, but if you had been following the topic you would know
that I asked that specific question at the very beginning, assuming that
the field was set, and was informed by someone else very firmly that it was
not.  I accepted that without checking it, and you could have corrected me
without the histrionics.  It makes little difference though -- who says we
have to use ReplyMsg for such conditions?



| "...Capital letters were always the        |
| best way of dealing with things you        |     -- Pete Goodeve --
| didn't have a good answer to."             |
|  [Dirk Gently's Holistic Detective Agency] |
|                              Douglas Adams |

pete@violet.berkeley.edu (Pete Goodeve) (03/23/88)

Article 17273 of comp.sys.amiga:
Subject: Re: IPC: Messages (again)

In <806@nuchat.UUCP> peter@nuchat.UUCP (Peter da Silva) responds to
a posting of mine quibbling with some of his IPC message format
suggestions.  My response to his response has to be essentially: Yes, yes
... and yes.  Most of my disagreement seems to have been the result of
a rather hasty reading (hence misunderstanding) of what he was saying --
er, sort of what I've been accusing other people of doing!  Sorry.

In fact there was some very hasty thinking going on, because the IPCEntry
structure pair of {ID,pointer} is exactly what I came round to thinking was
the correct solution, yet didn't see that that was precisely what he had
suggested!  Somehow I'd got the impression he wanted the data in line. Ah,
well -- I guess we're in agreement.

At one or two points, though, I have a little more clarification to make,
so let's go round one more time.


> ......... Programs should not go away and leave things hanging.
> If you need to do this, reply to the message after squirreling away the
> data in the message.
> .... [sneakily edited...]
>            ......                    So, let's define a message type
> that's exempt from this restriction. We'll call it a timing message. A timing
> message doesn't contain any data outside the message itself (no pointers), and
> it doesn't contain anything that requires special handling (locks, etc).

Yes, this is really what I meant.  If there's any complexity in a message
we should hope it can be replied.  On the other hand, I still claim that we
will run into situations -- many of which will be discovered later,
probably when we have just outlawed the possibility -- where the server,
rather than the client, will have to handle the disposal of resources.

I can also envisage situations where two applications will want to share a
bitmap, say, and there will be no way to tell beforehand which will want
to go away first (leaving the other to release it).  We may want a
use-count on shared memory, too.

> .....
> >[AllocMem/FreeMem]
> ... isn't necessary nor sufficient. As I noted before, pointers aren't the
> only thing that require special handling. Locks, Ports, Handles, and so on
> can't be handled just by freeing the memory involved.

Point noted.  Isn't sufficient, anyway.  But on the other hand these types
of entities (Locks, etc.) are even more likely to be "handed over" to the
other application.  Your suggestion that the server control ownership by
zeroing out pointers it has "taken over" probably covers things fairly
well (except for "sharing" things -- see above).


> .....
> Also, by requiring messages be contiguous you radically increase the amount
> of copying that's going on.

I've abandoned that suggestion.


> ....
> I wasn't saying that things entries point to wouldn't be overwritten, just

(Actually I think I was referring to an earlier posting of yours here.)


>    ......             Also, you might get more than one reply to a given
> message. For example, in my browser messages... if you send an ADDT message,
> you will get a reply every time the user selects you from his tools menu.

Uh, do you mean that ONE message will get replied more than once? (AFTER
it has been GetMsg'd but NOT PutMsg'd again??!)  I'll assume you don't mean
that, but rather that you will get additional messages to your reply port.
(Which you in turn will have to reply?)


>  [I said: ...]
> > picture of the ideal message is a simple fixed structure that gives you
> > direct access to any item within it, and my reaction to a couple of the
> > recent proposals is that they rather violate this principle unnecessarily
> > by using multiple chunks that can only be reached by scanning from the
> > beginning.
>
> As an alternative you could send several messages, but this would have more
> overhead than scanning a single message. Since the Entries are an array, you
> don't have much overhead at all in scanning them.

Actually (aside from the fact that I misread your scheme) I was thinking
more of the IFF type structures some have suggested, where the only way to
get to a particular chunk is by traversing all those preceding it.


> [regarding adding ln_Type codes...]
> Are you sure that this is safe? What if C= implements NT_NETWORK in Kickstart
> 1.7?

My reason for considering it "safe" is that normally messages are messages
are messages, and so even if we did choose a code that conflicted, it
shouldn't ever find itself in a list of anything but messages.

Anyhow, it turns out I was misinformed, and PutMsg and GetMsg DO set
the ln_Type field, so our possibilities become highly limited.  I do still
think that we should add a UnkmownMsg() reply procedure (which would set
the type to NT_UNKNOWN) as a format-independent way of telling the client
it's out of luck.  And there IS that mysterious type NT_FREEMSG... does
anybody know what that was reserved for?  (I inquired at BADGE without
success.)


> > [I said] ..........                        (so our only real disparity is
> > in the function and positioning of the ID words.  Can we get together on
> > this Peter?)

And as usual didn't make clear what I meant.  I was only referring to
the different positioning of the main ID word which for generality I still
think should be the first longword of the message, with the status
following.  So, does this come close to complete agreement?

struct IPCEntry {
    ULONG   IE_Id;  /* strictly determines meaning of data referenced */
    ULONG   IE_Size;    /* size of data structure -- I think we need this */
    void   *IE_Ptr; /* points to defined data structure (could be within
                    message block if IE_Id says so) */
    };


struct IPCMessage {
    struct Message IPC_Msg;
        /* ..ln_Name field should be NULL
            ..ln_Type will be NT_MESSAGE, NT_REPLYMSG or NT_UNKNOWN
            mn_Length will include IPC_Items array and any in-line data
        */
    ULONG   IPC_Type,   /* four character (or other) ID */
            IPC_Status; /* type dependent return status */
    USHORT  IPC_Itemcount;  /* should be enough, surely? */
    struct  IPCEntry    IPC_Items[];
    };

(I've vacillated between "Entry" and "Item"... I prefer "Item" slightly, but
whatever.)

                                            -- Pete --

peter@nuchat.UUCP (Peter da Silva) (03/27/88)

In article ... pete@violet.berkeley.edu (Pete Goodeve) writes:
  Me:
< > ......... Programs should not go away and leave things hanging.
< > If you need to do this, reply to the message after squirreling away the
< > data in the message.
< > .... [sneakily edited...]

Yeh, I'm talking about realtime messages, not dangerous ones. You're
dangerous, Maverick :->.

< Yes, this is really what I meant.  If there's any complexity in a message
< we should hope it can be replied.  On the other hand, I still claim that we
< will run into situations -- many of which will be discovered later,
< probably when we have just outlawed the possibility -- where the server,
< rather than the client, will have to handle the disposal of resources.

In fact my Browser message deals with one such situation. My solution, which
I see (by means of psychotic powers I can predict what you're going to say
next :->) you understand, is to have the server explicitly claim resources
it requires.

< I can also envisage situations where two applications will want to share a
< bitmap, say, and there will be no way to tell beforehand which will want
< to go away first (leaving the other to release it).  We may want a
< use-count on shared memory, too.

Tricky. Let's leave this particular problem for later.

< Point noted.  Isn't sufficient, anyway.  But on the other hand these types
< of entities (Locks, etc.) are even more likely to be "handed over" to the
< other application.  Your suggestion that the server control ownership by
< zeroing out pointers it has "taken over" probably covers things fairly
< well (except for "sharing" things -- see above).

Ah, proof of my psychotic abilities. Yes.

< >    ......             Also, you might get more than one reply to a given
< > message. For example, in my browser messages... if you send an ADDT message,
< > you will get a reply every time the user selects you from his tools menu.
< 
< Uh, do you mean that ONE message will get replied more than once? (AFTER
< it has been GetMsg'd but NOT PutMsg'd again??!)  I'll assume you don't mean
< that, but rather that you will get additional messages to your reply port.
< (Which you in turn will have to reply?)

Yes, I'm using the term "reply" a little loosely, here.

< I do still
< think that we should add a UnkmownMsg() reply procedure (which would set
< the type to NT_UNKNOWN) as a format-independent way of telling the client
< it's out of luck.  And there IS that mysterious type NT_FREEMSG... does
< anybody know what that was reserved for?  (I inquired at BADGE without
< success.)

I don't see why you want to overload data onto this channel. Would another
USHORT in the body of the message be too much to ask for?

< And as usual didn't make clear what I meant.  I was only referring to
< the different positioning of the main ID word which for generality I still
< think should be the first longword of the message, with the status
< following.  So, does this come close to complete agreement?
< 
< struct IPCEntry {
<     ULONG   IE_Id;  /* strictly determines meaning of data referenced */
<     ULONG   IE_Size;    /* size of data structure -- I think we need this */
<     void   *IE_Ptr; /* points to defined data structure (could be within
<                     message block if IE_Id says so) */
<     };

I wouldn't want to put it into the message block depending on ID. Matt
Dillon's point about not having to know the ID to pass a message
along is a valid one. I think that you're right... we need teh size (and
of course Matt's point requires it) Let's just let pointers be pointers,
and allocate this stuff together when needed.

< struct IPCMessage {
<     struct Message IPC_Msg;
<         /* ..ln_Name field should be NULL
<             ..ln_Type will be NT_MESSAGE, NT_REPLYMSG or NT_UNKNOWN
<             mn_Length will include IPC_Items array and any in-line data
<         */
<     ULONG   IPC_Type,   /* four character (or other) ID */
<             IPC_Status; /* type dependent return status */
<     USHORT  IPC_Itemcount;  /* should be enough, surely? */
<     struct  IPCEntry    IPC_Items[];
<     };

< (I've vacillated between "Entry" and "Item"... I prefer "Item" slightly, but
< whatever.)

OK, let's go with "Item". struct IPCItem and all. (that what you mean?)

<                                             -- Pete --
-- 
-- a clone of Peter (have you hugged your wolf today) da Silva  `-_-'
-- normally  ...!hoptoad!academ!uhnix1!sugar!peter                U
-- Disclaimer: These aren't mere opinions... these are *values*.

pete@violet.berkeley.edu (Pete Goodeve) (04/02/88)

Responding to two of Peter da Silva's messages at once...

From <864@nuchat.UUCP>:

> < [Me:]...
> < think that we should add a UnkmownMsg() reply procedure (which would set
> < the type to NT_UNKNOWN) as a format-independent way of telling the client
> < it's out of luck. [....]
>
> I don't see why you want to overload data onto this channel. Would another
> USHORT in the body of the message be too much to ask for?

This was part of my fight to retrofit to other-format messages.  I guess
I've retired from that particular fray...  We'll just reserve a bit or two
in the IPC_Status field.


> < struct IPCItem {
> <      ......
> <     void   *IE_Ptr; /* points to defined data structure (could be within
> <                     message block if IE_Id says so) */
> <     };
>
> I wouldn't want to put it into the message block depending on ID. Matt
> Dillon's point about not having to know the ID to pass a message
> along is a valid one.

Agreed.  My original thoughts were to have the ID control the format, as it
does in IFF, but that becomes impractical when you take all the points Matt
and other people have raised into account.  See below for more...

>
> OK, let's go with "Item". struct IPCItem and all. (that what you mean?)

Yaay!! [jumps up and down in high glee...]  Nynhh Hynhh.. I like dis game!

> --

From <1771@sugar.UUCP>:

>
> In my last IPC message I said that only pointers should go in the pointer
> field of the IPCItem structure. That was totally bogus... you should be
> able to put RastPorts, Locks, anything in there.
                                ^^^^^^ that'll fit into a longword I assume..
>
> But you still need to be able to let IPCGateways know about them if they
> can do anything with them.
>
> How about this. If the size feild is zero, then that means "Mind your own
> business, Spock, I'm sick of your half-breed interference". So IPCGateway
> can copy stuff through with non-zero size feilds, and leave bad ones behind.

A good thought, but does it go far enough?  The problem seems to me that
the server may need -- so far! -- at least three items of information about
an item:

    1) "You (the server) can take responsibility for this item, and free it
        when you're done"
    2) "The contents of this item may be transmitted elsewhere" (i.e. not a
       lock etc.)
    3) "This item is included in the mn_Length" (maybe this could be
        flagged by a size field of zero, but there's always the chance we
        might like the size for some other purpose).

These are pretty independent.  One item might be a port structure, say,
that could be passed to another process but not down a network; or a buffer
could be transmittable, but kept by the client.  I think IE_Size==0 should
be reserved to indicate that the item is NOT a pointer.

Looks like we're forced into YAFF (Yet Another Bloody Field) in each item
that you can put these flags in -- and all the others we'll think of.  I
thought at first a single Flags word at the head of the message might be
enough, but I suspect we'd surely want items with different characteristics
in the same message (command fields that remained client's property, with
buffers to be passed on, for example).  I suppose we might as well make it
a long word, but maybe split off 16 bits for item dependent flags (ignored
by processes which didn't understand the ID).  We probably also ought to
allow the server to set some of the bits to indicate, for instance, "Don't
know about this item"  (This wouldn't be set by processes such as a network
handler -- only by a server that the client sent the wrong type of item
to).   So, Revision k+1?:


 struct IPCItem {
     ULONG   IE_Id;  /* strictly determines meaning of data referenced */
     ULONG   IE_Flags;
     ULONG   IE_Size;    /* size of data structure -- I think we need this */
     void   *IE_Ptr; /* points to defined data structure
                     (could be within message block if IE_Flags says so) */
     };

/* Flags set by client (tentative, natch...): */

#define IPC_IE_TRANSFER   0x08000000
#define IPC_IE_NETWORK    0x04000000
#define IPC_IE_INMESSAGE  0x02000000

/* Flag returned by server (ditto): */

#define IPC_IE_NOTKNOWN   0x80000000

I actually have NO suggested changes to the previous message structure...!

                                        -- Pete --
[ BTW:

> -- a clone of Peter (have you hugged your wolf today) da Silva  `-_-'
       ^^^^^ how many of these do you have?  There's a Peter daSilva (sic)
       doing some good photo work for the campus newsrag.  (If I had a
       DigiView, I'd send you a sample...)                               ]

peter@nuchat.UUCP (Peter da Silva) (04/07/88)

In article ... pete@violet.berkeley.edu (Pete Goodeve) writes:
> Responding to two of Peter da Silva's messages at once...

> From <864@nuchat.UUCP>:

> This was part of my fight to retrofit to other-format messages.  I guess
> I've retired from that particular fray...  We'll just reserve a bit or two
> in the IPC_Status field.

I like dis game, too.

> Agreed.  My original thoughts were to have the ID control the format, as it
> does in IFF, but that becomes impractical when you take all the points Matt
> and other people have raised into account.  See below for more...

> > OK, let's go with "Item". struct IPCItem and all. (that what you mean?)

> Yaay!! [jumps up and down in high glee...]  Nynhh Hynhh.. I like dis game!

Are you a Goon Show fan, too?
(I talk to the trees, that's why they put me away)

> From <1771@sugar.UUCP>:

> > In my last IPC message I said that only pointers should go in the pointer
> > field of the IPCItem structure. That was totally bogus... you should be
> > able to put RastPorts, Locks, anything in there.
>                                 ^^^^^^ that'll fit into a longword I assume..

Yeh, anything that will fit in a longword.

> A good thought, but does it go far enough?  The problem seems to me that
> the server may need -- so far! -- at least three items of information about
> an item:

>     1) "You (the server) can take responsibility for this item, and free it
>         when you're done"

Good point.

>     2) "The contents of this item may be transmitted elsewhere" (i.e. not a
>        lock etc.)
>     3) "This item is included in the mn_Length" (maybe this could be
>         flagged by a size field of zero, but there's always the chance we
>         might like the size for some other purpose).

No, I wouldn't want to flag this with a size feild of zero, because the message
might want to be disassembled and reassembled on the other side of the gateway.

> These are pretty independent.  One item might be a port structure, say,
> that could be passed to another process but not down a network; or a buffer
> could be transmittable, but kept by the client.  I think IE_Size==0 should
> be reserved to indicate that the item is NOT a pointer.

At least that it's not an explicit pointer to something with a known size.
After all, the size of a SimpleRefresh layer can vary widely, and BPTRs are
still pointers. (yeh, I'm picking nits. Wanna make something of it?)

> Looks like we're forced into YAFF (Yet Another Bloody Field) in each item

YABF, don't you mean? :->

>  struct IPCItem {
>      ULONG   IE_Id;  /* strictly determines meaning of data referenced */
>      ULONG   IE_Flags;
>      ULONG   IE_Size;    /* size of data structure -- I think we need this */
>      void   *IE_Ptr; /* points to defined data structure
>               ^      (could be within message block if IE_Flags says so) */
>      };       |
                \_ Shouldn't this column be an 'I' for 'Item' now?

> /* Flags set by client (tentative, natch...): */

> #define IPC_IE_TRANSFER   0x08000000
> #define IPC_IE_NETWORK    0x04000000
> #define IPC_IE_INMESSAGE  0x02000000

> /* Flag returned by server (ditto): */

> #define IPC_IE_NOTKNOWN   0x80000000

  #define IPC_IE_STOLEN     0x40000000

> I actually have NO suggested changes to the previous message structure...!

Wow.

> > -- a clone of Peter (have you hugged your wolf today) da Silva  `-_-'
>        ^^^^^ how many of these do you have?  There's a Peter daSilva (sic)
>        doing some good photo work for the campus newsrag.  (If I had a
>        DigiView, I'd send you a sample...)                               ]

Not one of mine, man. Here are my clones:

nuchat	:	...!uunet!nuchat
	|	...!hoptoad!academ!uhnix1!!nuchat

sugar	:	nuchat!sugar
	|	...!hoptoad!academ!uhnix1!sugar

argent	:	nuchat!argent
	|	sugar!argent

	nuchat!peter            <-- clone #1.
	sugar!peter             <-- true name.
	argent!peter            <-- my amiga, with uupc.
	sugar!ficc!peter        <-- business wetware only.
	...!seismo!ucmhou!peter <-- I think.
-- 
-- a clone of Peter (have you hugged your wolf today) da Silva  `-_-'
-- normally  ...!hoptoad!academ!uhnix1!sugar!peter                U
-- Disclaimer: These aren't mere opinions... these are *values*.

kkaempf@rmi.UUCP (Klaus Kaempf) (04/11/88)

In article <7929@agate.BERKELEY.EDU>
pete@violet.berkeley.edu (Pete Goodeve) writes:
> And there IS that mysterious type NT_FREEMSG ... does
> anybody know what that was reserved for? (I inquired at
> BADGE without success.)

void ReplyMsg(mn)
struct Message *mn;
 {
 struct MsgPort *mp;

 if((mp = mn->mn_ReplyPort)) == NULL)
  {
  mn->mn_Node.ln_Type = NT_FREEMSG;
  }
 else
  {
  mn->mn_Node.ln_Type = NT_REPLYMSG;
  (*(PutMsg + SOME_BYTES))(mp, mn); /* argh - don't set ln_Type to NT_MESSAGE */
  }
 }

If a message does not have a reply port associated with it,
it becomes a FreeMsg after being "replied". So there is
nothing mysterious about it, it might be even useful (I must
admit, that - although undocumented - I have used it once!).

Any comments and criticism on releasing such pieces of
information (like the more dangerous WorkBenchBase I posted
some weeks ago) are appreciated.

Prost Mahlzeit!

!ralph

Ralph Babel, Falkenweg 3, D-6204 Taunusstein, FRGermany

pete@violet.berkeley.edu (Pete Goodeve) (04/14/88)

In article <895@nuchat.UUCP> Peter da Silva writes:

> Are you a Goon Show fan, too?
> (I talk to the trees, that's why they put me away)

Well, only a cardboard replica, actually.  (You can't get the wood, y'know...)

>
> > Looks like we're forced into YAFF (Yet Another Bloody Field) in each item
>
> YABF, don't you mean? :->

As a matter of fact it was "Bloody" that was mis-substituted.... (:^))

>
> >      void   *IE_Ptr; /* points to defined data structure
> >               ^      (could be within message block if IE_Flags says so) */
> >      };       |
>                 \_ Shouldn't this column be an 'I' for 'Item' now?

Aye aye cap'n...

So -- do we actually have an agreed message format?  Can we start using it?
Can we persuade anyone else to start using it?

                                        -- Pete --

doug@eris (Doug Merritt) (04/14/88)

In article <8720@agate.BERKELEY.EDU> pete@violet.berkeley.edu.UUCP (Pete Goodeve) writes:
>So -- do we actually have an agreed message format?  Can we start using it?
>Can we persuade anyone else to start using it?

Hey, if the dust is finally starting to clear, I'd like to see
what the current model looks like in a nutshell.

That should go a long way towards persuading others.

	Doug Merritt		doug@mica.berkeley.edu (ucbvax!mica!doug)
			or	ucbvax!unisoft!certes!doug