/*******************************************************************
 *                                                                 *
 *                           IPC.h                                 *
 *                                                                 *
 *           Inter-Process-Communication Message Format            *
 *                                                                 *
 *              Revision 0.1 -- 1988 April 30                      *
 *                                                                 *
 *         Copyright 1988 Peter da Silva & Peter Goodeve           *
 *                      All Rights reserved                        *
 *                                                                 *
 *  This source is freely distributable, but should not be         *
 *  modified without prior consultation with the authors.          *
 *                                                                 *
 *******************************************************************/

#ifndef EXEC_TYPES_H
#include "exec/types.h"
#endif

#ifndef EXEC_PORTS_H
#include "exec/ports.h"
#endif

/*** Item Reference block -- an arbitrary number of these may be
   put in an IPCMessage ***/

struct IPCItem {
    ULONG   ii_Id;      /* four character ID (normally);
                           determines exact meaning of IPCItem IDs */
    ULONG   ii_Flags;   /* upper 16 bits have standard meaning;
                           lower 16 bits are message dependent */
    ULONG   ii_Size;    /* size of data structure (zero if ii_Ptr is not
                           actually a pointer to data) */
    void   *ii_Ptr;     /* points to defined data structure (could be within
                           message block if IE_Flags says so) -- also may be
                           recast to other 32-bit value (e.g. Lock) */
    };



/*** The basic IPCMessage block ***/

struct IPCMessage {
    struct Message  ipc_Msg;
        /* ..ln_Name field should be NULL
            mn_Length will include IPC_Items array and any in-line data
        */
    ULONG   ipc_Id,                /* four character (or other) ID */
            ipc_Flags;
    UWORD   ipc_ItemCount;         /* number of items in array */
    struct  IPCItem ipc_Items[1];  /* .. actual size as needed */
    };


/*************************************************************/

/* Flags set by client (tentative...): */
/* -- may appear in either IPCItem or IPCMessage Flags field */

#define IPC_TRANSFER   0x08000000
    /* Data block ownership may be transferred to server */
#define IPC_NETWORK    0x04000000
    /* The data in this block/message may be transmitted to
       another machine */
#define IPC_INMESSAGE  0x02000000
    /* The data in this block/message is included in the message length */

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

#define IPC_NOTKNOWN   0x80000000
    /* The server could not handle this block/message
       (either because it did not understand the ID or
       was unable to process it -- see the secondary flags */
#define IPC_MODIFIED   0x40000000
    /* The server modified the data, either within the
       supplied data block(s) or -- if permitted -- by
       replacing/removing the block pointer; again maybe
       other flag bits should indicate the nature of
       the modification */

/* valid for Item only: */
#define IPC_SERVER_OWNED 0x10000000
    /* The server owns this data Item -- either because it has
       created it or because it took it over from the client
       (in which case it clears IPC_TRANSFER, which must have
       been set) */


/* secondary flag bits (more to come...): */

#define IPC_CHECKITEM 0x00800000
    /* associated with IPC_NOTKNOWN -- indicates that one or more
       particular items caused the flag to be set */
#define IPC_FAILED 0x00400000
    /* IPC_NOTKNOWN flag was set because the server failed to
       handle an ID that it is designed to (rather than just
       not recognizing the block) */

/*************************************************************/


/*** IPC Ports and Procedures ***/


/* -- see IPCPorts.h for actual structure definitions */
#ifndef IPC_PORTS_H
/* Normal user doesn't need access to port components,
   so just use a convenient define.  Note that an IPC port
   is NEVER in private data space -- or in the public port
   list -- it is created and managed by the package routines
   only. */
#define IPCPort MsgPort
#endif


/* IPC Port Handling function prototypes: */

struct IPCPort * FindIPCPort(char *);
    /* returns pointer to port if it exists -- null otherwise;
       registers a new connection to the port */

struct IPCPort * GetIPCPort(char *);
    /* returns pointer to port -- it is created if it doesn't exist;
       registers a new connection to the port */


void UseIPCPort(struct IPCPort *);
    /* adds a connection to a port (passed by pointer from another
       process) */


void DropIPCPort(struct IPCPort *);
    /* disconnect from port -- port will be destroyed if there are
       no other connections left */


struct IPCPort * ServeIPCPort(char *);
    /* become a server for the named port (created if it doesn't exist);
       null is returned if the port already has a server, otherwise a
       pointer to it is returned */

void ShutIPCPort(struct IPCPort *);
    /* (server only) prevent more messages being sent to this port, but
       do not end server connection; remaining messages can be dealt
       with before Leaving */

void LeaveIPCPort(struct IPCPort *);
    /* cease to be a server for this port; another process can then
       become a server if it desires */

CheckIPCPort(struct IPCPort *, USHORT);
    /* returns number of current connections to this port (including
       server); a call by the server (only) will also set the (user
       settable) port flags to the value in the second argument --
       currently the only valid flag is IPP_NOTIFY */


PutIPCMsg(struct IPCPort *, struct IPCMessage *);
    /* sends an IPCMessage to an IPCPort; if the port has no server or
       is shut, the message is not sent and the function returns FALSE;
       otherwise it returns TRUE. (Other port flags to be added later
       may affect these actions.) */

struct IPCMessage * CreateIPCMsg(int);
    /* creates a standard IPCMessage block (in MEMF_PUBLIC) with the
       number of IPCItems supplied as argument ( special cases -- like
       in line data -- you will have to handle yourself, and you always
       have to manage the data blocks yourself). */


void DeleteIPCMsg(struct IPCMessage *);
    /* deletes a standard IPCMessage block;  you must first have disposed
       of any attached data as appropriate */


/* Server settable Port flags: */

#define IPP_NOTIFY 0x0001
    /* server wants to be signalled if connection is added or dropped
       (the port sigbit is used to signal the task,
        but no message is sent) */

/*************************************************************/
