/* * 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. */ /* * HISTORY * $Log: mach_msg_server.c,v $ * 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 #include #include #include #include /* * Routine: mach_msg_server * Purpose: * A simple generic server function. */ mach_msg_return_t __mach_msg_server_timeout(demux, max_size, rcv_name, option, timeout) boolean_t (*demux)(); mach_msg_size_t max_size; mach_port_t rcv_name; mach_msg_option_t option; mach_msg_timeout_t timeout; { register mig_reply_header_t *bufRequest, *bufReply, *bufTemp; register mach_msg_return_t mr; bufRequest = (mig_reply_header_t *) malloc(max_size); if (bufRequest == 0) return KERN_RESOURCE_SHORTAGE; bufReply = (mig_reply_header_t *) malloc(max_size); if (bufReply == 0) return KERN_RESOURCE_SHORTAGE; for (;;) { get_request: mr = __mach_msg(&bufRequest->Head, MACH_RCV_MSG|option, 0, max_size, rcv_name, timeout, MACH_PORT_NULL); while (mr == MACH_MSG_SUCCESS) { /* we have a request message */ (void) (*demux)(&bufRequest->Head, &bufReply->Head); if (bufReply->RetCode != KERN_SUCCESS) { if (bufReply->RetCode == MIG_NO_REPLY) goto get_request; /* don't destroy the reply port right, so we can send an error message */ bufRequest->Head.msgh_remote_port = MACH_PORT_NULL; __mach_msg_destroy(&bufRequest->Head); } if (bufReply->Head.msgh_remote_port == MACH_PORT_NULL) { /* no reply port, so destroy the reply */ if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) __mach_msg_destroy(&bufReply->Head); goto get_request; } /* send reply and get next request */ bufTemp = bufRequest; bufRequest = bufReply; bufReply = bufTemp; mr = __mach_msg(&bufRequest->Head, MACH_SEND_MSG|MACH_RCV_MSG|option, bufRequest->Head.msgh_size, max_size, rcv_name, timeout, MACH_PORT_NULL); } /* a message error occurred */ if (mr != MACH_SEND_INVALID_DEST) break; /* the reply can't be delivered, so destroy it */ __mach_msg_destroy(&bufRequest->Head); } free((char *) bufRequest); free((char *) bufReply); return mr; } mach_msg_return_t __mach_msg_server (demux, max_size, rcv_name) boolean_t (*demux) (); mach_msg_size_t max_size; mach_port_t rcv_name; { return __mach_msg_server_timeout (demux, max_size, rcv_name, option, MACH_MSG_TIMEOUT_NONE); }