summaryrefslogtreecommitdiffstats
path: root/src/ccapi/server
diff options
context:
space:
mode:
authorAlexandra Ellwood <lxs@mit.edu>2007-05-31 21:06:54 +0000
committerAlexandra Ellwood <lxs@mit.edu>2007-05-31 21:06:54 +0000
commitd45eeb7f708d5be2e9fbdbc54a04655776074f6c (patch)
tree5ab3d7e31f285ac4d6900d3abc647cbb53a05f8d /src/ccapi/server
parent66bd29f512b9bdd5e808d645118862112973d2d6 (diff)
downloadkrb5-d45eeb7f708d5be2e9fbdbc54a04655776074f6c.tar.gz
krb5-d45eeb7f708d5be2e9fbdbc54a04655776074f6c.tar.xz
krb5-d45eeb7f708d5be2e9fbdbc54a04655776074f6c.zip
Move CCAPI sources to krb5 repository
ticket: new status: open git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@19564 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/ccapi/server')
-rw-r--r--src/ccapi/server/ccs_array.c145
-rw-r--r--src/ccapi/server/ccs_array.h71
-rw-r--r--src/ccapi/server/ccs_cache_collection.c949
-rw-r--r--src/ccapi/server/ccs_cache_collection.h73
-rw-r--r--src/ccapi/server/ccs_ccache.c1002
-rw-r--r--src/ccapi/server/ccs_ccache.h78
-rw-r--r--src/ccapi/server/ccs_ccache_iterator.c156
-rw-r--r--src/ccapi/server/ccs_ccache_iterator.h38
-rw-r--r--src/ccapi/server/ccs_common.h44
-rw-r--r--src/ccapi/server/ccs_credentials.c136
-rw-r--r--src/ccapi/server/ccs_credentials.h46
-rw-r--r--src/ccapi/server/ccs_credentials_iterator.c158
-rw-r--r--src/ccapi/server/ccs_credentials_iterator.h38
-rw-r--r--src/ccapi/server/ccs_list.c345
-rw-r--r--src/ccapi/server/ccs_list.h129
-rw-r--r--src/ccapi/server/ccs_list_internal.c612
-rw-r--r--src/ccapi/server/ccs_list_internal.h92
-rw-r--r--src/ccapi/server/ccs_lock.c245
-rw-r--r--src/ccapi/server/ccs_lock.h61
-rw-r--r--src/ccapi/server/ccs_lock_state.c543
-rw-r--r--src/ccapi/server/ccs_lock_state.h57
-rw-r--r--src/ccapi/server/ccs_os_pipe.h44
-rw-r--r--src/ccapi/server/ccs_os_server.h35
-rw-r--r--src/ccapi/server/ccs_pipe.c163
-rw-r--r--src/ccapi/server/ccs_pipe.h52
-rw-r--r--src/ccapi/server/ccs_server.c333
-rw-r--r--src/ccapi/server/ccs_server.h50
-rw-r--r--src/ccapi/server/ccs_types.h93
-rw-r--r--src/ccapi/server/mac/CCacheServerInfo.plist38
-rw-r--r--src/ccapi/server/mac/ccs_os_pipe.c79
-rw-r--r--src/ccapi/server/mac/edu.mit.Kerberos.CCacheServer.plist17
-rw-r--r--src/ccapi/server/mac/main.c233
32 files changed, 6155 insertions, 0 deletions
diff --git a/src/ccapi/server/ccs_array.c b/src/ccapi/server/ccs_array.c
new file mode 100644
index 000000000..c798c7a3a
--- /dev/null
+++ b/src/ccapi/server/ccs_array.c
@@ -0,0 +1,145 @@
+/*
+ * $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 "cci_array_internal.h"
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_pipe_object_release (void *io_pipe)
+{
+ return cci_check_error (ccs_pipe_release ((ccs_pipe_t) io_pipe));
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_pipe_array_new (ccs_pipe_array_t *out_array)
+{
+ return cci_array_new (out_array, ccs_pipe_object_release);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_pipe_array_release (ccs_pipe_array_t io_array)
+{
+ return cci_array_release (io_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_uint64 ccs_pipe_array_count (ccs_pipe_array_t in_array)
+{
+ return cci_array_count (in_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline ccs_pipe_t ccs_pipe_array_object_at_index (ccs_pipe_array_t io_array,
+ cc_uint64 in_position)
+{
+ return cci_array_object_at_index (io_array, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_pipe_array_insert (ccs_pipe_array_t io_array,
+ ccs_pipe_t in_pipe,
+ cc_uint64 in_position)
+{
+ return cci_array_insert (io_array, in_pipe, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_pipe_array_remove (ccs_pipe_array_t io_array,
+ cc_uint64 in_position)
+{
+ return cci_array_remove (io_array, in_position);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_lock_object_release (void *io_lock)
+{
+ return cci_check_error (ccs_lock_release ((ccs_lock_t) io_lock));
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_lock_array_new (ccs_lock_array_t *out_array)
+{
+ return cci_array_new (out_array, ccs_lock_object_release);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_lock_array_release (ccs_lock_array_t io_array)
+{
+ return cci_array_release (io_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_uint64 ccs_lock_array_count (ccs_lock_array_t in_array)
+{
+ return cci_array_count (in_array);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline ccs_lock_t ccs_lock_array_object_at_index (ccs_lock_array_t io_array,
+ cc_uint64 in_position)
+{
+ return cci_array_object_at_index (io_array, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_lock_array_insert (ccs_lock_array_t io_array,
+ ccs_lock_t in_lock,
+ cc_uint64 in_position)
+{
+ return cci_array_insert (io_array, in_lock, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_lock_array_remove (ccs_lock_array_t io_array,
+ cc_uint64 in_position)
+{
+ return cci_array_remove (io_array, in_position);
+}
+
+/* ------------------------------------------------------------------------ */
+inline cc_int32 ccs_lock_array_move (ccs_lock_array_t io_array,
+ cc_uint64 in_position,
+ cc_uint64 in_new_position,
+ cc_uint64 *out_real_new_position)
+{
+ return cci_array_move (io_array, in_position, in_new_position, out_real_new_position);
+}
diff --git a/src/ccapi/server/ccs_array.h b/src/ccapi/server/ccs_array.h
new file mode 100644
index 000000000..865647c1c
--- /dev/null
+++ b/src/ccapi/server/ccs_array.h
@@ -0,0 +1,71 @@
+/*
+ * $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.
+ */
+
+#ifndef CCS_ARRAY_H
+#define CCS_ARRAY_H
+
+#include "ccs_types.h"
+
+inline cc_int32 ccs_pipe_array_new (ccs_pipe_array_t *out_array);
+
+inline cc_int32 ccs_pipe_array_release (ccs_pipe_array_t io_array);
+
+inline cc_uint64 ccs_pipe_array_count (ccs_pipe_array_t in_array);
+
+inline ccs_pipe_t ccs_pipe_array_object_at_index (ccs_pipe_array_t io_array,
+ cc_uint64 in_position);
+
+inline cc_int32 ccs_pipe_array_insert (ccs_pipe_array_t io_array,
+ ccs_pipe_t in_pipe,
+ cc_uint64 in_position);
+
+inline cc_int32 ccs_pipe_array_remove (ccs_pipe_array_t io_array,
+ cc_uint64 in_position);
+
+#pragma mark -
+
+inline cc_int32 ccs_lock_array_new (ccs_lock_array_t *out_array);
+
+inline cc_int32 ccs_lock_array_release (ccs_lock_array_t io_array);
+
+inline cc_uint64 ccs_lock_array_count (ccs_lock_array_t in_array);
+
+inline ccs_lock_t ccs_lock_array_object_at_index (ccs_lock_array_t io_array,
+ cc_uint64 in_position);
+
+inline cc_int32 ccs_lock_array_insert (ccs_lock_array_t io_array,
+ ccs_lock_t in_lock,
+ cc_uint64 in_position);
+
+inline cc_int32 ccs_lock_array_remove (ccs_lock_array_t io_array,
+ cc_uint64 in_position);
+
+inline cc_int32 ccs_lock_array_move (ccs_lock_array_t io_array,
+ cc_uint64 in_position,
+ cc_uint64 in_new_position,
+ cc_uint64 *out_real_new_position);
+
+#endif /* CCS_ARRAY_H */
diff --git a/src/ccapi/server/ccs_cache_collection.c b/src/ccapi/server/ccs_cache_collection.c
new file mode 100644
index 000000000..4927aaacb
--- /dev/null
+++ b/src/ccapi/server/ccs_cache_collection.c
@@ -0,0 +1,949 @@
+/*
+ * $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"
+
+struct ccs_cache_collection_d {
+ cc_time_t last_changed_time;
+ cc_uint64 next_unique_name;
+ cci_identifier_t identifier;
+ ccs_lock_state_t lock_state;
+ ccs_ccache_list_t ccaches;
+};
+
+struct ccs_cache_collection_d ccs_cache_collection_initializer = { 0, 0, NULL, NULL, NULL };
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_new (ccs_cache_collection_t *out_cache_collection)
+{
+ cc_int32 err = ccNoError;
+ ccs_cache_collection_t cache_collection = NULL;
+
+ if (!out_cache_collection) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ cache_collection = malloc (sizeof (*cache_collection));
+ if (cache_collection) {
+ *cache_collection = ccs_cache_collection_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ err = ccs_server_new_identifier (&cache_collection->identifier);
+ }
+
+ if (!err) {
+ err = ccs_lock_state_new (&cache_collection->lock_state,
+ ccErrInvalidContext,
+ ccErrContextLocked,
+ ccErrContextUnlocked);
+ }
+
+ if (!err) {
+ err = ccs_ccache_list_new (&cache_collection->ccaches);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_changed (cache_collection);
+ }
+
+ if (!err) {
+ *out_cache_collection = cache_collection;
+ cache_collection = NULL;
+ }
+
+ ccs_cache_collection_release (cache_collection);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_cache_collection_release (ccs_cache_collection_t io_cache_collection)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_cache_collection) { err = ccErrBadParam; }
+
+ if (!err) {
+ cci_identifier_release (io_cache_collection->identifier);
+ ccs_lock_state_release (io_cache_collection->lock_state);
+ ccs_ccache_list_release (io_cache_collection->ccaches);
+ free (io_cache_collection);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_cache_collection_compare_identifier (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_equal ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_compare (in_cache_collection->identifier,
+ in_identifier,
+ out_equal);
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_changed (ccs_cache_collection_t io_cache_collection)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ cc_time_t now = time (NULL);
+
+ if (io_cache_collection->last_changed_time < now) {
+ io_cache_collection->last_changed_time = now;
+ } else {
+ io_cache_collection->last_changed_time++;
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_find_ccache_by_name (ccs_cache_collection_t in_cache_collection,
+ const char *in_name,
+ ccs_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_list_iterator_t iterator = NULL;
+
+ if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_name ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches, &iterator);
+ }
+
+ while (!err) {
+ ccs_ccache_t ccache = NULL;
+
+ err = ccs_ccache_list_iterator_next (iterator, &ccache);
+
+ if (!err) {
+ cc_uint32 equal = 0;
+
+ err = ccs_ccache_compare_name (ccache, in_name, &equal);
+
+ if (!err && equal) {
+ *out_ccache = ccache;
+ break;
+ }
+ }
+ }
+ if (err == ccIteratorEnd) { err = ccErrCCacheNotFound; }
+
+ if (iterator) { ccs_ccache_list_iterator_release (iterator); }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_find_ccache (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier,
+ ccs_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_ccache_list_find (in_cache_collection->ccaches,
+ in_identifier, out_ccache);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_collection_move_ccache (ccs_cache_collection_t io_cache_collection,
+ cci_identifier_t in_source_identifier,
+ ccs_ccache_t io_destination_ccache)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_t source_ccache = NULL;
+
+ if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_source_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_destination_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_cache_collection_find_ccache (io_cache_collection,
+ in_source_identifier,
+ &source_ccache);
+ }
+
+ if (!err) {
+ err = ccs_ccache_swap_contents (source_ccache, io_destination_ccache);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_destroy_ccache (io_cache_collection,
+ in_source_identifier);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_destroy_ccache (ccs_cache_collection_t io_cache_collection,
+ cci_identifier_t in_identifier)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_ccache_list_remove (io_cache_collection->ccaches,
+ in_identifier);
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_find_ccache_iterator (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier,
+ ccs_ccache_iterator_t *out_ccache_iterator)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_ccache_list_find_iterator (in_cache_collection->ccaches,
+ in_identifier,
+ out_ccache_iterator);
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_find_credentials_iterator (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier,
+ ccs_ccache_t *out_ccache,
+ ccs_credentials_iterator_t *out_credentials_iterator)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_list_iterator_t iterator = NULL;
+
+ if (!in_cache_collection ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches, &iterator);
+ }
+
+ while (!err) {
+ ccs_ccache_t ccache = NULL;
+
+ err = ccs_ccache_list_iterator_next (iterator, &ccache);
+
+ if (!err) {
+ cc_int32 terr = ccs_ccache_find_credentials_iterator (ccache,
+ in_identifier,
+ out_credentials_iterator);
+ if (!terr) {
+ *out_ccache = ccache;
+ break;
+ }
+ }
+ }
+ if (err == ccIteratorEnd) { err = cci_check_error (ccErrInvalidCredentialsIterator); }
+
+ if (iterator) { ccs_ccache_list_iterator_release (iterator); }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_get_next_unique_ccache_name (ccs_cache_collection_t io_cache_collection,
+ char **out_name)
+{
+ cc_int32 err = ccNoError;
+ cc_uint64 count = 0;
+ char *name = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!out_name ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_cache_collection_list_count (io_cache_collection->ccaches, &count);
+ }
+
+ if (!err) {
+ if (count > 0) {
+ while (!err) {
+ int ret = asprintf (&name, "%lld", io_cache_collection->next_unique_name++);
+ if (ret < 0 || !name) { err = cci_check_error (ccErrNoMem); }
+
+ if (!err) {
+ ccs_ccache_t ccache = NULL; /* temporary to hold ccache pointer */
+ err = ccs_cache_collection_find_ccache_by_name (io_cache_collection,
+ name, &ccache);
+ }
+
+ if (err == ccErrCCacheNotFound) {
+ err = ccNoError;
+ break; /* found a unique one */
+ }
+ }
+ } else {
+ name = strdup (k_cci_context_initial_ccache_name);
+ if (!name) { err = cci_check_error (ccErrNoMem); }
+ }
+ }
+
+ if (!err) {
+ *out_name = name;
+ name = NULL;
+ }
+
+ free (name);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_get_default_ccache (ccs_cache_collection_t in_cache_collection,
+ ccs_ccache_t *out_ccache)
+{
+ cc_int32 err = ccNoError;
+ cc_uint64 count = 0;
+
+ if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!out_ccache ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_ccache_list_count (in_cache_collection->ccaches, &count);
+ }
+
+ if (!err) {
+ if (count > 0) {
+ /* First ccache is the default */
+ ccs_ccache_list_iterator_t iterator = NULL;
+
+ err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches,
+ &iterator);
+
+ if (!err) {
+ err = ccs_ccache_list_iterator_next (iterator, out_ccache);
+ }
+
+ ccs_ccache_list_iterator_release (iterator);
+
+ } else {
+ err = cci_check_error (ccErrCCacheNotFound);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_cache_collection_set_default_ccache (ccs_cache_collection_t io_cache_collection,
+ cci_identifier_t in_identifier)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_t old_default = NULL;
+ ccs_ccache_t new_default = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_cache_collection_get_default_ccache (io_cache_collection,
+ &old_default);
+ }
+
+ if (!err) {
+ err = ccs_ccache_list_push_front (io_cache_collection->ccaches,
+ in_identifier);
+ }
+
+ if (!err) {
+ err = ccs_ccache_notify_default_state_changed (old_default,
+ io_cache_collection,
+ FALSE /* no longer default */);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_get_default_ccache (io_cache_collection,
+ &new_default);
+ }
+
+ if (!err) {
+ err = ccs_ccache_notify_default_state_changed (new_default,
+ io_cache_collection,
+ TRUE /* now default */);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_changed (io_cache_collection);
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+#pragma mark -- IPC Messages --
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_context_release (ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ /* Currently does nothing */
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_sync (ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_write (io_cache_collection->identifier, io_reply_data);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_get_change_time (ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_write_time (io_reply_data, io_cache_collection->last_changed_time);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_get_default_ccache_name (ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint64 count = 0;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_cache_collection_list_count (io_cache_collection->ccaches, &count);
+ }
+
+ if (!err) {
+ if (count > 0) {
+ ccs_ccache_t ccache = NULL;
+
+ err = ccs_cache_collection_get_default_ccache (io_cache_collection, &ccache);
+
+ if (!err) {
+ err = ccs_ccache_write_name (ccache, io_reply_data);
+ }
+ } else {
+ err = cci_stream_write_string (io_reply_data,
+ k_cci_context_initial_ccache_name);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_open_ccache (ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ char *name = NULL;
+ ccs_ccache_t ccache = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_read_string (in_request_data, &name);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_find_ccache_by_name (io_cache_collection,
+ name, &ccache);
+ }
+
+ if (!err) {
+ err = ccs_ccache_write (ccache, io_reply_data);
+ }
+
+ free (name);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_open_default_ccache (ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_t ccache = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_cache_collection_get_default_ccache (io_cache_collection,
+ &ccache);
+ }
+
+ if (!err) {
+ err = ccs_ccache_write (ccache, io_reply_data);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_create_ccache (ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ char *name = NULL;
+ cc_uint32 cred_vers;
+ char *principal = NULL;
+ ccs_ccache_t ccache = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_read_string (in_request_data, &name);
+ }
+
+ if (!err) {
+ err = cci_stream_read_uint32 (in_request_data, &cred_vers);
+ }
+
+ if (!err) {
+ err = cci_stream_read_string (in_request_data, &principal);
+ }
+
+ if (!err) {
+ cc_int32 terr = ccs_cache_collection_find_ccache_by_name (io_cache_collection,
+ name,
+ &ccache);
+
+ if (!terr) {
+ err = ccs_ccache_reset (ccache, cred_vers, principal);
+
+ } else {
+ err = ccs_ccache_new (&ccache, cred_vers, name, principal,
+ io_cache_collection->ccaches);
+ }
+ }
+
+ if (!err) {
+ err = ccs_ccache_write (ccache, io_reply_data);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_changed (io_cache_collection);
+ }
+
+ free (name);
+ free (principal);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_create_default_ccache (ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 cred_vers;
+ char *principal = NULL;
+ ccs_ccache_t ccache = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_read_uint32 (in_request_data, &cred_vers);
+ }
+
+ if (!err) {
+ err = cci_stream_read_string (in_request_data, &principal);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_get_default_ccache (io_cache_collection,
+ &ccache);
+
+ if (!err) {
+ err = ccs_ccache_reset (ccache, cred_vers, principal);
+
+ } else if (err == ccErrCCacheNotFound) {
+ char *name = NULL;
+
+ err = ccs_cache_collection_get_next_unique_ccache_name (io_cache_collection,
+ &name);
+
+ if (!err) {
+ err = ccs_ccache_new (&ccache, cred_vers, name, principal,
+ io_cache_collection->ccaches);
+ }
+
+ free (name);
+ }
+ }
+
+ if (!err) {
+ err = ccs_ccache_write (ccache, io_reply_data);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_changed (io_cache_collection);
+ }
+
+ free (principal);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_create_new_ccache (ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 cred_vers;
+ char *principal = NULL;
+ char *name = NULL;
+ ccs_ccache_t ccache = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_read_uint32 (in_request_data, &cred_vers);
+ }
+
+ if (!err) {
+ err = cci_stream_read_string (in_request_data, &principal);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_get_next_unique_ccache_name (io_cache_collection,
+ &name);
+ }
+
+ if (!err) {
+ err = ccs_ccache_new (&ccache, cred_vers, name, principal,
+ io_cache_collection->ccaches);
+ }
+
+ if (!err) {
+ err = ccs_ccache_write (ccache, io_reply_data);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_changed (io_cache_collection);
+ }
+
+ free (name);
+ free (principal);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_new_ccache_iterator (ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_iterator_t ccache_iterator = NULL;
+
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_ccache_list_new_iterator (io_cache_collection->ccaches,
+ &ccache_iterator);
+ }
+
+ if (!err) {
+ err = ccs_ccache_list_iterator_write (ccache_iterator, io_reply_data);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_lock (ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cc_uint32 *out_will_block,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 lock_type;
+ cc_uint32 block;
+
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_will_block ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_read_uint32 (in_request_data, &lock_type);
+ }
+
+ if (!err) {
+ err = cci_stream_read_uint32 (in_request_data, &block);
+ }
+
+ if (!err) {
+ err = ccs_lock_state_add (io_cache_collection->lock_state,
+ in_client_pipe, in_reply_pipe,
+ lock_type, block, out_will_block);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_unlock (ccs_pipe_t in_client_pipe,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_lock_state_remove (io_cache_collection->lock_state,
+ in_client_pipe);
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+ cc_int32 ccs_cache_collection_handle_message (ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ ccs_cache_collection_t io_cache_collection,
+ enum cci_msg_id_t in_request_name,
+ cci_stream_t in_request_data,
+ cc_uint32 *out_will_block,
+ cci_stream_t *out_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 will_block = 0;
+ cci_stream_t reply_data = NULL;
+
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_will_block ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_new (&reply_data);
+ }
+
+ if (!err) {
+ if (in_request_name == cci_context_release_msg_id) {
+ err = ccs_cache_collection_context_release (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_sync_msg_id) {
+ err = ccs_cache_collection_sync (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_get_change_time_msg_id) {
+ err = ccs_cache_collection_get_change_time (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_get_default_ccache_name_msg_id) {
+ err = ccs_cache_collection_get_default_ccache_name (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_open_ccache_msg_id) {
+ err = ccs_cache_collection_open_ccache (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_open_default_ccache_msg_id) {
+ err = ccs_cache_collection_open_default_ccache (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_create_ccache_msg_id) {
+ err = ccs_cache_collection_create_ccache (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_create_default_ccache_msg_id) {
+ err = ccs_cache_collection_create_default_ccache (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_create_new_ccache_msg_id) {
+ err = ccs_cache_collection_create_new_ccache (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_new_ccache_iterator_msg_id) {
+ err = ccs_cache_collection_new_ccache_iterator (io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_context_lock_msg_id) {
+ err = ccs_cache_collection_lock (in_client_pipe, in_reply_pipe,
+ io_cache_collection,
+ in_request_data,
+ &will_block, reply_data);
+
+ } else if (in_request_name == cci_context_unlock_msg_id) {
+ err = ccs_cache_collection_unlock (in_client_pipe, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else {
+ err = ccErrBadInternalMessage;
+ }
+ }
+
+ if (!err) {
+ *out_will_block = will_block;
+ *out_reply_data = reply_data;
+ reply_data = NULL; /* take ownership */
+ }
+
+ cci_stream_release (reply_data);
+
+ return cci_check_error (err);
+}
diff --git a/src/ccapi/server/ccs_cache_collection.h b/src/ccapi/server/ccs_cache_collection.h
new file mode 100644
index 000000000..4d663f992
--- /dev/null
+++ b/src/ccapi/server/ccs_cache_collection.h
@@ -0,0 +1,73 @@
+/*
+ * $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.
+ */
+
+#ifndef CCS_CACHE_COLLECTION_H
+#define CCS_CACHE_COLLECTION_H
+
+#include "ccs_types.h"
+
+cc_int32 ccs_cache_collection_new (ccs_cache_collection_t *out_cache_collection);
+
+inline cc_int32 ccs_cache_collection_release (ccs_cache_collection_t io_cache_collection);
+
+inline cc_int32 ccs_cache_collection_compare_identifier (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier,
+ cc_uint32 *out_equal);
+
+cc_int32 ccs_cache_collection_changed (ccs_cache_collection_t io_cache_collection);
+
+cc_int32 ccs_cache_collection_set_default_ccache (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier);
+
+cc_int32 ccs_cache_collection_find_ccache (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier,
+ ccs_ccache_t *out_ccache);
+
+cc_int32 ccs_ccache_collection_move_ccache (ccs_cache_collection_t io_cache_collection,
+ cci_identifier_t in_source_identifier,
+ ccs_ccache_t io_destination_ccache);
+
+cc_int32 ccs_cache_collection_destroy_ccache (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier);
+
+cc_int32 ccs_cache_collection_find_ccache_iterator (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier,
+ ccs_ccache_iterator_t *out_ccache_iterator);
+
+cc_int32 ccs_cache_collection_find_credentials_iterator (ccs_cache_collection_t in_cache_collection,
+ cci_identifier_t in_identifier,
+ ccs_ccache_t *out_ccache,
+ ccs_credentials_iterator_t *out_credentials_iterator);
+
+cc_int32 ccs_cache_collection_handle_message (ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ ccs_cache_collection_t io_cache_collection,
+ enum cci_msg_id_t in_request_name,
+ cci_stream_t in_request_data,
+ cc_uint32 *out_will_block,
+ cci_stream_t *out_reply_data);
+
+#endif /* CCS_CACHE_COLLECTION_H */
diff --git a/src/ccapi/server/ccs_ccache.c b/src/ccapi/server/ccs_ccache.c
new file mode 100644
index 000000000..aaeed9796
--- /dev/null
+++ b/src/ccapi/server/ccs_ccache.c
@@ -0,0 +1,1002 @@
+/*
+ * $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"
+
+struct ccs_ccache_d {
+ cci_identifier_t identifier;
+ ccs_lock_state_t lock_state;
+ cc_uint32 cred_vers;
+ char *name;
+ char *principal;
+ cc_time_t last_default_time;
+ cc_time_t last_changed_time;
+ cc_uint32 kdc_time_offset_v4_valid;
+ cc_time_t kdc_time_offset_v4;
+ cc_uint32 kdc_time_offset_v5_valid;
+ cc_time_t kdc_time_offset_v5;
+ ccs_credentials_list_t credentials;
+};
+
+struct ccs_ccache_d ccs_ccache_initializer = { NULL, NULL, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, NULL };
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_new (ccs_ccache_t *out_ccache,
+ cc_uint32 in_cred_vers,
+ const char *in_name,
+ const char *in_principal,
+ ccs_ccache_list_t io_ccache_list)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_t ccache = NULL;
+
+ if (!out_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_name ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_principal) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ ccache = malloc (sizeof (*ccache));
+ if (ccache) {
+ *ccache = ccs_ccache_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ err = ccs_server_new_identifier (&ccache->identifier);
+ }
+
+ if (!err) {
+ err = ccs_lock_state_new (&ccache->lock_state,
+ ccErrInvalidCCache,
+ ccErrCCacheLocked,
+ ccErrCCacheUnlocked);
+ }
+
+ if (!err) {
+ ccache->cred_vers = in_cred_vers;
+
+ if (in_cred_vers != cc_credentials_v4 &&
+ in_cred_vers != cc_credentials_v5) {
+ err = cci_check_error (ccErrBadCredentialsVersion);
+ }
+ }
+
+ if (!err) {
+ ccache->name = strdup (in_name);
+ if (!ccache->name) { err = cci_check_error (ccErrNoMem); }
+ }
+
+ if (!err) {
+ ccache->principal = strdup (in_principal);
+ if (!ccache->principal) { err = cci_check_error (ccErrNoMem); }
+ }
+
+ if (!err) {
+ err = ccs_credentials_list_new (&ccache->credentials);
+ }
+
+ if (!err) {
+ cc_uint64 now = time (NULL);
+ cc_uint64 count = 0;
+
+ err = ccs_ccache_list_count (io_ccache_list, &count);
+
+ if (!err) {
+ /* first cache is default */
+ ccache->last_default_time = (count == 0) ? now : 0;
+ ccache->last_changed_time = now;
+ }
+ }
+
+ if (!err) {
+ /* Add self to the list of ccaches */
+ err = ccs_ccache_list_add (io_ccache_list, ccache);
+ }
+
+ if (!err) {
+ *out_ccache = ccache;
+ ccache = NULL;
+ }
+
+ ccs_ccache_release (ccache);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_reset (ccs_ccache_t io_ccache,
+ cc_uint32 in_cred_vers,
+ const char *in_principal)
+{
+ cc_int32 err = ccNoError;
+ char *principal = NULL;
+ ccs_credentials_list_t credentials = NULL;
+
+ if (!io_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ if (in_cred_vers != cc_credentials_v4 &&
+ in_cred_vers != cc_credentials_v5) {
+ err = cci_check_error (ccErrBadCredentialsVersion);
+ }
+ }
+
+ if (!err) {
+ principal = strdup (in_principal);
+ if (!io_ccache->principal) { err = cci_check_error (ccErrNoMem); }
+ }
+
+ if (!err) {
+ err = ccs_credentials_list_new (&credentials);
+ }
+
+ if (!err) {
+ io_ccache->cred_vers = in_cred_vers;
+
+ free (io_ccache->principal);
+ io_ccache->principal = principal;
+ principal = NULL; /* take ownership */
+
+ ccs_credentials_list_release (io_ccache->credentials);
+ io_ccache->credentials = credentials;
+ credentials = NULL; /* take ownership */
+
+ }
+
+ free (principal);
+ ccs_credentials_list_release (credentials);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_swap_contents (ccs_ccache_t io_source_ccache,
+ ccs_ccache_t io_destination_ccache)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_source_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_destination_ccache) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ struct ccs_ccache_d temp_ccache = *io_destination_ccache;
+
+ /* swap everything */
+ *io_destination_ccache = *io_source_ccache;
+ *io_source_ccache = temp_ccache;
+
+ /* swap back the name and identifier */
+ io_source_ccache->identifier = io_destination_ccache->identifier;
+ io_destination_ccache->identifier = temp_ccache.identifier;
+
+ io_source_ccache->name = io_destination_ccache->name;
+ io_destination_ccache->name = temp_ccache.name;
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_release (ccs_ccache_t io_ccache)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache) { err = ccErrBadParam; }
+
+ if (!err) {
+ cci_identifier_release (io_ccache->identifier);
+ ccs_lock_state_release (io_ccache->lock_state);
+ free (io_ccache->name);
+ free (io_ccache->principal);
+ ccs_credentials_list_release (io_ccache->credentials);
+ free (io_ccache);
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_compare_identifier (ccs_ccache_t in_ccache,
+ cci_identifier_t in_identifier,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+ if (!out_equal ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_compare (in_ccache->identifier,
+ in_identifier,
+ out_equal);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_compare_name (ccs_ccache_t in_ccache,
+ const char *in_name,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_ccache) { err = cci_check_error (ccErrBadParam); }
+ if (!in_name ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_equal) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_equal = (strcmp (in_ccache->name, in_name) == 0);
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_changed (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ cc_time_t now = time (NULL);
+
+ if (io_ccache->last_changed_time < now) {
+ io_ccache->last_changed_time = now;
+ } else {
+ io_ccache->last_changed_time++;
+ }
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_changed (io_cache_collection);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_notify_default_state_changed (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cc_uint32 in_new_default_state)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err && in_new_default_state) {
+ cc_time_t now = time (NULL);
+
+ if (io_ccache->last_default_time < now) {
+ io_ccache->last_default_time = now;
+ } else {
+ io_ccache->last_default_time++;
+ }
+ }
+
+ if (!err) {
+ err = ccs_ccache_changed (io_ccache, io_cache_collection);
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_find_credentials_iterator (ccs_ccache_t in_ccache,
+ cci_identifier_t in_identifier,
+ ccs_credentials_iterator_t *out_credentials_iterator)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_credentials_list_find_iterator (in_ccache->credentials,
+ in_identifier,
+ out_credentials_iterator);
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_write (ccs_ccache_t in_ccache,
+ cci_stream_t io_stream)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_ccache) { err = cci_check_error (ccErrBadParam); }
+ if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_write (in_ccache->identifier, io_stream);
+ }
+
+ return cci_check_error (err);
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_write_name (ccs_ccache_t in_ccache,
+ cci_stream_t io_stream)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_ccache) { err = cci_check_error (ccErrBadParam); }
+ if (!io_stream) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_write_string (io_stream, in_ccache->name);
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+#pragma mark -- IPC Messages --
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_destroy (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_cache_collection_destroy_ccache (io_cache_collection,
+ io_ccache->identifier);
+ }
+
+ if (!err) {
+ /* ccache has been destroyed so just mark the cache collection */
+ err = ccs_cache_collection_changed (io_cache_collection);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_set_default (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_cache_collection_set_default_ccache (io_cache_collection,
+ io_ccache->identifier);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_credentials_version (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_write_uint32 (io_reply_data, io_ccache->cred_vers);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_name (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_write_string (io_reply_data, io_ccache->name);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_principal (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_write_string (io_reply_data, io_ccache->principal);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_set_principal (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ char *principal = NULL;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_read_string (io_reply_data, &principal);
+ }
+
+ if (!err) {
+ free (io_ccache->principal);
+ io_ccache->principal = principal;
+ principal = NULL;
+
+ err = ccs_ccache_changed (io_ccache, io_cache_collection);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_store_credentials (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ ccs_credentials_t credentials = NULL;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_credentials_new (&credentials, in_request_data,
+ io_ccache->credentials);
+ }
+
+ if (!err) {
+ err = ccs_ccache_changed (io_ccache, io_cache_collection);
+ }
+
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_remove_credentials (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cci_identifier_t credentials_identifier = NULL;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_read (&credentials_identifier, in_request_data);
+ }
+
+ if (!err) {
+ err = ccs_credentials_list_remove (io_ccache->credentials, credentials_identifier);
+ }
+
+ if (!err) {
+ err = ccs_ccache_changed (io_ccache, io_cache_collection);
+ }
+
+ cci_identifier_release (credentials_identifier);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_new_credentials_iterator (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ ccs_credentials_iterator_t credentials_iterator = NULL;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_credentials_list_new_iterator (io_ccache->credentials,
+ &credentials_iterator);
+ }
+
+ if (!err) {
+ err = ccs_credentials_list_iterator_write (credentials_iterator, io_reply_data);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_move (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cci_identifier_t source_identifier = NULL;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ /* Note: message is sent as the destination ccache to avoid */
+ /* extra work on the server when deleting it the source ccache. */
+ err = cci_identifier_read (&source_identifier, in_request_data);
+ }
+
+ if (!err) {
+ err = ccs_ccache_collection_move_ccache (io_cache_collection,
+ source_identifier,
+ io_ccache);
+ }
+
+ if (!err) {
+ err = ccs_ccache_changed (io_ccache, io_cache_collection);
+ }
+
+ cci_identifier_release (source_identifier);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_lock (ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cc_uint32 *out_will_block,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 lock_type;
+ cc_uint32 block;
+
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_will_block ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_read_uint32 (in_request_data, &lock_type);
+ }
+
+ if (!err) {
+ err = cci_stream_read_uint32 (in_request_data, &block);
+ }
+
+ if (!err) {
+ err = ccs_lock_state_add (io_ccache->lock_state,
+ in_client_pipe, in_reply_pipe,
+ lock_type, block, out_will_block);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_unlock (ccs_pipe_t in_client_pipe,
+ ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_lock_state_remove (io_ccache->lock_state, in_client_pipe);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_last_default_time (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err && io_ccache->last_default_time == 0) {
+ err = cci_check_error (ccErrNeverDefault);
+ }
+
+ if (!err) {
+ err = cci_stream_write_time (io_reply_data, io_ccache->last_default_time);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_change_time (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_write_time (io_reply_data, io_ccache->last_changed_time);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_get_kdc_time_offset (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 cred_vers = 0;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_read_uint32 (in_request_data, &cred_vers);
+ }
+
+ if (!err) {
+ if (cred_vers == cc_credentials_v4) {
+ if (io_ccache->kdc_time_offset_v4_valid) {
+ err = cci_stream_write_time (io_reply_data, io_ccache->kdc_time_offset_v4);
+ } else {
+ err = cci_check_error (ccErrTimeOffsetNotSet);
+ }
+
+ } else if (cred_vers == cc_credentials_v5) {
+ if (io_ccache->kdc_time_offset_v5_valid) {
+ err = cci_stream_write_time (io_reply_data, io_ccache->kdc_time_offset_v5);
+ } else {
+ err = cci_check_error (ccErrTimeOffsetNotSet);
+ }
+
+ } else {
+ err = cci_check_error (ccErrBadCredentialsVersion);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_set_kdc_time_offset (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 cred_vers = 0;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_read_uint32 (in_request_data, &cred_vers);
+ }
+
+ if (!err) {
+ if (cred_vers == cc_credentials_v4) {
+ err = cci_stream_read_time (in_request_data, &io_ccache->kdc_time_offset_v4);
+
+ if (!err) {
+ io_ccache->kdc_time_offset_v4_valid = 1;
+ }
+ } else if (cred_vers == cc_credentials_v5) {
+ err = cci_stream_read_time (in_request_data, &io_ccache->kdc_time_offset_v5);
+
+ if (!err) {
+ io_ccache->kdc_time_offset_v5_valid = 1;
+ }
+ } else {
+ err = cci_check_error (ccErrBadCredentialsVersion);
+ }
+ }
+
+ if (!err) {
+ err = ccs_ccache_changed (io_ccache, io_cache_collection);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_clear_kdc_time_offset (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 cred_vers = 0;
+
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_read_uint32 (in_request_data, &cred_vers);
+ }
+
+ if (!err) {
+ if (cred_vers == cc_credentials_v4) {
+ io_ccache->kdc_time_offset_v4 = 0;
+ io_ccache->kdc_time_offset_v4_valid = 0;
+
+ } else if (cred_vers == cc_credentials_v5) {
+ io_ccache->kdc_time_offset_v5 = 0;
+ io_ccache->kdc_time_offset_v5_valid = 0;
+
+ } else {
+ err = cci_check_error (ccErrBadCredentialsVersion);
+ }
+ }
+
+ if (!err) {
+ err = ccs_ccache_changed (io_ccache, io_cache_collection);
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_ccache_handle_message (ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ enum cci_msg_id_t in_request_name,
+ cci_stream_t in_request_data,
+ cc_uint32 *out_will_block,
+ cci_stream_t *out_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 will_block = 0;
+ cci_stream_t reply_data = NULL;
+
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_will_block ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_new (&reply_data);
+ }
+
+ if (!err) {
+ if (in_request_name == cci_ccache_destroy_msg_id) {
+ err = ccs_ccache_destroy (io_ccache, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_ccache_set_default_msg_id) {
+ err = ccs_ccache_set_default (io_ccache, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_ccache_get_credentials_version_msg_id) {
+ err = ccs_ccache_get_credentials_version (io_ccache, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_ccache_get_name_msg_id) {
+ err = ccs_ccache_get_name (io_ccache, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_ccache_get_principal_msg_id) {
+ err = ccs_ccache_get_principal (io_ccache, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_ccache_set_principal_msg_id) {
+ err = ccs_ccache_set_principal (io_ccache, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_ccache_store_credentials_msg_id) {
+ err = ccs_ccache_store_credentials (io_ccache, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_ccache_remove_credentials_msg_id) {
+ err = ccs_ccache_remove_credentials (io_ccache, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_ccache_new_credentials_iterator_msg_id) {
+ err = ccs_ccache_new_credentials_iterator (io_ccache, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_ccache_move_msg_id) {
+ err = ccs_ccache_move (io_ccache, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_ccache_lock_msg_id) {
+ err = ccs_ccache_lock (in_client_pipe, in_reply_pipe,
+ io_ccache, io_cache_collection,
+ in_request_data,
+ &will_block, reply_data);
+
+ } else if (in_request_name == cci_ccache_unlock_msg_id) {
+ err = ccs_ccache_unlock (in_client_pipe,
+ io_ccache, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_ccache_get_last_default_time_msg_id) {
+ err = ccs_ccache_get_last_default_time (io_ccache, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_ccache_get_change_time_msg_id) {
+ err = ccs_ccache_get_change_time (io_ccache, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_ccache_get_kdc_time_offset_msg_id) {
+ err = ccs_ccache_get_kdc_time_offset (io_ccache, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_ccache_set_kdc_time_offset_msg_id) {
+ err = ccs_ccache_set_kdc_time_offset (io_ccache, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else if (in_request_name == cci_ccache_clear_kdc_time_offset_msg_id) {
+ err = ccs_ccache_clear_kdc_time_offset (io_ccache, io_cache_collection,
+ in_request_data, reply_data);
+
+ } else {
+ err = ccErrBadInternalMessage;
+ }
+ }
+
+ if (!err) {
+ *out_will_block = will_block;
+ *out_reply_data = reply_data;
+ reply_data = NULL; /* take ownership */
+ }
+
+ cci_stream_release (reply_data);
+
+ return cci_check_error (err);
+}
+
diff --git a/src/ccapi/server/ccs_ccache.h b/src/ccapi/server/ccs_ccache.h
new file mode 100644
index 000000000..837c6b457
--- /dev/null
+++ b/src/ccapi/server/ccs_ccache.h
@@ -0,0 +1,78 @@
+/*
+ * $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.
+ */
+
+#ifndef CCS_CCACHE_H
+#define CCS_CCACHE_H
+
+#include "ccs_types.h"
+
+cc_int32 ccs_ccache_new (ccs_ccache_t *out_ccache,
+ cc_uint32 in_cred_vers,
+ const char *in_name,
+ const char *in_principal,
+ ccs_ccache_list_t io_ccache_list);
+
+cc_int32 ccs_ccache_reset (ccs_ccache_t io_ccache,
+ cc_uint32 in_cred_vers,
+ const char *in_principal);
+
+cc_int32 ccs_ccache_swap_contents (ccs_ccache_t io_source_ccache,
+ ccs_ccache_t io_destination_ccache);
+
+inline cc_int32 ccs_ccache_release (ccs_ccache_t io_ccache);
+
+inline cc_int32 ccs_ccache_compare_identifier (ccs_ccache_t in_ccache,
+ cci_identifier_t in_identifier,
+ cc_uint32 *out_equal);
+
+cc_int32 ccs_ccache_compare_name (ccs_ccache_t in_ccache,
+ const char *in_name,
+ cc_uint32 *out_equal);
+
+cc_int32 ccs_ccache_notify_default_state_changed (ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ cc_uint32 in_new_default_state);
+
+cc_int32 ccs_ccache_find_credentials_iterator (ccs_ccache_t in_ccache,
+ cci_identifier_t in_identifier,
+ ccs_credentials_iterator_t *out_credentials_iterator);
+
+cc_int32 ccs_ccache_write (ccs_ccache_t in_ccache,
+ cci_stream_t io_stream);
+
+cc_int32 ccs_ccache_write_name (ccs_ccache_t in_ccache,
+ cci_stream_t io_stream);
+
+cc_int32 ccs_ccache_handle_message (ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ ccs_ccache_t io_ccache,
+ ccs_cache_collection_t io_cache_collection,
+ enum cci_msg_id_t in_request_name,
+ cci_stream_t in_request_data,
+ cc_uint32 *out_will_block,
+ cci_stream_t *out_reply_data);
+
+#endif /* CCS_CCACHE_H */
diff --git a/src/ccapi/server/ccs_ccache_iterator.c b/src/ccapi/server/ccs_ccache_iterator.c
new file mode 100644
index 000000000..77d83f1b0
--- /dev/null
+++ b/src/ccapi/server/ccs_ccache_iterator.c
@@ -0,0 +1,156 @@
+/*
+ * $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"
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_iterator_release (ccs_ccache_iterator_t io_ccache_iterator,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_ccache_iterator ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_ccache_list_iterator_release (io_ccache_iterator);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_iterator_next (ccs_ccache_iterator_t io_ccache_iterator,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_t ccache = NULL;
+
+ if (!io_ccache_iterator ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_ccache_list_iterator_next (io_ccache_iterator, &ccache);
+ }
+
+ if (!err) {
+ err = ccs_ccache_write (ccache, io_reply_data);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_iterator_clone (ccs_ccache_iterator_t io_ccache_iterator,
+ ccs_cache_collection_t io_cache_collection,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ ccs_ccache_iterator_t ccache_iterator = NULL;
+
+ if (!io_ccache_iterator ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_ccache_list_iterator_clone (io_ccache_iterator,
+ &ccache_iterator);
+ }
+
+ if (!err) {
+ err = ccs_ccache_list_iterator_write (ccache_iterator, io_reply_data);
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+ cc_int32 ccs_ccache_iterator_handle_message (ccs_ccache_iterator_t io_ccache_iterator,
+ ccs_cache_collection_t io_cache_collection,
+ enum cci_msg_id_t in_request_name,
+ cci_stream_t in_request_data,
+ cci_stream_t *out_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cci_stream_t reply_data = NULL;
+
+ if (!in_request_data) { err = cci_check_error (ccErrBadParam); }
+ if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_new (&reply_data);
+ }
+
+ if (!err) {
+ if (in_request_name == cci_ccache_iterator_release_msg_id) {
+ err = ccs_ccache_iterator_release (io_ccache_iterator,
+ io_cache_collection,
+ in_request_data,
+ reply_data);
+
+ } else if (in_request_name == cci_ccache_iterator_next_msg_id) {
+ err = ccs_ccache_iterator_next (io_ccache_iterator,
+ io_cache_collection,
+ in_request_data,
+ reply_data);
+
+ } else if (in_request_name == cci_ccache_iterator_clone_msg_id) {
+ err = ccs_ccache_iterator_clone (io_ccache_iterator,
+ io_cache_collection,
+ in_request_data,
+ reply_data);
+
+ } else {
+ err = ccErrBadInternalMessage;
+ }
+ }
+
+ if (!err) {
+ *out_reply_data = reply_data;
+ reply_data = NULL; /* take ownership */
+ }
+
+ cci_stream_release (reply_data);
+
+ return cci_check_error (err);
+}
+
diff --git a/src/ccapi/server/ccs_ccache_iterator.h b/src/ccapi/server/ccs_ccache_iterator.h
new file mode 100644
index 000000000..8ec361a67
--- /dev/null
+++ b/src/ccapi/server/ccs_ccache_iterator.h
@@ -0,0 +1,38 @@
+/*
+ * $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.
+ */
+
+#ifndef CCS_CCACHE_ITERATOR_H
+#define CCS_CCACHE_ITERATOR_H
+
+#include "ccs_types.h"
+
+ cc_int32 ccs_ccache_iterator_handle_message (ccs_ccache_iterator_t io_ccache_iterator,
+ ccs_cache_collection_t io_cache_collection,
+ enum cci_msg_id_t in_request_name,
+ cci_stream_t in_request_data,
+ cci_stream_t *out_reply_data);
+
+#endif /* CCS_CCACHE_ITERATOR_H */
diff --git a/src/ccapi/server/ccs_common.h b/src/ccapi/server/ccs_common.h
new file mode 100644
index 000000000..f035780da
--- /dev/null
+++ b/src/ccapi/server/ccs_common.h
@@ -0,0 +1,44 @@
+/*
+ * $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.
+ */
+
+#ifndef CCS_COMMON_H
+#define CCS_COMMON_H
+
+#include "cci_common.h"
+
+#include "ccs_array.h"
+#include "ccs_list.h"
+#include "ccs_cache_collection.h"
+#include "ccs_ccache_iterator.h"
+#include "ccs_ccache.h"
+#include "ccs_credentials_iterator.h"
+#include "ccs_credentials.h"
+#include "ccs_lock.h"
+#include "ccs_lock_state.h"
+#include "ccs_pipe.h"
+#include "ccs_server.h"
+
+#endif /* CCS_COMMON_H */
diff --git a/src/ccapi/server/ccs_credentials.c b/src/ccapi/server/ccs_credentials.c
new file mode 100644
index 000000000..7cb6483f0
--- /dev/null
+++ b/src/ccapi/server/ccs_credentials.c
@@ -0,0 +1,136 @@
+/*
+ * $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"
+
+struct ccs_credentials_d {
+ cc_credentials_union *cred_union;
+ cci_identifier_t identifier;
+};
+
+struct ccs_credentials_d ccs_credentials_initializer = { NULL, NULL };
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_credentials_new (ccs_credentials_t *out_credentials,
+ cci_stream_t in_stream,
+ ccs_credentials_list_t io_credentials_list)
+{
+ cc_int32 err = ccNoError;
+ ccs_credentials_t credentials = NULL;
+
+ if (!out_credentials) { err = cci_check_error (ccErrBadParam); }
+ if (!in_stream ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ credentials = malloc (sizeof (*credentials));
+ if (credentials) {
+ *credentials = ccs_credentials_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ err = cci_cred_union_read (&credentials->cred_union, in_stream);
+ }
+
+ if (!err) {
+ err = ccs_server_new_identifier (&credentials->identifier);
+ }
+
+ if (!err) {
+ err = ccs_credentials_list_add (io_credentials_list, credentials);
+ }
+
+ if (!err) {
+ *out_credentials = credentials;
+ credentials = NULL;
+ }
+
+ ccs_credentials_release (credentials);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_release (ccs_credentials_t io_credentials)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_credentials) { err = ccErrBadParam; }
+
+ if (!err) {
+ cci_cred_union_release (io_credentials->cred_union);
+ cci_identifier_release (io_credentials->identifier);
+ free (io_credentials);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_credentials_write (ccs_credentials_t in_credentials,
+ cci_stream_t io_stream)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_credentials) { err = cci_check_error (ccErrBadParam); }
+ if (!io_stream ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_write (in_credentials->identifier, io_stream);
+ }
+
+ if (!err) {
+ err = cci_cred_union_write (in_credentials->cred_union, io_stream);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_compare_identifier (ccs_credentials_t in_credentials,
+ cci_identifier_t in_identifier,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_credentials) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_equal ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_compare (in_credentials->identifier,
+ in_identifier,
+ out_equal);
+ }
+
+ return cci_check_error (err);
+}
diff --git a/src/ccapi/server/ccs_credentials.h b/src/ccapi/server/ccs_credentials.h
new file mode 100644
index 000000000..e4dbb69f5
--- /dev/null
+++ b/src/ccapi/server/ccs_credentials.h
@@ -0,0 +1,46 @@
+/*
+ * $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.
+ */
+
+#ifndef CCS_CREDENTIALS_H
+#define CCS_CREDENTIALS_H
+
+#include "ccs_types.h"
+
+
+cc_int32 ccs_credentials_new (ccs_credentials_t *out_credentials,
+ cci_stream_t in_stream,
+ ccs_credentials_list_t io_credentials_list);
+
+inline cc_int32 ccs_credentials_release (ccs_credentials_t io_credentials);
+
+cc_int32 ccs_credentials_write (ccs_credentials_t in_credentials,
+ cci_stream_t io_stream);
+
+inline cc_int32 ccs_credentials_compare_identifier (ccs_credentials_t in_credentials,
+ cci_identifier_t in_identifier,
+ cc_uint32 *out_equal);
+
+#endif /* CCS_CREDENTIALS_H */
diff --git a/src/ccapi/server/ccs_credentials_iterator.c b/src/ccapi/server/ccs_credentials_iterator.c
new file mode 100644
index 000000000..f95dc4842
--- /dev/null
+++ b/src/ccapi/server/ccs_credentials_iterator.c
@@ -0,0 +1,158 @@
+/*
+ * $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"
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_credentials_iterator_release (ccs_credentials_iterator_t io_credentials_iterator,
+ ccs_ccache_t io_ccache,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_credentials_list_iterator_release (io_credentials_iterator);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_credentials_iterator_next (ccs_credentials_iterator_t io_credentials_iterator,
+ ccs_ccache_t io_ccache,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ ccs_credentials_t credentials = NULL;
+
+ if (!io_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_credentials_list_iterator_next (io_credentials_iterator,
+ &credentials);
+ }
+
+ if (!err) {
+ err = ccs_credentials_write (credentials, io_reply_data);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_credentials_iterator_clone (ccs_credentials_iterator_t io_credentials_iterator,
+ ccs_ccache_t io_ccache,
+ cci_stream_t in_request_data,
+ cci_stream_t io_reply_data)
+{
+ cc_int32 err = ccNoError;
+ ccs_credentials_iterator_t credentials_iterator = NULL;
+
+ if (!io_credentials_iterator) { err = cci_check_error (ccErrBadParam); }
+ if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_credentials_list_iterator_clone (io_credentials_iterator,
+ &credentials_iterator);
+ }
+
+ if (!err) {
+ err = ccs_credentials_list_iterator_write (credentials_iterator,
+ io_reply_data);
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+ cc_int32 ccs_credentials_iterator_handle_message (ccs_credentials_iterator_t io_credentials_iterator,
+ ccs_ccache_t io_ccache,
+ enum cci_msg_id_t in_request_name,
+ cci_stream_t in_request_data,
+ cci_stream_t *out_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cci_stream_t reply_data = NULL;
+
+ if (!in_request_data) { err = cci_check_error (ccErrBadParam); }
+ if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_stream_new (&reply_data);
+ }
+
+ if (!err) {
+ if (in_request_name == cci_credentials_iterator_release_msg_id) {
+ err = ccs_credentials_iterator_release (io_credentials_iterator,
+ io_ccache,
+ in_request_data,
+ reply_data);
+
+ } else if (in_request_name == cci_credentials_iterator_next_msg_id) {
+ err = ccs_credentials_iterator_next (io_credentials_iterator,
+ io_ccache,
+ in_request_data,
+ reply_data);
+
+ } else if (in_request_name == cci_credentials_iterator_clone_msg_id) {
+ err = ccs_credentials_iterator_clone (io_credentials_iterator,
+ io_ccache,
+ in_request_data,
+ reply_data);
+
+ } else {
+ err = ccErrBadInternalMessage;
+ }
+ }
+
+ if (!err) {
+ *out_reply_data = reply_data;
+ reply_data = NULL; /* take ownership */
+ }
+
+ cci_stream_release (reply_data);
+
+ return cci_check_error (err);
+}
+
diff --git a/src/ccapi/server/ccs_credentials_iterator.h b/src/ccapi/server/ccs_credentials_iterator.h
new file mode 100644
index 000000000..af3cf1a18
--- /dev/null
+++ b/src/ccapi/server/ccs_credentials_iterator.h
@@ -0,0 +1,38 @@
+/*
+ * $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.
+ */
+
+#ifndef CCS_CREDENTIALS_ITERATOR_H
+#define CCS_CREDENTIALS_ITERATOR_H
+
+#include "ccs_types.h"
+
+ cc_int32 ccs_credentials_iterator_handle_message (ccs_credentials_iterator_t io_credentials_iterator,
+ ccs_ccache_t io_ccache,
+ enum cci_msg_id_t in_request_name,
+ cci_stream_t in_request_data,
+ cci_stream_t *out_reply_data);
+
+#endif /* CCS_CREDENTIALS_ITERATOR_H */
diff --git a/src/ccapi/server/ccs_list.c b/src/ccapi/server/ccs_list.c
new file mode 100644
index 000000000..17355c08f
--- /dev/null
+++ b/src/ccapi/server/ccs_list.c
@@ -0,0 +1,345 @@
+/*
+ * $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 "ccs_list_internal.h"
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_list_object_release (void *io_object)
+{
+ return cci_check_error (ccs_cache_collection_release ((ccs_cache_collection_t) io_object));
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_cache_collection_list_object_compare_identifier (void *in_cache_collection,
+ cci_identifier_t in_identifier,
+ cc_uint32 *out_equal)
+{
+ return ccs_cache_collection_compare_identifier ((ccs_cache_collection_t) in_cache_collection,
+ in_identifier,
+ out_equal);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_cache_collection_list_new (ccs_cache_collection_list_t *out_list)
+{
+ return ccs_list_new (out_list,
+ ccErrInvalidContext,
+ ccErrInvalidContext,
+ ccs_cache_collection_list_object_compare_identifier,
+ ccs_cache_collection_list_object_release);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_cache_collection_list_count (ccs_cache_collection_list_t in_list,
+ cc_uint64 *out_count)
+{
+ return ccs_list_count (in_list, out_count);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_cache_collection_list_find (ccs_cache_collection_list_t in_list,
+ cci_identifier_t in_identifier,
+ ccs_cache_collection_t *out_cache_collection)
+{
+ return ccs_list_find (in_list, in_identifier, (ccs_object_t *) out_cache_collection);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_cache_collection_list_add (ccs_cache_collection_list_t io_list,
+ ccs_cache_collection_t in_cache_collection)
+{
+ return ccs_list_add (io_list, in_cache_collection);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_cache_collection_list_remove (ccs_cache_collection_list_t io_list,
+ cci_identifier_t in_identifier)
+{
+ return ccs_list_remove (io_list, in_identifier);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_cache_collection_list_release (ccs_cache_collection_list_t io_list)
+{
+ return ccs_list_release (io_list);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_list_object_release (void *io_ccache)
+{
+ return cci_check_error (ccs_ccache_release ((ccs_ccache_t) io_ccache));
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_ccache_list_object_compare_identifier (void *in_ccache,
+ cci_identifier_t in_identifier,
+ cc_uint32 *out_equal)
+{
+ return ccs_ccache_compare_identifier ((ccs_ccache_t) in_ccache,
+ in_identifier,
+ out_equal);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_new (ccs_ccache_list_t *out_list)
+{
+ return ccs_list_new (out_list,
+ ccErrInvalidCCache,
+ ccErrInvalidCCacheIterator,
+ ccs_ccache_list_object_compare_identifier,
+ ccs_ccache_list_object_release);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_new_iterator (ccs_ccache_list_t in_list,
+ ccs_ccache_list_iterator_t *out_list_iterator)
+{
+ return ccs_list_new_iterator (in_list, out_list_iterator);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_count (ccs_ccache_list_t in_list,
+ cc_uint64 *out_count)
+{
+ return ccs_list_count (in_list, out_count);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_find (ccs_ccache_list_t in_list,
+ cci_identifier_t in_identifier,
+ ccs_ccache_t *out_ccache)
+{
+ return ccs_list_find (in_list, in_identifier, (ccs_object_t *) out_ccache);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_find_iterator (ccs_ccache_list_t in_list,
+ cci_identifier_t in_identifier,
+ ccs_ccache_list_iterator_t *out_list_iterator)
+{
+ return ccs_list_find_iterator (in_list, in_identifier,
+ (ccs_list_iterator_t *) out_list_iterator);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_add (ccs_ccache_list_t io_list,
+ ccs_ccache_t in_ccache)
+{
+ return ccs_list_add (io_list, in_ccache);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_remove (ccs_ccache_list_t io_list,
+ cci_identifier_t in_identifier)
+{
+ return ccs_list_remove (io_list, in_identifier);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_push_front (ccs_ccache_list_t io_list,
+ cci_identifier_t in_identifier)
+{
+ return ccs_list_push_front (io_list, in_identifier);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_release (ccs_ccache_list_t io_list)
+{
+ return ccs_list_release (io_list);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_iterator_write (ccs_ccache_list_iterator_t in_list_iterator,
+ cci_stream_t in_stream)
+{
+ return ccs_list_iterator_write (in_list_iterator, in_stream);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_iterator_clone (ccs_ccache_list_iterator_t in_list_iterator,
+ ccs_ccache_list_iterator_t *out_list_iterator)
+{
+ return ccs_list_iterator_clone (in_list_iterator, out_list_iterator);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_iterator_next (ccs_ccache_list_iterator_t io_list_iterator,
+ ccs_ccache_t *out_ccache)
+{
+ return ccs_list_iterator_next (io_list_iterator, (ccs_object_t *) out_ccache);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_ccache_list_iterator_release (ccs_ccache_list_iterator_t io_list_iterator)
+{
+ return ccs_list_iterator_release (io_list_iterator);
+}
+
+#pragma mark-
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_credentials_list_object_release (void *io_object)
+{
+ return cci_check_error (ccs_credentials_release ((ccs_credentials_t) io_object));
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_credentials_list_object_compare_identifier (void *in_credentials,
+ cci_identifier_t in_identifier,
+ cc_uint32 *out_equal)
+{
+ return ccs_credentials_compare_identifier ((ccs_credentials_t) in_credentials,
+ in_identifier,
+ out_equal);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_new (ccs_credentials_list_t *out_list)
+{
+ return ccs_list_new (out_list,
+ ccErrInvalidCredentials,
+ ccErrInvalidCredentialsIterator,
+ ccs_credentials_list_object_compare_identifier,
+ ccs_credentials_list_object_release);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_new_iterator (ccs_credentials_list_t in_list,
+ ccs_credentials_list_iterator_t *out_list_iterator)
+{
+ return ccs_list_new_iterator (in_list, out_list_iterator);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_count (ccs_credentials_list_t in_list,
+ cc_uint64 *out_count)
+{
+ return ccs_list_count (in_list, out_count);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_find (ccs_credentials_list_t in_list,
+ cci_identifier_t in_identifier,
+ ccs_credentials_t *out_credentials)
+{
+ return ccs_list_find (in_list, in_identifier, (ccs_object_t *) out_credentials);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_find_iterator (ccs_credentials_list_t in_list,
+ cci_identifier_t in_identifier,
+ ccs_credentials_list_iterator_t *out_list_iterator)
+{
+ return ccs_list_find_iterator (in_list, in_identifier,
+ (ccs_list_iterator_t *) out_list_iterator);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_add (ccs_credentials_list_t io_list,
+ ccs_credentials_t in_credential)
+{
+ return ccs_list_add (io_list, in_credential);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_remove (ccs_credentials_list_t io_list,
+ cci_identifier_t in_identifier)
+{
+ return ccs_list_remove (io_list, in_identifier);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_release (ccs_credentials_list_t io_list)
+{
+ return ccs_list_release (io_list);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_iterator_write (ccs_credentials_list_iterator_t in_list_iterator,
+ cci_stream_t in_stream)
+{
+ return ccs_list_iterator_write (in_list_iterator, in_stream);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_iterator_clone (ccs_credentials_list_iterator_t in_list_iterator,
+ ccs_credentials_list_iterator_t *out_list_iterator)
+{
+ return ccs_list_iterator_clone (in_list_iterator, out_list_iterator);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_iterator_next (ccs_credentials_list_iterator_t io_list_iterator,
+ ccs_credentials_t *out_credential)
+{
+ return ccs_list_iterator_next (io_list_iterator, (ccs_object_t *) out_credential);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_credentials_list_iterator_release (ccs_credentials_list_iterator_t io_list_iterator)
+{
+ return ccs_list_iterator_release (io_list_iterator);
+}
diff --git a/src/ccapi/server/ccs_list.h b/src/ccapi/server/ccs_list.h
new file mode 100644
index 000000000..435821a5b
--- /dev/null
+++ b/src/ccapi/server/ccs_list.h
@@ -0,0 +1,129 @@
+/*
+ * $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.
+ */
+
+#ifndef CCS_LIST_H
+#define CCS_LIST_H
+
+
+#include "ccs_types.h"
+
+cc_int32 ccs_cache_collection_list_new (ccs_cache_collection_list_t *out_list);
+
+cc_int32 ccs_cache_collection_list_count (ccs_cache_collection_list_t in_list,
+ cc_uint64 *out_count);
+
+cc_int32 ccs_cache_collection_list_find (ccs_cache_collection_list_t in_list,
+ cci_identifier_t in_identifier,
+ ccs_cache_collection_t *out_cache_collection);
+
+cc_int32 ccs_cache_collection_list_add (ccs_cache_collection_list_t io_list,
+ ccs_cache_collection_t in_cache_collection);
+
+cc_int32 ccs_cache_collection_list_remove (ccs_cache_collection_list_t io_list,
+ cci_identifier_t in_identifier);
+
+cc_int32 ccs_cache_collection_list_release (ccs_cache_collection_list_t io_list);
+
+#pragma mark -
+
+cc_int32 ccs_ccache_list_new (ccs_ccache_list_t *out_list);
+
+cc_int32 ccs_ccache_list_new_iterator (ccs_ccache_list_t in_list,
+ ccs_ccache_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_ccache_list_count (ccs_ccache_list_t in_list,
+ cc_uint64 *out_count);
+
+cc_int32 ccs_ccache_list_find (ccs_ccache_list_t in_list,
+ cci_identifier_t in_identifier,
+ ccs_ccache_t *out_ccache);
+
+cc_int32 ccs_ccache_list_find_iterator (ccs_ccache_list_t in_list,
+ cci_identifier_t in_identifier,
+ ccs_ccache_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_ccache_list_add (ccs_ccache_list_t io_list,
+ ccs_ccache_t in_ccache);
+
+cc_int32 ccs_ccache_list_remove (ccs_ccache_list_t io_list,
+ cci_identifier_t in_identifier);
+
+cc_int32 ccs_ccache_list_push_front (ccs_ccache_list_t io_list,
+ cci_identifier_t in_identifier);
+
+cc_int32 ccs_ccache_list_release (ccs_ccache_list_t io_list);
+
+
+cc_int32 ccs_ccache_list_iterator_write (ccs_ccache_list_iterator_t in_list_iterator,
+ cci_stream_t in_stream);
+
+cc_int32 ccs_ccache_list_iterator_clone (ccs_ccache_list_iterator_t in_list_iterator,
+ ccs_ccache_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_ccache_list_iterator_next (ccs_ccache_list_iterator_t io_list_iterator,
+ ccs_ccache_t *out_ccache);
+
+cc_int32 ccs_ccache_list_iterator_release (ccs_ccache_list_iterator_t io_list_iterator);
+
+#pragma mark -
+
+cc_int32 ccs_credentials_list_new (ccs_credentials_list_t *out_list);
+
+cc_int32 ccs_credentials_list_new_iterator (ccs_credentials_list_t in_list,
+ ccs_credentials_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_credentials_list_count (ccs_credentials_list_t in_list,
+ cc_uint64 *out_count);
+
+cc_int32 ccs_credentials_list_find (ccs_credentials_list_t in_list,
+ cci_identifier_t in_identifier,
+ ccs_credentials_t *out_credentials);
+
+cc_int32 ccs_credentials_list_find_iterator (ccs_credentials_list_t in_list,
+ cci_identifier_t in_identifier,
+ ccs_credentials_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_credentials_list_add (ccs_credentials_list_t io_list,
+ ccs_credentials_t in_credential);
+
+cc_int32 ccs_credentials_list_remove (ccs_credentials_list_t io_list,
+ cci_identifier_t in_identifier);
+
+cc_int32 ccs_credentials_list_release (ccs_credentials_list_t io_list);
+
+
+cc_int32 ccs_credentials_list_iterator_write (ccs_credentials_list_iterator_t in_list_iterator,
+ cci_stream_t in_stream);
+
+cc_int32 ccs_credentials_list_iterator_clone (ccs_credentials_list_iterator_t in_list_iterator,
+ ccs_credentials_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_credentials_list_iterator_next (ccs_credentials_list_iterator_t io_list_iterator,
+ ccs_credentials_t *out_credential);
+
+cc_int32 ccs_credentials_list_iterator_release (ccs_credentials_list_iterator_t io_list_iterator);
+
+#endif /* CCS_LIST_H */
diff --git a/src/ccapi/server/ccs_list_internal.c b/src/ccapi/server/ccs_list_internal.c
new file mode 100644
index 000000000..a930fba33
--- /dev/null
+++ b/src/ccapi/server/ccs_list_internal.c
@@ -0,0 +1,612 @@
+/*
+ * $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_list_internal.h"
+#include "cci_array_internal.h"
+#include "cci_identifier.h"
+#include "ccs_server.h"
+
+typedef enum {
+ ccs_list_action_insert,
+ ccs_list_action_remove,
+ ccs_list_action_push_front
+} ccs_list_action_enum;
+
+/* ------------------------------------------------------------------------ */
+
+struct ccs_list_d {
+ cci_array_t objects;
+ cci_array_t iterators;
+
+ cc_int32 object_not_found_err;
+ cc_int32 iterator_not_found_err;
+
+ ccs_object_compare_identifier_t object_compare_identifier;
+};
+
+struct ccs_list_d ccs_list_initializer = { NULL, NULL, -1, -1, NULL };
+
+/* ------------------------------------------------------------------------ */
+
+struct ccs_list_iterator_d {
+ cci_identifier_t identifier;
+ ccs_list_t list;
+ cc_uint64 current;
+};
+
+struct ccs_list_iterator_d ccs_list_iterator_initializer = { NULL, NULL, 0 };
+
+static cc_int32 ccs_list_iterator_new (ccs_list_iterator_t *out_list_iterator,
+ ccs_list_t in_list);
+
+static cc_int32 ccs_list_iterator_object_release (cci_array_object_t io_list_iterator);
+
+static cc_int32 ccs_list_iterator_update (ccs_list_iterator_t io_list_iterator,
+ ccs_list_action_enum in_action,
+ cc_uint64 in_object_index);
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_new (ccs_list_t *out_list,
+ cc_int32 in_object_not_found_err,
+ cc_int32 in_iterator_not_found_err,
+ ccs_object_compare_identifier_t in_object_compare_identifier,
+ ccs_object_release_t in_object_release)
+{
+ cc_int32 err = ccNoError;
+ ccs_list_t list = NULL;
+
+ if (!out_list) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ list = malloc (sizeof (*list));
+ if (list) {
+ *list = ccs_list_initializer;
+ list->object_not_found_err = in_object_not_found_err;
+ list->iterator_not_found_err = in_iterator_not_found_err;
+ list->object_compare_identifier = in_object_compare_identifier;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ err = cci_array_new (&list->objects, in_object_release);
+ }
+
+ if (!err) {
+ err = cci_array_new (&list->iterators, ccs_list_iterator_object_release);
+ }
+
+ if (!err) {
+ *out_list = list;
+ list = NULL;
+ }
+
+ ccs_list_release (list);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_release (ccs_list_t io_list)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_list) { err = ccErrBadParam; }
+
+ if (!err) {
+ cc_uint64 i;
+
+ for (i = 0; i < cci_array_count (io_list->iterators); i++) {
+ ccs_list_iterator_release (cci_array_object_at_index (io_list->iterators, i));
+ }
+ free (io_list->iterators);
+ cci_array_release (io_list->objects);
+ free (io_list);
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_new_iterator (ccs_list_t io_list,
+ ccs_list_iterator_t *out_list_iterator)
+{
+ return cci_check_error (ccs_list_iterator_new (out_list_iterator, io_list));
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_release_iterator (ccs_list_t io_list,
+ cci_identifier_t in_identifier)
+{
+ cc_int32 err = ccNoError;
+ ccs_list_iterator_t iterator = NULL;
+
+ if (!io_list ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_list_find_iterator (io_list, in_identifier, &iterator);
+ }
+
+ if (!err) {
+ err = ccs_list_iterator_release (iterator);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_count (ccs_list_t in_list,
+ cc_uint64 *out_count)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_list ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_count) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_count = cci_array_count (in_list->objects);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_list_find_index (ccs_list_t in_list,
+ cci_identifier_t in_identifier,
+ cc_uint64 *out_object_index)
+{
+ cc_int32 err = ccNoError;
+ cc_int32 found = 0;
+
+ if (!in_list ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_object_index) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err && !found) {
+ cc_uint64 i;
+
+ for (i = 0; !err && i < cci_array_count (in_list->objects); i++) {
+ cc_uint32 equal = 0;
+ cci_array_object_t object = cci_array_object_at_index (in_list->objects, i);
+
+ err = in_list->object_compare_identifier (object, in_identifier, &equal);
+
+ if (!err && equal) {
+ found = 1;
+ *out_object_index = i;
+ }
+ }
+ }
+
+ if (!err && !found) {
+ err = cci_check_error (in_list->object_not_found_err);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+cc_int32 ccs_list_find (ccs_list_t in_list,
+ cci_identifier_t in_identifier,
+ ccs_object_t *out_object)
+{
+ cc_int32 err = ccNoError;
+ cc_uint64 i;
+
+ if (!in_list ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+ if (!out_object ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_list_find_index (in_list, in_identifier, &i);
+ }
+
+ if (!err) {
+ *out_object = cci_array_object_at_index (in_list->objects, i);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_list_find_iterator_index (ccs_list_t in_list,
+ cci_identifier_t in_identifier,
+ cc_uint64 *out_object_index)
+{
+ cc_int32 err = ccNoError;
+ cc_int32 found = 0;
+
+ if (!in_list ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_object_index) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err && !found) {
+ cc_uint64 i;
+
+ for (i = 0; !err && i < cci_array_count (in_list->iterators); i++) {
+ cc_uint32 equal = 0;
+ ccs_list_iterator_t iterator = cci_array_object_at_index (in_list->iterators, i);
+
+ err = cci_identifier_compare (iterator->identifier, in_identifier, &equal);
+
+ if (!err && equal) {
+ found = 1;
+ *out_object_index = i;
+ }
+ }
+ }
+
+ if (!err && !found) {
+ err = cci_check_error (in_list->object_not_found_err);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_find_iterator (ccs_list_t in_list,
+ cci_identifier_t in_identifier,
+ ccs_list_iterator_t *out_list_iterator)
+{
+ cc_int32 err = ccNoError;
+ cc_uint64 i;
+
+ if (!in_list ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_list_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_list_find_iterator_index (in_list, in_identifier, &i);
+ }
+
+ if (!err) {
+ *out_list_iterator = cci_array_object_at_index (in_list->iterators, i);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_add (ccs_list_t io_list,
+ ccs_object_t in_object)
+{
+ cc_int32 err = ccNoError;
+ cc_uint64 add_index;
+
+ if (!io_list ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_object) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ add_index = cci_array_count (io_list->objects);
+
+ err = cci_array_insert (io_list->objects, in_object, add_index);
+ }
+
+ if (!err) {
+ /* Fixup iterator indexes */
+ cc_uint64 i;
+
+ for (i = 0; !err && i < cci_array_count (io_list->iterators); i++) {
+ ccs_list_iterator_t iterator = cci_array_object_at_index (io_list->iterators, i);
+
+ err = ccs_list_iterator_update (iterator, ccs_list_action_insert, add_index);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_remove (ccs_list_t io_list,
+ cci_identifier_t in_identifier)
+{
+ cc_int32 err = ccNoError;
+ cc_uint64 remove_index;
+
+ if (!io_list ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_list_find_index (io_list, in_identifier, &remove_index);
+ }
+
+ if (!err) {
+ err = cci_array_remove (io_list->objects, remove_index);
+ }
+
+ if (!err) {
+ /* Fixup iterator indexes */
+ cc_uint64 i;
+
+ for (i = 0; !err && i < cci_array_count (io_list->iterators); i++) {
+ ccs_list_iterator_t iterator = cci_array_object_at_index (io_list->iterators, i);
+
+ err = ccs_list_iterator_update (iterator, ccs_list_action_remove, remove_index);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_push_front (ccs_list_t io_list,
+ cci_identifier_t in_identifier)
+{
+ cc_int32 err = ccNoError;
+ cc_uint64 push_front_index;
+
+ if (!io_list ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_identifier) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_list_find_index (io_list, in_identifier, &push_front_index);
+ }
+
+ if (!err) {
+ err = cci_array_push_front (io_list->objects, push_front_index);
+ }
+
+ if (!err) {
+ /* Fixup iterator indexes */
+ cc_uint64 i;
+
+ for (i = 0; !err && i < cci_array_count (io_list->iterators); i++) {
+ ccs_list_iterator_t iterator = cci_array_object_at_index (io_list->iterators, i);
+
+ err = ccs_list_iterator_update (iterator,
+ ccs_list_action_push_front,
+ push_front_index);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_list_iterator_new (ccs_list_iterator_t *out_list_iterator,
+ ccs_list_t io_list)
+{
+ cc_int32 err = ccNoError;
+ ccs_list_iterator_t list_iterator = NULL;
+
+ if (!out_list_iterator) { err = cci_check_error (ccErrBadParam); }
+ if (!io_list ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ list_iterator = malloc (sizeof (*list_iterator));
+ if (list_iterator) {
+ *list_iterator = ccs_list_iterator_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ err = ccs_server_new_identifier (&list_iterator->identifier);
+ }
+
+ if (!err) {
+ list_iterator->list = io_list;
+ list_iterator->current = 0;
+
+ err = cci_array_insert (io_list->iterators,
+ list_iterator, cci_array_count (io_list->iterators));
+ }
+
+ if (!err) {
+ *out_list_iterator = list_iterator;
+ list_iterator = NULL;
+ }
+
+ ccs_list_iterator_release (list_iterator);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_iterator_write (ccs_list_iterator_t in_list_iterator,
+ cci_stream_t in_stream)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_list_iterator) { err = cci_check_error (ccErrBadParam); }
+ if (!in_stream ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_identifier_write (in_list_iterator->identifier,
+ in_stream);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_iterator_clone (ccs_list_iterator_t in_list_iterator,
+ ccs_list_iterator_t *out_list_iterator)
+{
+ cc_int32 err = ccNoError;
+ ccs_list_iterator_t list_iterator = NULL;
+
+ if (!in_list_iterator ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_list_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_list_iterator_new (&list_iterator, in_list_iterator->list);
+ }
+
+ if (!err) {
+ list_iterator->current = in_list_iterator->current;
+
+ *out_list_iterator = list_iterator;
+ list_iterator = NULL;
+ }
+
+ ccs_list_iterator_release (list_iterator);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_list_iterator_object_release (cci_array_object_t io_list_iterator)
+{
+ cc_int32 err = ccNoError;
+ ccs_list_iterator_t list_iterator = (ccs_list_iterator_t) io_list_iterator;
+
+ if (!io_list_iterator) { err = ccErrBadParam; }
+
+ if (!err) {
+ cci_identifier_release (list_iterator->identifier);
+ free (io_list_iterator);
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_iterator_release (ccs_list_iterator_t io_list_iterator)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_list_iterator) { err = ccErrBadParam; }
+
+ if (!err) {
+ cc_uint64 i = 0;
+
+ if (ccs_list_find_iterator_index (io_list_iterator->list,
+ io_list_iterator->identifier,
+ &i) == ccNoError) {
+ /* cci_array_remove will call ccs_list_iterator_object_release */
+ cci_array_remove (io_list_iterator->list->iterators, i);
+ } else {
+ cci_debug_printf ("Warning: iterator not in iterator list!");
+ }
+ }
+
+ return err;
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_iterator_current (ccs_list_iterator_t io_list_iterator,
+ ccs_object_t *out_object)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_list_iterator) { err = cci_check_error (ccErrBadParam); }
+ if (!out_object ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ if (io_list_iterator->current < cci_array_count (io_list_iterator->list->objects)) {
+ *out_object = cci_array_object_at_index (io_list_iterator->list->objects,
+ io_list_iterator->current);
+ } else {
+ err = ccIteratorEnd;
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_list_iterator_next (ccs_list_iterator_t io_list_iterator,
+ ccs_object_t *out_object)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_list_iterator) { err = cci_check_error (ccErrBadParam); }
+ if (!out_object ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ if (io_list_iterator->current < cci_array_count (io_list_iterator->list->objects)) {
+ *out_object = cci_array_object_at_index (io_list_iterator->list->objects,
+ io_list_iterator->current);
+ io_list_iterator->current++;
+ } else {
+ err = ccIteratorEnd;
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_list_iterator_update (ccs_list_iterator_t io_list_iterator,
+ ccs_list_action_enum in_action,
+ cc_uint64 in_object_index)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_list_iterator) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ /* When the list changes adjust the current index so that */
+ /* we don't unnecessarily skip or double count items */
+ if (in_action == ccs_list_action_insert) {
+ if (io_list_iterator->current > in_object_index) {
+ io_list_iterator->current++;
+ }
+
+ } else if (in_action == ccs_list_action_remove) {
+ if (io_list_iterator->current >= in_object_index) {
+ io_list_iterator->current--;
+ }
+
+ } else if (in_action == ccs_list_action_push_front) {
+ if (io_list_iterator->current < in_object_index) {
+ io_list_iterator->current++;
+ }
+
+ } else {
+ err = cci_check_error (ccErrBadParam);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
diff --git a/src/ccapi/server/ccs_list_internal.h b/src/ccapi/server/ccs_list_internal.h
new file mode 100644
index 000000000..83320a5eb
--- /dev/null
+++ b/src/ccapi/server/ccs_list_internal.h
@@ -0,0 +1,92 @@
+/*
+ * $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.
+ */
+
+#ifndef CCS_LIST_INTERNAL_H
+#define CCS_LIST_INTERNAL_H
+
+#include "cci_common.h"
+
+struct ccs_list_d;
+typedef struct ccs_list_d *ccs_list_t;
+
+struct ccs_list_iterator_d;
+typedef struct ccs_list_iterator_d *ccs_list_iterator_t;
+
+typedef void *ccs_object_t;
+typedef cc_int32 (*ccs_object_release_t) (ccs_object_t);
+typedef cc_int32 (*ccs_object_compare_identifier_t) (ccs_object_t, cci_identifier_t, cc_uint32 *);
+
+cc_int32 ccs_list_new (ccs_list_t *out_list,
+ cc_int32 in_object_not_found_err,
+ cc_int32 in_iterator_not_found_err,
+ ccs_object_compare_identifier_t in_object_compare_identifier,
+ ccs_object_release_t in_object_release);
+
+cc_int32 ccs_list_release (ccs_list_t io_list);
+
+cc_int32 ccs_list_new_iterator (ccs_list_t io_list,
+ ccs_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_list_release_iterator (ccs_list_t io_list,
+ cci_identifier_t in_identifier);
+
+cc_int32 ccs_list_count (ccs_list_t in_list,
+ cc_uint64 *out_count);
+
+cc_int32 ccs_list_find (ccs_list_t in_list,
+ cci_identifier_t in_identifier,
+ ccs_object_t *out_object);
+
+cc_int32 ccs_list_find_iterator (ccs_list_t in_list,
+ cci_identifier_t in_identifier,
+ ccs_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_list_add (ccs_list_t io_list,
+ ccs_object_t in_object);
+
+cc_int32 ccs_list_remove (ccs_list_t io_list,
+ cci_identifier_t in_identifier);
+
+cc_int32 ccs_list_push_front (ccs_list_t io_list,
+ cci_identifier_t in_identifier);
+
+
+cc_int32 ccs_list_iterator_write (ccs_list_iterator_t in_list_iterator,
+ cci_stream_t in_stream);
+
+cc_int32 ccs_list_iterator_clone (ccs_list_iterator_t in_list_iterator,
+ ccs_list_iterator_t *out_list_iterator);
+
+cc_int32 ccs_list_iterator_current (ccs_list_iterator_t io_list_iterator,
+ ccs_object_t *out_object);
+
+cc_int32 ccs_list_iterator_next (ccs_list_iterator_t io_list_iterator,
+ ccs_object_t *out_object);
+
+cc_int32 ccs_list_iterator_release (ccs_list_iterator_t io_list_iterator);
+
+
+#endif /* CCS_LIST_INTERNAL_H */
diff --git a/src/ccapi/server/ccs_lock.c b/src/ccapi/server/ccs_lock.c
new file mode 100644
index 000000000..939da5e12
--- /dev/null
+++ b/src/ccapi/server/ccs_lock.c
@@ -0,0 +1,245 @@
+/*
+ * $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"
+
+struct ccs_lock_d {
+ cc_uint32 type;
+ cc_uint32 pending;
+ cc_int32 invalid_object_err;
+ ccs_pipe_t client_pipe;
+ ccs_pipe_t reply_pipe;
+};
+
+struct ccs_lock_d ccs_lock_initializer = { 0, 1, 1, NULL, NULL };
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_new (ccs_lock_t *out_lock,
+ cc_uint32 in_type,
+ cc_int32 in_invalid_object_err,
+ ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe)
+{
+ cc_int32 err = ccNoError;
+ ccs_lock_t lock = NULL;
+
+ if (!out_lock ) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
+
+ if (in_type != cc_lock_read &&
+ in_type != cc_lock_write &&
+ in_type != cc_lock_upgrade &&
+ in_type != cc_lock_downgrade) {
+ err = cci_check_error (ccErrBadLockType);
+ }
+
+ if (!err) {
+ lock = malloc (sizeof (*lock));
+ if (lock) {
+ *lock = ccs_lock_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ err = ccs_pipe_copy (&lock->client_pipe, in_client_pipe);
+ }
+
+ if (!err) {
+ err = ccs_pipe_copy (&lock->reply_pipe, in_reply_pipe);
+ }
+
+ if (!err) {
+ lock->type = in_type;
+ lock->invalid_object_err = in_invalid_object_err;
+
+ *out_lock = lock;
+ lock = NULL;
+ }
+
+ ccs_lock_release (lock);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_release (ccs_lock_t io_lock)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_lock) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err && io_lock->pending) {
+ err = ccs_server_send_reply (io_lock->reply_pipe,
+ io_lock->invalid_object_err, NULL);
+ }
+
+ if (!err) {
+ ccs_pipe_release (io_lock->client_pipe);
+ ccs_pipe_release (io_lock->reply_pipe);
+ free (io_lock);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_grant_lock (ccs_lock_t io_lock)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_lock) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ if (io_lock->pending) {
+ err = ccs_server_send_reply (io_lock->reply_pipe, err, NULL);
+
+ if (!err) {
+ ccs_pipe_release (io_lock->reply_pipe);
+ io_lock->pending = 0;
+ io_lock->reply_pipe = NULL;
+ }
+ } else {
+ cci_debug_printf ("WARNING %s() called on non-pending lock!",
+ __FUNCTION__);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_uint32 ccs_lock_is_pending (ccs_lock_t in_lock,
+ cc_uint32 *out_pending)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_lock ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_pending) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_pending = in_lock->pending;
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_type (ccs_lock_t in_lock,
+ cc_uint32 *out_lock_type)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_lock ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_lock_type) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_lock_type = in_lock->type;
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_is_read_lock (ccs_lock_t in_lock,
+ cc_uint32 *out_is_read_lock)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_lock ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_is_read_lock) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_is_read_lock = (in_lock->type == cc_lock_read ||
+ in_lock->type == cc_lock_downgrade);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_is_write_lock (ccs_lock_t in_lock,
+ cc_uint32 *out_is_write_lock)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_lock ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_is_write_lock) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_is_write_lock = (in_lock->type == cc_lock_write ||
+ in_lock->type == cc_lock_upgrade);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_is_for_client (ccs_lock_t in_lock,
+ ccs_pipe_t in_client_pipe,
+ cc_uint32 *out_is_for_client)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_lock ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_is_for_client ) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_pipe_compare (in_lock->client_pipe, in_client_pipe,
+ out_is_for_client);
+ }
+
+ return cci_check_error (err);
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_client (ccs_lock_t in_lock,
+ ccs_pipe_t *out_client_pipe)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_lock ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_client_pipe) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_client_pipe = in_lock->client_pipe;
+ }
+
+ return cci_check_error (err);
+}
diff --git a/src/ccapi/server/ccs_lock.h b/src/ccapi/server/ccs_lock.h
new file mode 100644
index 000000000..197f5d50d
--- /dev/null
+++ b/src/ccapi/server/ccs_lock.h
@@ -0,0 +1,61 @@
+/*
+ * $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.
+ */
+
+#ifndef CCS_LOCK_H
+#define CCS_LOCK_H
+
+#include "ccs_types.h"
+
+cc_int32 ccs_lock_new (ccs_lock_t *out_lock,
+ cc_uint32 in_type,
+ cc_int32 in_invalid_object_err,
+ ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe);
+
+cc_int32 ccs_lock_release (ccs_lock_t io_lock);
+
+cc_int32 ccs_lock_grant_lock (ccs_lock_t io_lock);
+
+cc_uint32 ccs_lock_is_pending (ccs_lock_t in_lock,
+ cc_uint32 *out_pending);
+
+cc_int32 ccs_lock_type (ccs_lock_t in_lock,
+ cc_uint32 *out_lock_type);
+
+cc_int32 ccs_lock_is_read_lock (ccs_lock_t in_lock,
+ cc_uint32 *out_is_read_lock);
+
+cc_int32 ccs_lock_is_write_lock (ccs_lock_t in_lock,
+ cc_uint32 *out_is_write_lock);
+
+cc_int32 ccs_lock_is_for_client (ccs_lock_t in_lock,
+ ccs_pipe_t in_client_pipe,
+ cc_uint32 *out_is_for_client);
+
+cc_int32 ccs_lock_client (ccs_lock_t in_lock,
+ ccs_pipe_t *out_client_pipe);
+
+#endif /* CCS_LOCK_H */
diff --git a/src/ccapi/server/ccs_lock_state.c b/src/ccapi/server/ccs_lock_state.c
new file mode 100644
index 000000000..f9bb614c2
--- /dev/null
+++ b/src/ccapi/server/ccs_lock_state.c
@@ -0,0 +1,543 @@
+/*
+ * $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"
+
+struct ccs_lock_state_d {
+ cc_int32 invalid_object_err;
+ cc_int32 pending_lock_err;
+ cc_int32 no_lock_err;
+ ccs_lock_array_t locks;
+ cc_uint64 first_pending_lock_index;
+};
+
+struct ccs_lock_state_d ccs_lock_state_initializer = { 1, 1, 1, NULL, 0 };
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_state_new (ccs_lock_state_t *out_lock_state,
+ cc_int32 in_invalid_object_err,
+ cc_int32 in_pending_lock_err,
+ cc_int32 in_no_lock_err)
+{
+ cc_int32 err = ccNoError;
+ ccs_lock_state_t lock_state = NULL;
+
+ if (!out_lock_state) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ lock_state = malloc (sizeof (*lock_state));
+ if (lock_state) {
+ *lock_state = ccs_lock_state_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ err = ccs_lock_array_new (&lock_state->locks);
+ }
+
+ if (!err) {
+ lock_state->invalid_object_err = in_invalid_object_err;
+ lock_state->pending_lock_err = in_pending_lock_err;
+ lock_state->no_lock_err = in_no_lock_err;
+
+ *out_lock_state = lock_state;
+ lock_state = NULL;
+ }
+
+ ccs_lock_state_release (lock_state);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_state_release (ccs_lock_state_t io_lock_state)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_lock_state) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ ccs_lock_array_release (io_lock_state->locks);
+ free (io_lock_state);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_state_allow_read (ccs_lock_state_t in_lock_state,
+ ccs_pipe_t in_client_pipe,
+ cc_uint32 *out_allow_read)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 allow_read = 0;
+
+ if (!in_lock_state ) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!out_allow_read ) { err = cci_check_error (ccErrBadParam); }
+
+ /* A client may read if no other clients have write locks */
+
+ if (!err) {
+ cc_uint64 lock_count = in_lock_state->first_pending_lock_index;
+ if (lock_count == 0) {
+ allow_read = 1;
+ } else {
+ ccs_lock_t lock = ccs_lock_array_object_at_index (in_lock_state->locks, 0);
+ cc_uint32 is_read_lock;
+ cc_uint32 is_for_client;
+
+ err = ccs_lock_is_read_lock (lock, &is_read_lock);
+
+ if (!err) {
+ err = ccs_lock_is_for_client (lock, in_client_pipe, &is_for_client);
+ }
+
+ if (!err) {
+ /* read locks or write lock we own */
+ allow_read = (is_read_lock || is_for_client);
+ }
+ }
+ }
+
+ if (!err) {
+ *out_allow_read = allow_read;
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_state_allow_write (ccs_lock_state_t in_lock_state,
+ ccs_pipe_t in_client_pipe,
+ cc_uint32 *out_allow_write)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 allow_write = 0;
+
+ if (!in_lock_state ) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!out_allow_write ) { err = cci_check_error (ccErrBadParam); }
+
+ /* A client may write if there are no locks or if it has a write lock */
+
+ if (!err) {
+ cc_uint64 lock_count = in_lock_state->first_pending_lock_index;
+ if (lock_count == 0) {
+ allow_write = 1;
+ } else {
+ ccs_lock_t lock = ccs_lock_array_object_at_index (in_lock_state->locks, 0);
+ cc_uint32 is_write_lock = 0;
+ cc_uint32 is_for_client = 0;
+
+ err = ccs_lock_is_write_lock (lock, &is_write_lock);
+
+ if (!err) {
+ err = ccs_lock_is_for_client (lock, in_client_pipe, &is_for_client);
+ }
+
+ if (!err) {
+ allow_write = (is_write_lock && is_for_client);
+ }
+ }
+ }
+
+ if (!err) {
+ *out_allow_write = allow_write;
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_lock_status_add_pending_lock (ccs_lock_state_t io_lock_state,
+ ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ cc_uint32 in_lock_type,
+ cc_uint64 *out_lock_index)
+{
+ cc_int32 err = ccNoError;
+ ccs_lock_t lock = NULL;
+
+ if (!io_lock_state ) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_lock_new (&lock, in_lock_type,
+ io_lock_state->invalid_object_err,
+ in_client_pipe, in_reply_pipe);
+ }
+
+ if (!err) {
+ err = ccs_lock_array_insert (io_lock_state->locks, lock,
+ ccs_lock_array_count (io_lock_state->locks));
+ if (!err) { lock = NULL; /* take ownership */ }
+ }
+
+ if (!err) {
+ *out_lock_index = ccs_lock_array_count (io_lock_state->locks) - 1;
+ }
+
+ ccs_lock_release (lock);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_lock_status_remove_lock (ccs_lock_state_t io_lock_state,
+ cc_uint64 in_lock_index)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_lock_state) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_lock_array_remove (io_lock_state->locks, in_lock_index);
+
+ if (!err && in_lock_index < io_lock_state->first_pending_lock_index) {
+ io_lock_state->first_pending_lock_index--;
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_lock_status_grant_lock (ccs_lock_state_t io_lock_state,
+ cc_uint64 in_pending_lock_index)
+{
+ cc_int32 err = ccNoError;
+ cc_uint64 new_lock_index = 0;
+
+ if (!io_lock_state) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err && in_pending_lock_index < io_lock_state->first_pending_lock_index) {
+ err = cci_check_error (ccErrBadParam);
+ }
+
+ if (!err) {
+ err = ccs_lock_array_move (io_lock_state->locks,
+ in_pending_lock_index,
+ io_lock_state->first_pending_lock_index,
+ &new_lock_index);
+ if (!err) { io_lock_state->first_pending_lock_index++; }
+ }
+
+ if (!err) {
+ ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks,
+ new_lock_index);
+ err = ccs_lock_grant_lock (lock);
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_lock_state_check_pending_lock (ccs_lock_state_t io_lock_state,
+ ccs_pipe_t in_pending_lock_client_pipe,
+ cc_uint32 in_pending_lock_type,
+ cc_uint32 *out_grant_lock)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 is_write_locked = 0;
+ cc_uint32 client_has_lock = 0;
+ cc_uint32 client_lock_type = 0;
+ cc_uint32 grant_lock = 0;
+
+ if (!io_lock_state ) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_pending_lock_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!out_grant_lock ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ cc_uint64 i;
+ cc_uint64 lock_count = io_lock_state->first_pending_lock_index;
+
+ for (i = 0; !err && i < lock_count; i++) {
+ ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i);
+ cc_uint32 lock_type = 0;
+ cc_uint32 lock_is_for_client = 0;
+
+ err = ccs_lock_type (lock, &lock_type);
+
+ if (!err) {
+ err = ccs_lock_is_for_client (lock, in_pending_lock_client_pipe,
+ &lock_is_for_client);
+ }
+
+ if (!err) {
+ if (lock_type == cc_lock_write || lock_type == cc_lock_upgrade) {
+ if (is_write_locked) {
+ cci_debug_printf ("WARNING %s() multiple write locks.",
+ __FUNCTION__);
+ }
+ is_write_locked = 1;
+ }
+
+ if (lock_is_for_client) {
+ if (client_has_lock) {
+ cci_debug_printf ("WARNING %s() client has multiple locks.",
+ __FUNCTION__);
+ }
+ client_has_lock = 1;
+ client_lock_type = lock_type;
+ }
+ }
+ }
+ }
+
+ if (!err) {
+ cc_uint64 lock_count = io_lock_state->first_pending_lock_index;
+
+ if (in_pending_lock_type == cc_lock_write) {
+ if (client_has_lock) {
+ err = cci_check_error (ccErrBadLockType);
+ } else {
+ grant_lock = (lock_count == 0);
+ }
+
+ } else if (in_pending_lock_type == cc_lock_read) {
+ if (client_has_lock) {
+ err = cci_check_error (ccErrBadLockType);
+ } else {
+ grant_lock = !is_write_locked;
+ }
+
+ } else if (in_pending_lock_type == cc_lock_upgrade) {
+ if (!client_has_lock || (client_lock_type != cc_lock_read &&
+ client_lock_type != cc_lock_downgrade)) {
+ err = cci_check_error (ccErrBadLockType);
+ } else {
+ /* don't grant if other clients have read locks */
+ grant_lock = (lock_count == 1);
+ }
+
+ } else if (in_pending_lock_type == cc_lock_downgrade) {
+ if (!client_has_lock || (client_lock_type != cc_lock_write &&
+ client_lock_type != cc_lock_upgrade)) {
+ err = cci_check_error (ccErrBadLockType);
+ } else {
+ /* downgrades can never block */
+ grant_lock = 1;
+ }
+ } else {
+ err = cci_check_error (ccErrBadLockType);
+ }
+ }
+
+ if (!err) {
+ *out_grant_lock = grant_lock;
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_lock_status_try_to_grant_pending_locks (ccs_lock_state_t io_lock_state)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 done = 1;
+
+ if (!io_lock_state) { err = cci_check_error (ccErrBadParam); }
+
+ /* The lock array should now be in one of two states: empty or containing
+ * only read locks because if it contained a write lock we would have just
+ * deleted it. Look at the pending locks and see if we can grant them.
+ * Note that downgrade locks mean we must check all pending locks each pass
+ * since a downgrade lock might be last in the list. */
+
+
+ while (!err && !done) {
+ cc_uint64 i;
+ cc_uint64 count = ccs_lock_array_count (io_lock_state->locks);
+ cc_uint32 granted_lock = 0;
+
+ for (i = io_lock_state->first_pending_lock_index; !err && i < count; i++) {
+ ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i);
+ cc_uint32 lock_type = 0;
+ ccs_pipe_t client_pipe = NULL;
+ cc_uint32 can_grant_lock_now = 0;
+
+ err = ccs_lock_client (lock, &client_pipe);
+
+ if (!err) {
+ err = ccs_lock_type (lock, &lock_type);
+ }
+
+ if (!err) {
+ err = ccs_lock_state_check_pending_lock (io_lock_state, client_pipe,
+ lock_type, &can_grant_lock_now);
+ }
+
+ if (!err && can_grant_lock_now) {
+ err = ccs_lock_status_grant_lock (io_lock_state, i);
+ if (!err) { granted_lock = 1; }
+ }
+ }
+
+ if (!err && !granted_lock) {
+ done = 1;
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_state_add (ccs_lock_state_t io_lock_state,
+ ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ cc_uint32 in_lock_type,
+ cc_uint32 in_block,
+ cc_uint32 *out_will_block)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 can_grant_lock_now = 0;
+ cc_uint32 will_block = 0;
+
+ if (!io_lock_state ) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_will_block ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ /* Sanity check: if there are any pending locks for this client
+ * the client must have timed out waiting for our reply. Remove any
+ * existing pending locks for the client. */
+ cc_uint64 i;
+ cc_uint64 count = ccs_lock_array_count (io_lock_state->locks);
+
+ for (i = io_lock_state->first_pending_lock_index; !err && i < count; i++) {
+ ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i);
+ cc_uint32 has_pending_lock_for_client = 0;
+
+ err = ccs_lock_is_for_client (lock, in_client_pipe, &has_pending_lock_for_client);
+
+ if (!err && has_pending_lock_for_client) {
+ cci_debug_printf ("WARNING %s() removing pending lock for client.", __FUNCTION__);
+ err = ccs_lock_status_remove_lock (io_lock_state, i);
+ }
+ }
+ }
+
+ if (!err) {
+ err = ccs_lock_state_check_pending_lock (io_lock_state, in_client_pipe,
+ in_lock_type, &can_grant_lock_now);
+ }
+
+ if (!err) {
+ if (!can_grant_lock_now && !in_block) {
+ err = cci_check_error (io_lock_state->pending_lock_err);
+
+ } else {
+ cc_uint64 new_lock_index = 0;
+
+ err = ccs_lock_status_add_pending_lock (io_lock_state,
+ in_client_pipe,
+ in_reply_pipe,
+ in_lock_type,
+ &new_lock_index);
+
+ if (!err) {
+ if (can_grant_lock_now) {
+ err = ccs_lock_status_grant_lock (io_lock_state,
+ new_lock_index);
+
+ if (!err && (in_lock_type == cc_lock_downgrade)) {
+ /* downgrades can allow us to grant other locks */
+ err = ccs_lock_status_try_to_grant_pending_locks (io_lock_state);
+ }
+ } else {
+ will_block = 1;
+ }
+ }
+ }
+ }
+
+ if (!err) {
+ *out_will_block = will_block;
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_lock_state_remove (ccs_lock_state_t io_lock_state,
+ ccs_pipe_t in_client_pipe)
+{
+ cc_int32 err = ccNoError;
+ cc_uint32 found_lock = 0;
+
+ if (!io_lock_state ) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ cc_uint64 i;
+ cc_uint64 lock_count = io_lock_state->first_pending_lock_index;
+
+ for (i = 0; !err && i < lock_count; i++) {
+ ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i);
+
+ err = ccs_lock_is_for_client (lock, in_client_pipe, &found_lock);
+
+ if (!err && found_lock) {
+ cci_debug_printf ("%s: Removing lock %p.", __FUNCTION__, lock);
+ err = ccs_lock_status_remove_lock (io_lock_state, i);
+ break;
+ }
+ }
+ }
+
+ if (!err && !found_lock) {
+ err = cci_check_error (io_lock_state->no_lock_err);
+ }
+
+ if (!err) {
+ err = ccs_lock_status_try_to_grant_pending_locks (io_lock_state);
+ }
+
+ return cci_check_error (err);
+}
+
diff --git a/src/ccapi/server/ccs_lock_state.h b/src/ccapi/server/ccs_lock_state.h
new file mode 100644
index 000000000..1918452c6
--- /dev/null
+++ b/src/ccapi/server/ccs_lock_state.h
@@ -0,0 +1,57 @@
+/*
+ * $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.
+ */
+
+#ifndef CCS_LOCK_STATE_H
+#define CCS_LOCK_STATE_H
+
+#include "ccs_types.h"
+
+cc_int32 ccs_lock_state_new (ccs_lock_state_t *out_lock_state,
+ cc_int32 in_invalid_object_err,
+ cc_int32 in_pending_lock_err,
+ cc_int32 in_no_lock_err);
+
+cc_int32 ccs_lock_state_release (ccs_lock_state_t io_lock_state);
+
+cc_int32 ccs_lock_state_allow_read (ccs_lock_state_t in_lock_state,
+ ccs_pipe_t in_client_pipe,
+ cc_uint32 *out_allow_read);
+
+cc_int32 ccs_lock_state_allow_write (ccs_lock_state_t in_lock_state,
+ ccs_pipe_t in_client_pipe,
+ cc_uint32 *out_allow_write);
+
+cc_int32 ccs_lock_state_add (ccs_lock_state_t io_lock_state,
+ ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ cc_uint32 in_lock_type,
+ cc_uint32 in_block,
+ cc_uint32 *out_will_block);
+
+cc_int32 ccs_lock_state_remove (ccs_lock_state_t io_lock_state,
+ ccs_pipe_t in_client_pipe);
+
+#endif /* CCS_LOCK_STATE_H */
diff --git a/src/ccapi/server/ccs_os_pipe.h b/src/ccapi/server/ccs_os_pipe.h
new file mode 100644
index 000000000..57fe64b99
--- /dev/null
+++ b/src/ccapi/server/ccs_os_pipe.h
@@ -0,0 +1,44 @@
+/*
+ * $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.
+ */
+
+#ifndef CCS_OS_PIPE_H
+#define CCS_OS_PIPE_H
+
+#include "ccs_types.h"
+
+inline cc_int32 ccs_os_pipe_copy (ccs_os_pipe_t *out_pipe,
+ ccs_os_pipe_t in_pipe);
+
+inline cc_int32 ccs_os_pipe_release (ccs_os_pipe_t io_pipe);
+
+inline cc_int32 ccs_os_pipe_compare (ccs_os_pipe_t in_pipe,
+ ccs_os_pipe_t in_compare_to_pipe,
+ cc_uint32 *out_equal);
+
+cc_int32 ccs_os_pipe_valid (ccs_os_pipe_t in_pipe);
+
+
+#endif /* CCS_OS_PIPE_H */
diff --git a/src/ccapi/server/ccs_os_server.h b/src/ccapi/server/ccs_os_server.h
new file mode 100644
index 000000000..557ad5905
--- /dev/null
+++ b/src/ccapi/server/ccs_os_server.h
@@ -0,0 +1,35 @@
+/*
+ * $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.
+ */
+
+#ifndef CCS_OS_SERVER_H
+#define CCS_OS_SERVER_H
+
+#include "ccs_types.h"
+
+cc_int32 ccs_os_server_send_reply (ccs_pipe_t in_reply_pipe,
+ cci_stream_t in_reply_stream);
+
+#endif /* CCS_OS_SERVER_H */
diff --git a/src/ccapi/server/ccs_pipe.c b/src/ccapi/server/ccs_pipe.c
new file mode 100644
index 000000000..d7521b57f
--- /dev/null
+++ b/src/ccapi/server/ccs_pipe.c
@@ -0,0 +1,163 @@
+/*
+ * $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 "ccs_os_pipe.h"
+
+struct ccs_pipe_d {
+ ccs_os_pipe_t os_pipe;
+};
+
+struct ccs_pipe_d ccs_pipe_initializer = { CCS_OS_PIPE_NULL };
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_pipe_new (ccs_pipe_t *out_pipe,
+ ccs_os_pipe_t in_os_pipe)
+{
+ cc_int32 err = ccNoError;
+ ccs_pipe_t new_pipe = NULL;
+
+ if (!out_pipe ) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_os_pipe_valid (in_os_pipe)) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ new_pipe = malloc (sizeof (*new_pipe));
+ if (new_pipe) {
+ *new_pipe = ccs_pipe_initializer;
+ } else {
+ err = cci_check_error (ccErrNoMem);
+ }
+ }
+
+ if (!err) {
+ err = ccs_os_pipe_copy (&new_pipe->os_pipe, in_os_pipe);
+ }
+
+ if (!err) {
+ *out_pipe = new_pipe;
+ new_pipe = NULL;
+ }
+
+ ccs_pipe_release (new_pipe);
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_pipe_release (ccs_pipe_t io_pipe)
+{
+ cc_int32 err = ccNoError;
+
+ if (!io_pipe) { err = ccErrBadParam; }
+
+ if (!err) {
+ ccs_os_pipe_release (io_pipe->os_pipe);
+ free (io_pipe);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_pipe_copy (ccs_pipe_t *out_pipe,
+ ccs_pipe_t in_pipe)
+{
+ cc_int32 err = ccNoError;
+
+ if (!out_pipe) { err = cci_check_error (ccErrBadParam); }
+ if (!in_pipe ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_pipe_new (out_pipe, in_pipe->os_pipe);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_pipe_compare (ccs_pipe_t in_pipe,
+ ccs_pipe_t in_compare_to_pipe,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+
+ if (!in_pipe ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_compare_to_pipe) { err = cci_check_error (ccErrBadParam); }
+ if (!out_equal ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_os_pipe_compare (in_pipe->os_pipe,
+ in_compare_to_pipe->os_pipe,
+ out_equal);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_pipe_compare_to_os_pipe (ccs_pipe_t in_pipe,
+ ccs_os_pipe_t in_compare_to_os_pipe,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+
+ if (in_pipe) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = ccs_os_pipe_compare (in_pipe->os_pipe,
+ in_compare_to_os_pipe,
+ out_equal);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_pipe_valid (ccs_pipe_t in_pipe)
+{
+ if (in_pipe) {
+ return ccs_os_pipe_valid (in_pipe->os_pipe);
+ } else {
+ return 0;
+ }
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+ccs_os_pipe_t ccs_pipe_os (ccs_pipe_t in_pipe)
+{
+ if (in_pipe) {
+ return in_pipe->os_pipe;
+ } else {
+ return CCS_OS_PIPE_NULL;
+ }
+}
diff --git a/src/ccapi/server/ccs_pipe.h b/src/ccapi/server/ccs_pipe.h
new file mode 100644
index 000000000..7f3c0d40d
--- /dev/null
+++ b/src/ccapi/server/ccs_pipe.h
@@ -0,0 +1,52 @@
+/*
+ * $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.
+ */
+
+#ifndef CCS_PIPE_H
+#define CCS_PIPE_H
+
+#include "ccs_types.h"
+
+cc_int32 ccs_pipe_new (ccs_pipe_t *out_pipe,
+ ccs_os_pipe_t in_os_pipe);
+
+cc_int32 ccs_pipe_copy (ccs_pipe_t *out_pipe,
+ ccs_pipe_t in_pipe);
+
+inline cc_int32 ccs_pipe_release (ccs_pipe_t io_pipe);
+
+cc_int32 ccs_pipe_compare (ccs_pipe_t in_pipe,
+ ccs_pipe_t in_compare_to_pipe,
+ cc_uint32 *out_equal);
+
+cc_int32 ccs_pipe_compare_to_os_pipe (ccs_pipe_t in_pipe,
+ ccs_os_pipe_t in_compare_to_os_pipe,
+ cc_uint32 *out_equal);
+
+cc_int32 ccs_pipe_valid (ccs_pipe_t in_pipe);
+
+ccs_os_pipe_t ccs_pipe_os (ccs_pipe_t in_pipe);
+
+#endif /* CCS_PIPE_H */
diff --git a/src/ccapi/server/ccs_server.c b/src/ccapi/server/ccs_server.c
new file mode 100644
index 000000000..b7d3be4b1
--- /dev/null
+++ b/src/ccapi/server/ccs_server.c
@@ -0,0 +1,333 @@
+/*
+ * $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 "ccs_os_server.h"
+
+/* Server Globals: */
+
+cci_uuid_string_t g_server_id = NULL;
+ccs_cache_collection_t g_cache_collection = NULL;
+ccs_pipe_array_t g_client_pipe_array = NULL;
+
+/* ------------------------------------------------------------------------ */
+
+ cc_int32 ccs_server_initialize (void)
+{
+ cc_int32 err = ccNoError;
+
+ if (!err) {
+ err = cci_identifier_new_uuid (&g_server_id);
+ }
+
+ if (!err) {
+ err = ccs_cache_collection_new (&g_cache_collection);
+ }
+
+ if (!err) {
+ err = ccs_pipe_array_new (&g_client_pipe_array);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+ cc_int32 ccs_server_cleanup (void)
+{
+ cc_int32 err = ccNoError;
+
+ if (!err) {
+ free (g_server_id);
+ cci_check_error (ccs_cache_collection_release (g_cache_collection));
+ cci_check_error (ccs_pipe_array_release (g_client_pipe_array));
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_server_new_identifier (cci_identifier_t *out_identifier)
+{
+ return cci_check_error (cci_identifier_new (out_identifier,
+ g_server_id));
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_server_add_client (ccs_os_pipe_t in_connection_os_pipe)
+{
+ cc_int32 err = ccNoError;
+ ccs_pipe_t connection_pipe = NULL;
+
+ if (!err) {
+ err = ccs_pipe_new (&connection_pipe, in_connection_os_pipe);
+ }
+
+ if (!err) {
+ cci_debug_printf ("%s: Adding client %p.", __FUNCTION__, connection_pipe);
+ err = ccs_pipe_array_insert (g_client_pipe_array,
+ connection_pipe,
+ ccs_pipe_array_count (g_client_pipe_array));
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_server_remove_client (ccs_os_pipe_t in_connection_os_pipe)
+{
+ cc_int32 err = ccNoError;
+
+ if (!err) {
+ cc_uint64 i;
+ cc_uint64 count = ccs_pipe_array_count (g_client_pipe_array);
+ cc_uint32 found = 0;
+
+ for (i = 0; !err && i < count; i++) {
+ ccs_pipe_t client = ccs_pipe_array_object_at_index (g_client_pipe_array, i);
+
+ err = ccs_pipe_compare_to_os_pipe (client, in_connection_os_pipe, &found);
+
+ if (!err && found) {
+ cci_debug_printf ("%s: Removing client %p.", __FUNCTION__, client);
+ err = ccs_pipe_array_remove (g_client_pipe_array, i);
+ break;
+ }
+ }
+
+ if (!err && !found) {
+ cci_debug_printf ("WARNING %s() didn't find client in client list.",
+ __FUNCTION__);
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+static cc_int32 ccs_server_request_demux (ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ ccs_cache_collection_t in_cache_collection,
+ enum cci_msg_id_t in_request_name,
+ cci_identifier_t in_request_identifier,
+ cci_stream_t in_request_data,
+ cc_uint32 *out_reply_immediately,
+ cci_stream_t *out_reply_data)
+{
+ cc_int32 err = ccNoError;
+
+ if (!ccs_pipe_valid (in_reply_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request_data ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_reply_immediately ) { err = cci_check_error (ccErrBadParam); }
+ if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ if (in_request_name > cci_context_first_msg_id &&
+ in_request_name < cci_context_last_msg_id) {
+ /* Note: context identifier doesn't need to match.
+ * Client just uses the identifier to detect server relaunch. */
+
+ if (!err) {
+ err = ccs_cache_collection_handle_message (in_client_pipe,
+ in_reply_pipe,
+ in_cache_collection,
+ in_request_name,
+ in_request_data,
+ out_reply_immediately,
+ out_reply_data);
+ }
+
+ } else if (in_request_name > cci_ccache_first_msg_id &&
+ in_request_name < cci_ccache_last_msg_id) {
+ ccs_ccache_t ccache = NULL;
+
+ err = ccs_cache_collection_find_ccache (in_cache_collection,
+ in_request_identifier,
+ &ccache);
+
+ if (!err) {
+ err = ccs_ccache_handle_message (in_client_pipe,
+ in_reply_pipe,
+ ccache,
+ in_cache_collection,
+ in_request_name,
+ in_request_data,
+ out_reply_immediately,
+ out_reply_data);
+ }
+
+ } else if (in_request_name > cci_ccache_iterator_first_msg_id &&
+ in_request_name < cci_ccache_iterator_last_msg_id) {
+ ccs_ccache_iterator_t ccache_iterator = NULL;
+
+ err = ccs_cache_collection_find_ccache_iterator (in_cache_collection,
+ in_request_identifier,
+ &ccache_iterator);
+
+ if (!err) {
+ err = ccs_ccache_iterator_handle_message (ccache_iterator,
+ in_cache_collection,
+ in_request_name,
+ in_request_data,
+ out_reply_data);
+ }
+
+ if (!err) {
+ *out_reply_immediately = 1; /* can't block */
+ }
+
+ } else if (in_request_name > cci_credentials_iterator_first_msg_id &&
+ in_request_name < cci_credentials_iterator_last_msg_id) {
+ ccs_credentials_iterator_t credentials_iterator = NULL;
+ ccs_ccache_t ccache = NULL;
+
+ err = ccs_cache_collection_find_credentials_iterator (in_cache_collection,
+ in_request_identifier,
+ &ccache,
+ &credentials_iterator);
+
+ if (!err) {
+ err = ccs_credentials_iterator_handle_message (credentials_iterator,
+ ccache,
+ in_request_name,
+ in_request_data,
+ out_reply_data);
+ }
+
+ if (!err) {
+ *out_reply_immediately = 1; /* can't block */
+ }
+
+ } else {
+ err = ccErrBadInternalMessage;
+ }
+ }
+
+ return cci_check_error (err);
+}
+
+#pragma mark -
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_server_handle_request (ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ cci_stream_t in_request)
+{
+ cc_int32 err = ccNoError;
+ enum cci_msg_id_t request_name = 0;
+ cci_identifier_t request_identifier = NULL;
+ cc_uint32 reply_immediately = 1;
+ cci_stream_t reply_data = NULL;
+
+ if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
+ if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
+ if (!in_request ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_message_read_request_header (in_request,
+ &request_name,
+ &request_identifier);
+ }
+
+ if (!err) {
+ cc_uint32 server_err = 0;
+ cc_uint32 valid = 0;
+ ccs_cache_collection_t cache_collection = g_cache_collection;
+
+ server_err = cci_identifier_is_for_server (request_identifier,
+ g_server_id,
+ &valid);
+
+ if (!server_err && !valid) {
+ server_err = cci_message_invalid_object_err (request_name);
+ }
+
+ if (!server_err) {
+
+ /* Monolithic server implementation would need to select
+ * cache collection here. Currently we only support per-user
+ * servers so we always use the same cache collection. */
+
+ server_err = ccs_server_request_demux (in_client_pipe,
+ in_reply_pipe,
+ cache_collection,
+ request_name,
+ request_identifier,
+ in_request,
+ &reply_immediately,
+ &reply_data);
+ }
+
+ if (server_err || reply_immediately) {
+ err = ccs_server_send_reply (in_reply_pipe, server_err, reply_data);
+ }
+ }
+
+ cci_identifier_release (request_identifier);
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_server_send_reply (ccs_pipe_t in_reply_pipe,
+ cc_int32 in_reply_err,
+ cci_stream_t in_reply_data)
+{
+ cc_int32 err = ccNoError;
+ cci_stream_t reply = NULL;
+
+ if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ err = cci_message_new_reply_header (&reply, in_reply_err);
+ }
+
+ if (!err && in_reply_data && cci_stream_size (in_reply_data) > 0) {
+ err = cci_stream_write (in_reply_data,
+ cci_stream_data (in_reply_data),
+ cci_stream_size (in_reply_data));
+ }
+
+ if (!err) {
+ err = ccs_os_server_send_reply (in_reply_pipe, reply);
+ }
+
+ cci_stream_release (reply);
+
+ return cci_check_error (err);
+}
diff --git a/src/ccapi/server/ccs_server.h b/src/ccapi/server/ccs_server.h
new file mode 100644
index 000000000..713271072
--- /dev/null
+++ b/src/ccapi/server/ccs_server.h
@@ -0,0 +1,50 @@
+/*
+ * $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.
+ */
+
+#ifndef CCS_SERVER_H
+#define CCS_SERVER_H
+
+#include "ccs_types.h"
+
+cc_int32 ccs_server_initialize (void);
+
+cc_int32 ccs_server_cleanup (void);
+
+cc_int32 ccs_server_new_identifier (cci_identifier_t *out_identifier);
+
+cc_int32 ccs_server_add_client (ccs_os_pipe_t in_connection_os_pipe);
+
+cc_int32 ccs_server_remove_client (ccs_os_pipe_t in_connection_os_pipe);
+
+cc_int32 ccs_server_handle_request (ccs_pipe_t in_client_pipe,
+ ccs_pipe_t in_reply_pipe,
+ cci_stream_t in_request);
+
+cc_int32 ccs_server_send_reply (ccs_pipe_t in_reply_pipe,
+ cc_int32 in_reply_err,
+ cci_stream_t in_reply_data);
+
+#endif /* CCS_SERVER_H */
diff --git a/src/ccapi/server/ccs_types.h b/src/ccapi/server/ccs_types.h
new file mode 100644
index 000000000..f96e8d39d
--- /dev/null
+++ b/src/ccapi/server/ccs_types.h
@@ -0,0 +1,93 @@
+/*
+ * $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.
+ */
+
+#ifndef CCS_TYPES_H
+#define CCS_TYPES_H
+
+#include "cci_types.h"
+
+struct cci_array_d;
+
+typedef struct cci_array_d *ccs_pipe_array_t;
+
+typedef struct cci_array_d *ccs_lock_array_t;
+
+#pragma mark -
+
+/* ccs_os_pipe_t is IPC-specific so it's special cased here */
+
+#if TARGET_OS_MAC
+#include <mach/mach_types.h>
+typedef mach_port_t ccs_os_pipe_t; /* Mach IPC port */
+#define CCS_OS_PIPE_NULL MACH_PORT_NULL
+
+#else
+typedef int ccs_os_pipe_t; /* Unix domain socket */
+#define CCS_OS_PIPE_NULL -1
+
+#endif
+
+#pragma mark -
+
+struct ccs_pipe_d;
+typedef struct ccs_pipe_d *ccs_pipe_t;
+
+struct ccs_list_d;
+struct ccs_list_iterator_d;
+
+typedef struct ccs_list_d *ccs_cache_collection_list_t;
+
+typedef struct ccs_list_d *ccs_ccache_list_t;
+typedef struct ccs_list_iterator_d *ccs_ccache_list_iterator_t;
+
+typedef struct ccs_list_d *ccs_credentials_list_t;
+typedef struct ccs_list_iterator_d *ccs_credentials_list_iterator_t;
+
+#pragma mark -
+
+struct ccs_client_d;
+typedef struct ccs_client_d *ccs_client_t;
+
+struct ccs_lock_d;
+typedef struct ccs_lock_d *ccs_lock_t;
+
+struct ccs_lock_state_d;
+typedef struct ccs_lock_state_d *ccs_lock_state_t;
+
+struct ccs_credentials_d;
+typedef struct ccs_credentials_d *ccs_credentials_t;
+
+typedef ccs_credentials_list_iterator_t ccs_credentials_iterator_t;
+
+struct ccs_ccache_d;
+typedef struct ccs_ccache_d *ccs_ccache_t;
+
+typedef ccs_ccache_list_iterator_t ccs_ccache_iterator_t;
+
+struct ccs_cache_collection_d;
+typedef struct ccs_cache_collection_d *ccs_cache_collection_t;
+
+#endif /* CCS_TYPES_H */
diff --git a/src/ccapi/server/mac/CCacheServerInfo.plist b/src/ccapi/server/mac/CCacheServerInfo.plist
new file mode 100644
index 000000000..e03d5f3ff
--- /dev/null
+++ b/src/ccapi/server/mac/CCacheServerInfo.plist
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>CCacheServer</string>
+ <key>CFBundleGetInfoString</key>
+ <string>4.1</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>edu.mit.Kerberos.CCacheServer</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>Kerberos Credentials Cache Server</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>CCSa</string>
+ <key>CFBundleVersion</key>
+ <string>0.0.1d1</string>
+ <key>CFBundleShortVersionString</key>
+ <string>5.5</string>
+ <key>CFBundleGetInfoString</key>
+ <string>5.5 Copyright MIT</string>
+ <key>KfMDisplayVersion</key>
+ <string>5.5 Copyright MIT</string>
+ <key>KfMDisplayCopyright</key>
+ <string>Copyright MIT</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>5.5 Copyright MIT</string>
+ <key>LSBackgroundOnly</key>
+ <string>1</string>
+</dict>
+</plist>
diff --git a/src/ccapi/server/mac/ccs_os_pipe.c b/src/ccapi/server/mac/ccs_os_pipe.c
new file mode 100644
index 000000000..c3e7542a6
--- /dev/null
+++ b/src/ccapi/server/mac/ccs_os_pipe.c
@@ -0,0 +1,79 @@
+/*
+ * $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 "ccs_os_pipe.h"
+#include <mach/port.h>
+
+/* On Mac OS X ccs_os_pipe_t is a mach_port_t */
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_os_pipe_copy (ccs_os_pipe_t *out_pipe,
+ ccs_os_pipe_t in_pipe)
+{
+ cc_int32 err = ccNoError;
+
+ if (!out_pipe) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_pipe = in_pipe;
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_os_pipe_release (ccs_os_pipe_t io_pipe)
+{
+ return ccNoError;
+}
+
+/* ------------------------------------------------------------------------ */
+
+inline cc_int32 ccs_os_pipe_compare (ccs_os_pipe_t in_pipe,
+ ccs_os_pipe_t in_compare_to_pipe,
+ cc_uint32 *out_equal)
+{
+ cc_int32 err = ccNoError;
+
+ if (!out_equal) { err = cci_check_error (ccErrBadParam); }
+
+ if (!err) {
+ *out_equal = (in_pipe == in_compare_to_pipe);
+ }
+
+ return cci_check_error (err);
+}
+
+/* ------------------------------------------------------------------------ */
+
+cc_int32 ccs_os_pipe_valid (ccs_os_pipe_t in_pipe)
+{
+ return MACH_PORT_VALID (in_pipe);
+}
+
diff --git a/src/ccapi/server/mac/edu.mit.Kerberos.CCacheServer.plist b/src/ccapi/server/mac/edu.mit.Kerberos.CCacheServer.plist
new file mode 100644
index 000000000..42e7f2720
--- /dev/null
+++ b/src/ccapi/server/mac/edu.mit.Kerberos.CCacheServer.plist
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>edu.mit.Kerberos.CCacheServer</string>
+ <key>Program</key>
+ <string>/System/Library/CoreServices/CCacheServer.app/Contents/MacOS/CCacheServer</string>
+ <key>MachServices</key>
+ <dict>
+ <key>edu.mit.Kerberos.CCacheServer.ipcService</key>
+ <true/>
+ </dict>
+ <key>OnDemand</key>
+ <true/>
+</dict>
+</plist>
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);
+}