summaryrefslogtreecommitdiffstats
path: root/src/ccapi/server/mac/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ccapi/server/mac/main.c')
-rw-r--r--src/ccapi/server/mac/main.c233
1 files changed, 233 insertions, 0 deletions
diff --git a/src/ccapi/server/mac/main.c b/src/ccapi/server/mac/main.c
new file mode 100644
index 000000000..0753a240b
--- /dev/null
+++ b/src/ccapi/server/mac/main.c
@@ -0,0 +1,233 @@
+/*
+ * $Header$
+ *
+ * Copyright 2006 Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "ccs_common.h"
+
+#include <syslog.h>
+#include <Kerberos/kipc_server.h>
+#include "cci_mig_requestServer.h"
+#include "cci_mig_reply.h"
+#include "ccs_os_server.h"
+
+/* ------------------------------------------------------------------------ */
+
+static boolean_t ccs_server_demux (mach_msg_header_t *request,
+ mach_msg_header_t *reply)
+{
+ boolean_t handled = false;
+
+ if (!handled) {
+ handled = ccs_server (request, reply);
+ }
+
+ if (!handled && request->msgh_id == MACH_NOTIFY_NO_SENDERS) {
+ kern_return_t err = KERN_SUCCESS;
+
+ err = ccs_server_remove_client (request->msgh_local_port);
+
+ if (!err) {
+ /* Check here for a client in our table and free rights associated with it */
+ err = mach_port_mod_refs (mach_task_self (), request->msgh_local_port,
+ MACH_PORT_RIGHT_RECEIVE, -1);
+ }
+
+ if (!err) {
+ handled = 1; /* was a port we are tracking */
+ }
+
+ cci_check_error (err);
+ }
+
+ return handled;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int main (int argc, const char *argv[])
+{
+ cc_int32 err = 0;
+
+ openlog (argv[0], LOG_CONS | LOG_PID, LOG_AUTH);
+ syslog (LOG_INFO, "Starting up.");
+
+ if (!err) {
+ err = ccs_server_initialize ();
+ }
+
+ if (!err) {
+ err = kipc_server_run_server (ccs_server_demux);
+ }
+
+ /* cleanup ccs resources */
+ ccs_server_cleanup ();
+
+ syslog (LOG_NOTICE, "Exiting: %s (%d)", kipc_error_string (err), err);
+
+ /* exit */
+ return err ? 1 : 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+kern_return_t ccs_mipc_create_client_connection (mach_port_t in_server_port,
+ mach_port_t *out_connection_port)
+{
+ kern_return_t err = KERN_SUCCESS;
+ mach_port_t connection_port = MACH_PORT_NULL;
+ mach_port_t old_notification_target = MACH_PORT_NULL;
+
+ if (!err) {
+ err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &connection_port);
+ }
+
+ if (!err) {
+ err = mach_port_move_member (mach_task_self (), connection_port, kipc_server_get_listen_portset ());
+ }
+
+ if (!err) {
+ /* request no-senders notification so we can tell when client quits/crashes */
+ err = mach_port_request_notification (mach_task_self (), connection_port,
+ MACH_NOTIFY_NO_SENDERS, 1, connection_port,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE, &old_notification_target );
+ }
+
+ if (!err) {
+ err = ccs_server_add_client (connection_port);
+ }
+
+ if (!err) {
+ *out_connection_port = connection_port;
+ connection_port = MACH_PORT_NULL;
+ }
+
+ if (MACH_PORT_VALID (connection_port)) { mach_port_deallocate (mach_task_self (), connection_port); }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_os_server_send_reply (ccs_pipe_t in_reply_pipe,
+ cci_stream_t in_reply_stream)
+{
+ kern_return_t err = KERN_SUCCESS;
+ cci_mipc_inl_reply_t inl_reply;
+ mach_msg_type_number_t inl_reply_length = 0;
+ cci_mipc_ool_reply_t ool_reply = NULL;
+ mach_msg_type_number_t ool_reply_length = 0;
+
+ if (!ccs_pipe_valid (in_reply_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!in_reply_stream ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ /* depending on how big the message is, use the fast inline buffer or
+ * the slow dynamically allocated buffer */
+ mach_msg_type_number_t reply_length = cci_stream_size (in_reply_stream);
+
+ if (reply_length > kCCAPIMaxILMsgSize) {
+ cci_debug_printf ("%s choosing out of line buffer (size is %d)",
+ __FUNCTION__, reply_length);
+
+ err = vm_read (mach_task_self (),
+ (vm_address_t) cci_stream_data (in_reply_stream), reply_length,
+ (vm_address_t *) &ool_reply, &ool_reply_length);
+
+ } else {
+ //cci_debug_printf ("%s choosing in line buffer (size is %d)",
+ // __FUNCTION__, reply_length);
+
+ inl_reply_length = reply_length;
+ memcpy (inl_reply, cci_stream_data (in_reply_stream), reply_length);
+ }
+ }
+
+ if (!err) {
+ err = ccs_mipc_reply (ccs_pipe_os (in_reply_pipe),
+ inl_reply, inl_reply_length,
+ ool_reply, ool_reply_length);
+ }
+
+ if (!err) {
+ /* Because we use ",dealloc" ool_reply will be freed by mach. Don't double free it. */
+ ool_reply = NULL;
+ ool_reply_length = 0;
+ }
+
+ if (ool_reply_length) { vm_deallocate (mach_task_self (), (vm_address_t) ool_reply, ool_reply_length); }
+
+ return cci_check_error (err);
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+kern_return_t ccs_mipc_request (mach_port_t in_connection_port,
+ mach_port_t in_reply_port,
+ cci_mipc_inl_request_t in_inl_request,
+ mach_msg_type_number_t in_inl_requestCnt,
+ cci_mipc_ool_request_t in_ool_request,
+ mach_msg_type_number_t in_ool_requestCnt)
+{
+ kern_return_t err = KERN_SUCCESS;
+ cci_stream_t request_stream = NULL;
+ ccs_pipe_t connection_pipe = NULL;
+ ccs_pipe_t reply_pipe = NULL;
+
+ if (!err) {
+ err = cci_stream_new (&request_stream);
+ }
+
+ if (!err) {
+ if (in_inl_requestCnt) {
+ err = cci_stream_write (request_stream, in_inl_request, in_inl_requestCnt);
+
+ } else if (in_ool_requestCnt) {
+ err = cci_stream_write (request_stream, in_ool_request, in_ool_requestCnt);
+
+ } else {
+ err = cci_check_error (ccErrBadInternalMessage);
+ }
+ }
+
+ if (!err) {
+ err = ccs_pipe_new (&connection_pipe, in_connection_port);
+ }
+
+ if (!err) {
+ err = ccs_pipe_new (&reply_pipe, in_reply_port);
+ }
+
+ if (!err) {
+ err = ccs_server_handle_request (connection_pipe, reply_pipe, request_stream);
+ }
+
+ ccs_pipe_release (connection_pipe);
+ ccs_pipe_release (reply_pipe);
+ cci_stream_release (request_stream);
+ if (in_ool_requestCnt) { vm_deallocate (mach_task_self (), (vm_address_t) in_ool_request, in_ool_requestCnt); }
+
+ return cci_check_error (err);
+}