xref: /freebsd/crypto/krb5/src/ccapi/server/ccs_callback.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* ccapi/server/ccs_callback.c */
2 /*
3  * Copyright 2006 Massachusetts Institute of Technology.
4  * All Rights Reserved.
5  *
6  * Export of this software from the United States of America may
7  * require a specific license from the United States Government.
8  * It is the responsibility of any person or organization contemplating
9  * export to obtain such a license before exporting.
10  *
11  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
12  * distribute this software and its documentation for any purpose and
13  * without fee is hereby granted, provided that the above copyright
14  * notice appear in all copies and that both that copyright notice and
15  * this permission notice appear in supporting documentation, and that
16  * the name of M.I.T. not be used in advertising or publicity pertaining
17  * to distribution of the software without specific, written prior
18  * permission.  Furthermore if you modify this software you must label
19  * your software as modified software and not distribute it in such a
20  * fashion that it might be confused with the original M.I.T. software.
21  * M.I.T. makes no representations about the suitability of
22  * this software for any purpose.  It is provided "as is" without express
23  * or implied warranty.
24  */
25 
26 #include "ccs_common.h"
27 
28 struct ccs_callback_d {
29     cc_int32 pending;
30     cc_int32 invalid_object_err;
31     ccs_pipe_t client_pipe;
32     ccs_pipe_t reply_pipe;
33     ccs_callback_owner_t owner; /* pointer to owner */
34     ccs_callback_owner_invalidate_t owner_invalidate;
35 };
36 
37 struct ccs_callback_d ccs_callback_initializer = { 1, 1, CCS_PIPE_NULL, CCS_PIPE_NULL, NULL, NULL };
38 
39 /* ------------------------------------------------------------------------ */
40 
ccs_callback_new(ccs_callback_t * out_callback,cc_int32 in_invalid_object_err,ccs_pipe_t in_client_pipe,ccs_pipe_t in_reply_pipe,ccs_callback_owner_t in_owner,ccs_callback_owner_invalidate_t in_owner_invalidate_function)41 cc_int32 ccs_callback_new (ccs_callback_t                  *out_callback,
42 			   cc_int32                         in_invalid_object_err,
43 			   ccs_pipe_t                       in_client_pipe,
44 			   ccs_pipe_t                       in_reply_pipe,
45 			   ccs_callback_owner_t             in_owner,
46 			   ccs_callback_owner_invalidate_t  in_owner_invalidate_function)
47 {
48     cc_int32 err = ccNoError;
49     ccs_callback_t callback = NULL;
50     ccs_client_t client = NULL;
51 
52     if (!out_callback                   ) { err = cci_check_error (ccErrBadParam); }
53     if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
54     if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); }
55     if (!in_owner                       ) { err = cci_check_error (ccErrBadParam); }
56     if (!in_owner_invalidate_function   ) { err = cci_check_error (ccErrBadParam); }
57 
58     if (!err) {
59         callback = malloc (sizeof (*callback));
60         if (callback) {
61             *callback = ccs_callback_initializer;
62         } else {
63             err = cci_check_error (ccErrNoMem);
64         }
65     }
66 
67     if (!err) {
68         err = ccs_server_client_for_pipe (in_client_pipe, &client);
69     }
70 
71     if (!err) {
72 	err = ccs_pipe_copy (&callback->client_pipe, in_client_pipe);
73     }
74 
75     if (!err) {
76 	err = ccs_pipe_copy (&callback->reply_pipe, in_reply_pipe);
77     }
78 
79     if (!err) {
80         callback->client_pipe = in_client_pipe;
81         callback->reply_pipe = in_reply_pipe;
82         callback->invalid_object_err = in_invalid_object_err;
83         callback->owner = in_owner;
84         callback->owner_invalidate = in_owner_invalidate_function;
85 
86         err = ccs_client_add_callback (client, callback);
87     }
88 
89     if (!err) {
90         *out_callback = callback;
91         callback = NULL;
92     }
93 
94     ccs_callback_release (callback);
95 
96     return cci_check_error (err);
97 }
98 
99 /* ------------------------------------------------------------------------ */
100 
ccs_callback_release(ccs_callback_t io_callback)101 cc_int32 ccs_callback_release (ccs_callback_t io_callback)
102 {
103     cc_int32 err = ccNoError;
104 
105     if (!err && io_callback) {
106 	ccs_client_t client = NULL;
107 
108 	if (io_callback->pending) {
109 	    err = ccs_server_send_reply (io_callback->reply_pipe,
110 					 io_callback->invalid_object_err, NULL);
111 
112 	    io_callback->pending = 0;
113 	}
114 
115 	if (!err) {
116 	    err = ccs_server_client_for_pipe (io_callback->client_pipe, &client);
117 	}
118 
119 	if (!err && client) {
120 	    /* if client object still has a reference to us, remove it */
121 	    err = ccs_client_remove_callback (client, io_callback);
122 	}
123 
124 	if (!err) {
125 	    ccs_pipe_release (io_callback->client_pipe);
126 	    ccs_pipe_release (io_callback->reply_pipe);
127 	    free (io_callback);
128 	}
129     }
130 
131     return cci_check_error (err);
132 }
133 
134 /* ------------------------------------------------------------------------ */
135 
ccs_callback_invalidate(ccs_callback_t io_callback)136 cc_int32 ccs_callback_invalidate (ccs_callback_t io_callback)
137 {
138     cc_int32 err = ccNoError;
139 
140     if (!io_callback) { err = cci_check_error (ccErrBadParam); }
141 
142     if (!err) {
143         io_callback->pending = 0; /* client is dead, don't try to talk to it */
144 	if (io_callback->owner_invalidate) {
145 	    err = io_callback->owner_invalidate (io_callback->owner, io_callback);
146 	} else {
147 	    cci_debug_printf ("WARNING %s() unable to notify callback owner!",
148 			      __FUNCTION__);
149 	}
150     }
151 
152     return cci_check_error (err);
153 }
154 
155 /* ------------------------------------------------------------------------ */
156 
ccs_callback_reply_to_client(ccs_callback_t io_callback,k5_ipc_stream in_stream)157 cc_int32 ccs_callback_reply_to_client (ccs_callback_t io_callback,
158 				       k5_ipc_stream   in_stream)
159 {
160     cc_int32 err = ccNoError;
161 
162     if (!io_callback) { err = cci_check_error (ccErrBadParam); }
163 
164     if (!err) {
165         if (io_callback->pending) {
166 	    cci_debug_printf ("%s: callback %p replying to client.", __FUNCTION__, io_callback);
167 
168             err = ccs_server_send_reply (io_callback->reply_pipe, err, in_stream);
169 
170             if (err) {
171                 cci_debug_printf ("WARNING %s() called on a lock belonging to a dead client!",
172                                   __FUNCTION__);
173             }
174 
175             io_callback->pending = 0;
176         } else {
177             cci_debug_printf ("WARNING %s() called on non-pending callback!",
178                               __FUNCTION__);
179         }
180     }
181 
182     return cci_check_error (err);
183 }
184 
185 /* ------------------------------------------------------------------------ */
186 
ccs_callback_is_pending(ccs_callback_t in_callback,cc_uint32 * out_pending)187 cc_uint32 ccs_callback_is_pending (ccs_callback_t  in_callback,
188 				   cc_uint32      *out_pending)
189 {
190     cc_int32 err = ccNoError;
191 
192     if (!in_callback) { err = cci_check_error (ccErrBadParam); }
193     if (!out_pending) { err = cci_check_error (ccErrBadParam); }
194 
195     if (!err) {
196         *out_pending = in_callback->pending;
197     }
198 
199     return cci_check_error (err);
200 }
201 
202 /* ------------------------------------------------------------------------ */
203 
ccs_callback_is_for_client_pipe(ccs_callback_t in_callback,ccs_pipe_t in_client_pipe,cc_uint32 * out_is_for_client_pipe)204 cc_int32 ccs_callback_is_for_client_pipe (ccs_callback_t  in_callback,
205 					  ccs_pipe_t      in_client_pipe,
206 					  cc_uint32      *out_is_for_client_pipe)
207 {
208     cc_int32 err = ccNoError;
209 
210     if (!in_callback                    ) { err = cci_check_error (ccErrBadParam); }
211     if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); }
212     if (!out_is_for_client_pipe         ) { err = cci_check_error (ccErrBadParam); }
213 
214     if (!err) {
215         err = ccs_pipe_compare (in_callback->client_pipe, in_client_pipe,
216                                 out_is_for_client_pipe);
217     }
218 
219     return cci_check_error (err);
220 }
221 
222 
223 /* ------------------------------------------------------------------------ */
224 
ccs_callback_client_pipe(ccs_callback_t in_callback,ccs_pipe_t * out_client_pipe)225 cc_int32 ccs_callback_client_pipe (ccs_callback_t  in_callback,
226 				   ccs_pipe_t     *out_client_pipe)
227 {
228     cc_int32 err = ccNoError;
229 
230     if (!in_callback    ) { err = cci_check_error (ccErrBadParam); }
231     if (!out_client_pipe) { err = cci_check_error (ccErrBadParam); }
232 
233     if (!err) {
234         *out_client_pipe = in_callback->client_pipe;
235     }
236 
237     return cci_check_error (err);
238 }
239