/*
 * Mach Operating System
 * Copyright (c) 1991,1990 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 */
/*
 * (pre-GNU) HISTORY
 *
 * Revision 2.4  91/05/14  17:53:15  mrt
 * 	Correcting copyright
 *
 * Revision 2.3  91/02/14  14:17:43  mrt
 * 	Added new Mach copyright
 * 	[91/02/13  12:44:15  mrt]
 *
 * Revision 2.2  90/08/06  17:24:22  rpd
 * 	Created.
 *
 */

#if 1
#include <mach.h>
#else
/* This is what CMU did, but that fails to declare some used functions.  */
#include <mach/port.h>
#include <mach/message.h>
#include <mach_init.h>
#endif

static void mach_msg_destroy_port(mach_port_t, mach_msg_type_name_t);
static void mach_msg_destroy_memory(vm_offset_t, vm_size_t);

/*
 *	Routine:	mach_msg_destroy
 *	Purpose:
 *		Deallocates all port rights and out-of-line memory
 *		found in a received message.
 */

void
__mach_msg_destroy(msg)
    mach_msg_header_t *msg;
{
    mach_msg_bits_t mbits = msg->msgh_bits;

    /*
     *	The msgh_local_port field doesn't hold a port right.
     *	The receive operation consumes the destination port right.
     */

    mach_msg_destroy_port(msg->msgh_remote_port, MACH_MSGH_BITS_REMOTE(mbits));

    if (mbits & MACH_MSGH_BITS_COMPLEX) {
#ifdef MACH_MSG_PORT_DESCRIPTOR
	mach_msg_body_t		*body;
	mach_msg_descriptor_t	*saddr, *eaddr;

    	body = (mach_msg_body_t *) (msg + 1);
    	saddr = (mach_msg_descriptor_t *)
			((mach_msg_base_t *) msg + 1);
    	eaddr =  saddr + body->msgh_descriptor_count;

	for  ( ; saddr < eaddr; saddr++) {
	    switch (saddr->type.type) {

	        case MACH_MSG_PORT_DESCRIPTOR: {
		    mach_msg_port_descriptor_t *dsc;

		    /*
		     * Destroy port rights carried in the message
		     */
		    dsc = &saddr->port;
		    mach_msg_destroy_port(dsc->name, dsc->disposition);
		    break;
	        }

	        case MACH_MSG_OOL_DESCRIPTOR : {
		    mach_msg_ool_descriptor_t *dsc;

		    /*
		     * Destroy memory carried in the message
		     */
		    dsc = &saddr->out_of_line;
		    if (dsc->deallocate) {
		        mach_msg_destroy_memory((vm_offset_t)dsc->address,
						dsc->size);
		    }
		    break;
	        }

	        case MACH_MSG_OOL_PORTS_DESCRIPTOR : {
		    mach_port_t             		*ports;
		    mach_msg_ool_ports_descriptor_t	*dsc;
		    mach_msg_type_number_t   		j;

		    /*
		     * Destroy port rights carried in the message
		     */
		    dsc = &saddr->ool_ports;
		    ports = (mach_port_t *) dsc->address;
		    for (j = 0; j < dsc->count; j++, ports++)  {
		        mach_msg_destroy_port(*ports, dsc->disposition);
		    }

		    /*
		     * Destroy memory carried in the message
		     */
		    if (dsc->deallocate) {
		        mach_msg_destroy_memory((vm_offset_t)dsc->address,
					dsc->count * sizeof(mach_port_t));
		    }
		    break;
	        }
	    }
	}
#else
	vm_offset_t saddr;
	vm_offset_t eaddr;

	saddr = (vm_offset_t) (msg + 1);
	eaddr = (vm_offset_t) msg + msg->msgh_size;

	while (saddr < eaddr) {
	    mach_msg_type_long_t *type;
	    mach_msg_type_name_t name;
	    mach_msg_type_size_t size;
	    mach_msg_type_number_t number;
	    boolean_t is_inline;
	    vm_size_t length;
	    vm_offset_t addr;

	    type = (mach_msg_type_long_t *) saddr;
	    is_inline = type->msgtl_header.msgt_inline;
	    if (type->msgtl_header.msgt_longform) {
		    name = type->msgtl_name;
		    size = type->msgtl_size;
		    number = type->msgtl_number;
		    saddr += sizeof(mach_msg_type_long_t);
	    } else {
		    name = type->msgtl_header.msgt_name;
		    size = type->msgtl_header.msgt_size;
		    number = type->msgtl_header.msgt_number;
		    saddr += sizeof(mach_msg_type_t);
	    }

	    /* calculate length of data in bytes, rounding up */
	    length = (((((number * size) + 7) >> 3) + sizeof (int) - 1)
		      &~ (sizeof (int) - 1));

	    addr = is_inline ? saddr : * (vm_offset_t *) saddr;

	    if (MACH_MSG_TYPE_PORT_ANY(name)) {
		mach_port_t *ports = (mach_port_t *) addr;
		mach_msg_type_number_t i;

		for (i = 0; i < number; i++)
		    mach_msg_destroy_port(*ports++, name);
	    }

	    if (is_inline) {
		/* inline data sizes round up to int boundaries */
		saddr += length;
	    } else {
		mach_msg_destroy_memory(addr, length);
		saddr += sizeof(vm_offset_t);
	    }
	}
#endif
    }
}

weak_alias (__mach_msg_destroy, mach_msg_destroy)

static void
mach_msg_destroy_port(port, type)
    mach_port_t port;
    mach_msg_type_name_t type;
{
    if (MACH_PORT_VALID(port)) switch (type) {
      case MACH_MSG_TYPE_MOVE_SEND:
      case MACH_MSG_TYPE_MOVE_SEND_ONCE:
	/* destroy the send/send-once right */
	(void) __mach_port_deallocate(mach_task_self(), port);
	break;

      case MACH_MSG_TYPE_MOVE_RECEIVE:
	/* destroy the receive right */
	(void) __mach_port_mod_refs(mach_task_self(), port,
				    MACH_PORT_RIGHT_RECEIVE, -1);
	break;

      case MACH_MSG_TYPE_MAKE_SEND:
	/* create a send right and then destroy it */
	(void) __mach_port_insert_right(mach_task_self(), port,
					port, MACH_MSG_TYPE_MAKE_SEND);
	(void) __mach_port_deallocate(mach_task_self(), port);
	break;

      case MACH_MSG_TYPE_MAKE_SEND_ONCE:
	/* create a send-once right and then destroy it */
	(void) __mach_port_extract_right(mach_task_self(), port,
					 MACH_MSG_TYPE_MAKE_SEND_ONCE,
					 &port, &type);
	(void) __mach_port_deallocate(mach_task_self(), port);
	break;
    }
}

static void
mach_msg_destroy_memory(addr, size)
    vm_offset_t addr;
    vm_size_t size;
{
    if (size > 0)
	(void) __vm_deallocate(__mach_task_self(), addr, size);
}
