/* Copyright (C) 1993-2014 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.  */

/* Based on CMU's mach_msg_server.c revision 2.4 of 91/05/14, and thus
   under the following copyright.  Rewritten by Roland McGrath (FSF)
   93/12/06 to use stack space instead of malloc, and to handle
   large messages with MACH_RCV_LARGE.  */

/*
 * 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:22  mrt
 * 	Correcting copyright
 *
 * Revision 2.3  91/02/14  14:17:47  mrt
 * 	Added new Mach copyright
 * 	[91/02/13  12:44:20  mrt]
 *
 * Revision 2.2  90/08/06  17:23:58  rpd
 * 	Created.
 *
 */


#include <mach.h>
#include <mach/mig_errors.h>
#include <stdlib.h>		/* For malloc and free.  */
#include <assert.h>

#ifdef NDR_CHAR_ASCII		/* OSF Mach flavors have different names.  */
# define mig_reply_header_t	mig_reply_error_t
#endif

mach_msg_return_t
__mach_msg_server_timeout (boolean_t (*demux) (mach_msg_header_t *request,
					       mach_msg_header_t *reply),
			   mach_msg_size_t max_size,
			   mach_port_t rcv_name,
			   mach_msg_option_t option,
			   mach_msg_timeout_t timeout)
{
  mig_reply_header_t *request, *reply;
  mach_msg_return_t mr;

  if (max_size == 0)
    {
#ifdef MACH_RCV_LARGE
      option |= MACH_RCV_LARGE;
      max_size = 2 * __vm_page_size; /* Generic.  Good? XXX */
#else
      max_size = 4 * __vm_page_size; /* XXX */
#endif
    }

  request = __alloca (max_size);
  reply = __alloca (max_size);

  while (1)
    {
    get_request:
      mr = __mach_msg (&request->Head, MACH_RCV_MSG|option,
		       0, max_size, rcv_name,
		       timeout, MACH_PORT_NULL);
      while (mr == MACH_MSG_SUCCESS)
	{
	  /* We have a request message.
	     Pass it to DEMUX for processing.  */

	  (void) (*demux) (&request->Head, &reply->Head);
	  assert (reply->Head.msgh_size <= max_size);

	  switch (reply->RetCode)
	    {
	    case KERN_SUCCESS:
	      /* Hunky dory.  */
	      break;

	    case MIG_NO_REPLY:
	      /* The server function wanted no reply sent.
		 Loop for another request.  */
	      goto get_request;

	    default:
	      /* Some error; destroy the request message to release any
		 port rights or VM it holds.  Don't destroy the reply port
		 right, so we can send an error message.  */
	      request->Head.msgh_remote_port = MACH_PORT_NULL;
	      __mach_msg_destroy (&request->Head);
	      break;
	    }

	  if (reply->Head.msgh_remote_port == MACH_PORT_NULL)
	    {
	      /* No reply port, so destroy the reply.  */
	      if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)
		__mach_msg_destroy (&reply->Head);
	      goto get_request;
	    }

	  /* Send the reply and the get next request.  */

	  {
	    /* Swap the request and reply buffers.  mach_msg will read the
	       reply message from the buffer we pass and write the new
	       request message to the same buffer.  */
	    void *tmp = request;
	    request = reply;
	    reply = tmp;
	  }

	  mr = __mach_msg (&request->Head,
			   MACH_SEND_MSG|MACH_RCV_MSG|option,
			   request->Head.msgh_size, max_size, rcv_name,
			   timeout, MACH_PORT_NULL);
	}

      /* A message error occurred.  */

      switch (mr)
	{
	case MACH_RCV_TOO_LARGE:
#ifdef MACH_RCV_LARGE
	  /* The request message is larger than MAX_SIZE, and has not
	     been dequeued.  The message header has the actual size of
	     the message.  We recurse here in hopes that the compiler
	     will optimize the tail-call and allocate some more stack
	     space instead of way too much.  */
	  return __mach_msg_server_timeout (demux, request->Head.msgh_size,
					    rcv_name, option, timeout);
#else
	  /* XXX the kernel has destroyed the msg */
	  break;
#endif

	case MACH_SEND_INVALID_DEST:
	  /* The reply can't be delivered, so destroy it.  This error
	     indicates only that the requester went away, so we
	     continue and get the next request.  */
	  __mach_msg_destroy (&request->Head);
	  break;

	default:
	  /* Some other form of lossage; return to caller.  */
	  return mr;
	}
    }
}
weak_alias (__mach_msg_server_timeout, mach_msg_server_timeout)

mach_msg_return_t
__mach_msg_server (demux, max_size, rcv_name)
     boolean_t (*demux) (mach_msg_header_t *in, mach_msg_header_t *out);
     mach_msg_size_t max_size;
     mach_port_t rcv_name;
{
  return __mach_msg_server_timeout (demux, max_size, rcv_name,
				    MACH_MSG_OPTION_NONE,
				    MACH_MSG_TIMEOUT_NONE);
}
weak_alias (__mach_msg_server, mach_msg_server)
